迭代

2017-06-12 87 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