迭代

2017-06-12 51 views
0

的Food101 SqueezeNet Caffe2数我想在Caffe2使用squeezenet的ETH Food101数据集进行分类。我的模型从模型动物园进口和我做了两个类型的修改的模型:迭代

1)改变的最后一层的尺寸以具有101个输出

2)从数据库中的图像是在NHWC形式和我刚刚翻转权重的尺寸匹配。 (我计划改变这种情况)

Food101数据集有75,000个图像用于训练,我目前使用的批量大小为128,初始学习率为-0.01,伽玛值为0.999,步长为1.我注意到对于网络的第一次2000次迭代,精度在1/128左右徘徊,这需要一个小时左右才能完成。

我添加了所有的权重model.params这样他们就可以在梯度下降得到更新(除数据),并重新初始化所有的权重为Xavier和偏见,以恒定的。我希望准确性能够在第一百到第几千次迭代中相当快地增长,然后随着迭代次数的增加而减少。对我来说,学习是保持恒定,约为0.1

当我观察我发现,平均是10 ^订单上的梯度文件-6与10^-7的标准偏差。这解释了学习速度缓慢,但我还没有能够让渐变开始高得多。

这是几个迭代

Min  Max   Avg  Sdev 
-1.69821e-05 2.10922e-05 1.52149e-06 5.7707e-06 
-1.60263e-05 2.01478e-05 1.49323e-06 5.41754e-06 
-1.62501e-05 1.97764e-05 1.49046e-06 5.2904e-06 
-1.64293e-05 1.90508e-05 1.45681e-06 5.22742e-06 

这里是我的代码的核心部分后首次卷积梯度统计:

#init_path is path to init_net protobuf 
#pred_path is path to pred_net protobuf 
def main(init_path, pred_path): 
    ws.ResetWorkspace() 
    data_folder = '/home/myhome/food101/' 
    #some debug code here 
    arg_scope = {"order":"NCHW"} 
    train_model = model_helper.ModelHelper(name="food101_train", arg_scope=arg_scope) 
    if not debug: 
      data, label = AddInput(
        train_model, batch_size=128, 
        db=os.path.join(data_folder, 'food101-train-nchw-leveldb'), 
        db_type='leveldb') 
    init_net_def, pred_net_def = update_squeeze_net(init_path, pred_path) 
    #print str(init_net_def) 
    train_model.param_init_net.AppendNet(core.Net(init_net_def)) 
    train_model.net.AppendNet(core.Net(pred_net_def)) 
    ws.RunNetOnce(train_model.param_init_net) 
    add_params(train_model, init_net_def) 
    AddTrainingOperators(train_model, 'softmaxout', 'label') 
    AddBookkeepingOperators(train_model) 

    ws.RunNetOnce(train_model.param_init_net) 
    if debug: 
      ws.FeedBlob('data', data) 
      ws.FeedBlob('label', label) 
    ws.CreateNet(train_model.net) 

    total_iters = 10000 
    accuracy = np.zeros(total_iters) 
    loss = np.zeros(total_iters) 
    # Now, we will manually run the network for 200 iterations. 
    for i in range(total_iters): 
      #try: 
      conv1_w = ws.FetchBlob('conv1_w') 
      print conv1_w[0][0] 
      ws.RunNet("food101_train") 
      #except RuntimeError: 
      #  print ws.FetchBlob('conv1').shape 
      #  print ws.FetchBlob('pool1').shape 
      #  print ws.FetchBlob('fire2/squeeze1x1_w').shape 
      #  print ws.FetchBlob('fire2/squeeze1x1_b').shape 
      #softmax = ws.FetchBlob('softmaxout') 
      #print softmax[i] 
      #print softmax[i][0][0] 
      #print softmax[i][0][:5] 
      #print softmax[64*i] 
      accuracy[i] = ws.FetchBlob('accuracy') 
      loss[i] = ws.FetchBlob('loss') 
      print accuracy[i], loss[i] 

我add_params函数初始化的权重如下

#ops allows me to only initialize the weights of specific ops because i initially was going to do last layer training 
def add_params(model, init_net_def, ops=[]): 
    def add_param(op): 
      for output in op.output: 
        if "_w" in output: 
          weight_shape = [] 
          for arg in op.arg: 
            if arg.name == 'shape': 
              weight_shape = arg.ints 
          weight_initializer = initializers.update_initializer(
                None, 
                None, 
                ("XavierFill", {})) 
          model.create_param(
            param_name=output, 
            shape=weight_shape, 
            initializer=weight_initializer, 
            tags=ParameterTags.WEIGHT) 
        elif "_b" in output: 
          weight_shape = [] 
          for arg in op.arg: 
            if arg.name == 'shape': 
              weight_shape = arg.ints 
          weight_initializer = initializers.update_initializer(
                None, 
                None, 
                ("ConstantFill", {})) 
          model.create_param(
            param_name=output, 
            shape=weight_shape, 
            initializer=weight_initializer, 

我发现,当我用我的第损失函数波动e完整的训练集,但是如果我只使用一个批次并迭代多次,我发现损失函数下降但非常缓慢。

回答

1

虽然SqueezeNet具有50个比AlexNet较少的参数,它仍然是一个非常大的网络。 The original paper没有提到培训时间,但SqueezeNet SQ需要22小时训练使用两个Titan X图形卡 - 这是一些预先训练的重量!我没有仔细检查你的代码,但是你所描述的是预期的行为 - 你的网络能够在单批处理中学习,只是没有你期望的那么快。

我建议重用尽可能多的权重越好,而不是重新初始化他们,就像SQ的创造者一样。这就是所谓的转移学习,它可以工作,因为图像中的许多较低级别的特征(线条,曲线,基本形状)都是相同的,而不管图像的内容如何,​​并且重用这些图层的权重可以使网络免受重新从头学习它们。

+0

谢谢你的答案杰夫。问题原来是我计算梯度下降的方式。我已经复制了他们的教程的加权总和下降,但在阅读更多内容后,似乎对于大型网络来说,需要更复杂的下降形式。切换到亚当使所有的不同,你最后一层的训练建议真的有助于加快培训。谢谢! – Shaun