CS 231 n作業ノート2.2:多層ニューラルネットワークの実現


CS 231 n概要


詳しくはCS 231 nカリキュラムノート1:Introductionを参照してください.本文はすべて作者自身の思考で、正確性は検証されていないで、指導を歓迎します.

作業ノート


この部分は二層ニューラルネットワークの拡張であり、詳細はCS 231 n作業ノート2.1:二層全接続ニューラルネットワークの階層的実現を参照する.注意:このセクションにはdropoutおよびbatch normalizationは含まれません.

1.初期化パラメータ


注意:今回はnormal関数を使用していますが、randn関数も使用できます
    self.params['W1'] = np.random.normal(scale=weight_scale,size=[input_dim,hidden_dims[0]])
    self.params['b1'] = np.zeros(hidden_dims[0])
    for index in range(1,len(hidden_dims)):
        self.params['W'+str(index+1)] = np.random.normal(scale=weight_scale,size=[hidden_dims[index-1],hidden_dims[index]])
        self.params['b'+str(index+1)] = np.zeros(hidden_dims[index])
    self.params['W'+str(len(hidden_dims)+1)] = np.random.normal(scale=weight_scale,size=[hidden_dims[-1],num_classes])
    self.params['b'+str(len(hidden_dims)+1)] = np.zeros(num_classes)

2.前方伝播


辞書cacheを使用して、各一時保存変数を記録します.
    cache = {}
    hidden_value = None
    hidden_value,cache['fc1'] = affine_forward(X,self.params['W1'],self.params['b1'])
    hidden_value,cache['relu1'] = relu_forward(hidden_value)
    for index in range(2,self.num_layers):
        hidden_value,cache['fc'+str(index)] = affine_forward(hidden_value,self.params['W'+str(index)],self.params['b'+str(index)])
        hidden_value,cache['relu'+str(index)] = relu_forward(hidden_value)

    scores,cache['score'] = affine_forward(hidden_value,self.params['W'+str(self.num_layers)],self.params['b'+str(self.num_layers)])

3.後方伝播


注:bias regularizationを使用しないことをもう一度強調します.
    loss, grads = 0.0, {}
    loss,dscores = softmax_loss(scores,y)
    for index in range(1,self.num_layers+1):
        loss += 0.5*self.reg*np.sum(self.params['W'+str(index)]**2)

    dhidden_value,grads['W'+str(self.num_layers)],grads['b'+str(self.num_layers)] = affine_backward(dscores,cache['score'])
    for index in range(self.num_layers-1,1,-1):
        dhidden_value = relu_backward(dhidden_value,cache['relu'+str(index)])
        dhidden_value,grads['W'+str(index)],grads['b'+str(index)] = affine_backward(dhidden_value,cache['fc'+str(index)])
    dhidden_value = relu_backward(dhidden_value,cache['relu1'])
    dhidden_value,grads['W1'],grads['b1'] = affine_backward(dhidden_value,cache['fc1'])

    for index in range(1,self.num_layers+1):
        grads['W'+str(index)] += self.reg * self.params['W'+str(index)] 

4.SolverのAPIを使用する


この部分はSolverをテストするためのAPIで、自分でsolverを表示します.pyでいいです.50%以上の精度を達成するには、一般的なパラメータを試してみるだけです.
model = TwoLayerNet()
solver = Solver(model,
                data,
                update_rule='sgd',
                optim_config={
                    'learning_rate': 1e-3,
                },
                lr_decay=0.95,
                num_epochs=10, batch_size=100,
                print_every=100)
solver.train()

5.50個のサンプルをオーバーフィットしたデータベース


このセクションは、多層ニューラルネットワークのテストおよび使用に用いられるとともに、深さニューラルネットワークに対するパラメータ調整が浅いニューラルネットワークよりも困難であることに留意される.

5.1. さんそうニューラルネットワーク


一般的なパラメータを試してください.
weight_scale = 1e-2
learning_rate = 7e-3
model = FullyConnectedNet([100, 100],
              weight_scale=weight_scale, dtype=np.float64)
solver = Solver(model, small_data,
                print_every=10, num_epochs=20, batch_size=25,
                update_rule='sgd',
                optim_config={
                  'learning_rate': learning_rate,
                }
         )
solver.train()

5.2. ごそうニューラルネットワーク


パラメータ調整プログラムを書く必要があります.深さが深いほど、パラメータ調整の難易度が高く、局所的な極致に落ちやすいことに気づきます.また、好ましいスーパーパラメータは、ある極小部分内にあるため、粗調の場合もステップ長を小さくする必要がある.
learning_rate = [1.8e-2,1.8e-2]
weight_scale = [3.25e-2,3.25e-2]
random_params = np.random.rand(1,2)
random_params[:,0] = random_params[:,0]*(learning_rate[1]-learning_rate[0]) + learning_rate[0]
random_params[:,1] = random_params[:,1]*(weight_scale[1]-weight_scale[0]) + weight_scale[0]

results = {}
best_train_acc = -1
best_solver = None

validation = False

for lr,ws in random_params:
    model = FullyConnectedNet([100, 100, 100, 100],
                    weight_scale=ws, dtype=np.float64)
    solver = Solver(model, small_data,
                    print_every=10, num_epochs=20, batch_size=25,
                    update_rule='sgd',
                    optim_config={
                      'learning_rate': lr,
                    },
                    verbose = not validation
             )
    solver.train()
    results[(lr,ws)] = (solver.loss_history[-1],solver.train_acc_history[-1])
    if (solver.train_acc_history[-1] > best_train_acc):
        best_train_acc = solver.train_acc_history[-1]
        best_solver = solver

if (validation):
    for lr,ws in results:
        print "learning rate: %.6e weight scale: %.6e train acc: %.6e" %(lr,ws,results[(lr,ws)][1])

    print "best train accuracy: %.6e" % (best_train_acc)

    import math
    x_scatter = [math.log10(x[0]) for x in results]
    y_scatter = [math.log10(x[1]) for x in results]
    colors = [results[x][1] for x in results]

    plt.scatter(x_scatter,y_scatter,100,c = colors)
    plt.xlabel("log learning rate")
    plt.ylabel("log weight scale")
    plt.colorbar()
    plt.show()
else:
    plt.plot(solver.loss_history, 'o')
    plt.title('Training loss history')
    plt.xlabel('Iteration')
    plt.ylabel('Training loss')
    plt.show()