Pythonのニューラルネットワークプログラミングノート

ニューロン

あなたは、ニューロンの強度を呼び出すだろうという痛みをつまん人を見たとき、彼らは知っていると思うことは閾値であり、私たちはビルドするとき、この現象が呼び出され、関数に抽象化された活性化関数

そして、ここで私たちが使用しているものであるシグモイド関数の理由を、それがスムーズに近い表示に非常に単純な関数です。

\ [Y = \ FRAC {1} {1 + E ^ { - X}} \]

Snipaste_2018-12-03_15-29-41.png

ニューラルネットワークの送信信号

ニューラルネットワークは、ニューロン入力のxの値とシグモイド関数によって得られた最終的な出力値を使用する権利を介して接続され、次いで層ごとに受け継があります。

\ [O =シグモイド(W \ CDOT I)\]

ここで、\(O \)は、出力行列で\(Wが\である)重み行列であり、\(I \)は入力行列です。

栗の場合:

、出力層:(関係なく、中間層が隠されて呼ばれるか、私たちの多くの層、私たちはここに隠された層内の一層のみであることに注意)、我々は3層ニューラルネットワークを設定すると仮定し、入力層、中間層です。

1. 入力層- >隠された層は、( - >隠された層であり、入力層)寸法また、我々は、マトリックスは、(3×1)行列で入力し、我々は最初の重み行列ので、4点の重みを設定しますそれは、我々は乗算出力行列(4×1)を取得し、次のステップを行う、(4×1)マトリックス出力が入力となる(4×3)です。

2. 隠された層- >出力層:これは、隠された層であり、そして、私たちの第2の重み行列(、そして私たちは二つの出力層の出力値を必要とし、私たちの入力行列は、(4×1)行列である- >出力層A)それは、我々は乗算出力マトリクス(2×1)を取得する、それが最終的な結果である、寸法(2×4)です。

逆伝搬

私たちは、その後、どのように我々はそれを改善することができ、今の結果は、前の層を介して送信することができ受けましたが、答えは絶対に許されませんか?

確かに、私たちは、その後、誤差eは、このようにある真値t、出力値Oを仮定して、誤差を計算する必要があります。

\ [とに= \]

book1.png

私たちは、図示の図に従って行いました。

1.アップデートエラー

だから、どのように隠れ層の誤差を決定するには?

我々は、リンク使用\(W_ {1,1} \)とリンク\(W_ {2,1} \)誤差の和を除算し、更新する、すなわち

\ [E_ {隠された、1} = E_ {出力、1} * \ FRAC {W_ {1,1}} {W_ {1,1} + W_ {2,1}} + E_ {出力、2} * \ FRAC {W_ {1,2}} {W_ {1,2} + W_ {2,2}} \]

また、計算に価値をもたらします

\ [0.8 * \ FRAC {2} {2 + 3} + 0.5 * \ FRAC {1} {1 + 4} = 0.42 \]

2.行列が更新されます

私たちは、私たちは、最も重要なことは、エラーの出力とリンクの重みで、本質的には、行列演算に上記の式は非常に複雑になることを見出した\(W_ {IJ} \)の乗算。より大きな重み手段は、複数の出力誤差隠れ層を運ぶために、分数の分母は正規化係数です。私たちはこの要因を無視するならば、我々だけで、エラーの大きさの崩壊を失いました。

ここで使用することである(E_1 * W_ {1,1} \ \) の代わりに(\ E_1 W_ * {1,1} /(W_ + W_ {1,1} {2,1}))\その後、我々は簡単に行列演算誤差が更新された実行することができます。

\ [ERROR_ {隠れ} = W ^ T_ {隠れ\ _output} \ CDOT ERROR_ {出力} \]

3.更新した重み

在神经网络中,我们采用梯度下降法来寻找最优的权重值。神经网络本身的输出函数部署一个误差函数,但我们知道,由于误差是目标训练值与实际输出值之间的差值,因此我们可以很容易的构建误差函数,即

\[(目标值-实际值)^2\]

为什么我们要构建平方项呢?为何不用绝对值误差呢?原因有三

  1. 使用误差的平方,我们可以很容易的使用代数计算出梯度下降的斜率;
  2. 误差函数平滑连续,这是的梯度下降法很好地发挥作用,没有间断,也没有突然的跳跃;
  3. 越接近最小值,梯度越小,这意味着,如果我们使用这个函数调节步长,超调的风险就会变得很小。

现在我们要更新\(w_{j,k}\)的权值,那么来推导一下它的更新公式:

首先有

\[\frac{\partial E}{\partial W_{j,k}} = \frac{\partial}{\partial W_{j,k}}(t_k-o_k)^2\]

然后根据链式法则得到:

\[\frac{\partial E}{\partial W_{j,k}} = \frac{\partial E}{\partial o_k} \cdot \frac{\partial o_k}{\partial W_{j,k}}\]

然后我们对其求偏导:

\[\frac{\partial E}{\partial W_{j,k}} = -2(t_k-o_k) \cdot \frac{\partial o_k}{\partial W_{j,k}}\\ = -2(t_k-o_k) \cdot \frac{\partial}{\partial W_{j,k}}sigmoid(\sum_{j}w_{j,k}\cdot o_j)\\ = -2(t_k-o_k) \cdot sigmoid(\sum_{j}w_{j,k}\cdot o_j)(1-sigmoid(\sum_{j}w_{j,k}\cdot o_j)) \cdot \frac{\partial}{\partial W_{j,k}}(\sum_{j}w_{j,k}\cdot o_j)\\ = -2(t_k-o_k) \cdot sigmoid(\sum_{j}w_{j,k}\cdot o_j)(1-sigmoid(\sum_{j}w_{j,k}\cdot o_j)) \cdot o_j\]

这样我们就得到了最后的权重更新公式:

\[new W_{j,k} = oldW_{j,k} - \alpha \cdot \frac{\partial E}{\partial W_{j,k}} \]

其中:

\[\frac{\partial E}{\partial W_{j,k}} = \Delta w_{j,k} = \alpha \cdot E_k \cdot O_k(1-O_k) \cdot O_j^T\]

输入与输出

1.输入

我们观察sigmoid函数注意到,当输入值变大,激活函数也就会越来越平坦,权重的改变取决于激活函数的梯度,小梯度也就意味着限制了神经网络的学习能力,这就是所谓的饱和神经网络。因此,我们要尽量保持小的输入。

入力信号が小さすぎると、我々は0.0と1.0との間の入力レンジを維持したいので、興味深いことに、しかし、コンピュータは、精度の損失となり、その後の入力0であろう\(O_jは、\)ように重み更新することを、0に設定されています式は学習障害で、その結果、0に等しい、我々は0もたらしを入力することを避けるために、たとえば0.01のために、小さなオフセットを追加する必要があります。

2.出力

当社は、取得した活性化関数の値が0と1の間の範囲に制限されます使用ノート:論理機能でも1.0数学者だけ徐々に近づく1.0に呼び出して、1.0に取得することはできません。

したがって、我々は150に例えば0.01ため、オフセットしているので、ここでは、活性化関数が0.0ないし1.0の一般的な範囲の出力を一致させることができる、目標値を調整する必要があるが、我々は、0.0と1.0に失敗します。

ランダムな初期重み

そして、初期重量の設定などの入力と出力は同じ原理的に従ってください。初期重量は、ネットワークの飽和につながる、活性化機能に大きな信号を引き起こし、それによってより良い権利の学習能力を軽量化するため、大規模な初期重み値を避ける必要があります大きすぎます。

私たちは、初期重みのから+1.0 -1.0の間で一様にランダムな選択を見ることができます。そして、我々はまた、数学者たちは、ある道の良い選択を、持っていることが証明された後の初期の重み分布が均一であることを願って、正規分布の逆数平方根に着信リンクのノード数に等しい0と標準偏差の平均値からサンプリング

すべてのすべてで、我々は禁止すべき初期重量は、痛みのような一定の値に設定され、これは非常に悪いになります0または初期重量に設定されています。

コードの実装

import numpy as np
import scipy.special
import matplotlib.pyplot as plt


# neural network class definition
class NeuralNetwork:
    def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
        # set number of nodes in each input, hidden, output layer
        self.inodes = inputnodes
        self.hnodes = hiddennodes
        self.onodes = outputnodes

        # learning rate
        self.lr = learningrate

        # 初始权重矩阵
        self.wih = np.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))
        self.who = np.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes, self.hnodes))

        # 激活函数
        self.activation_function = lambda x: scipy.special.expit(x)
        pass

    def train(self, inputs_list, targets_list):
        # 输入
        inputs = np.array(inputs_list, ndmin=2).T
        targets = np.array(targets_list, ndmin=2).T
        # 隐藏层计算
        hidden_inputs = np.dot(self.wih, inputs)
        hidden_outputs = self.activation_function(hidden_inputs)
        # 输出层计算
        final_inputs = np.dot(self.who, hidden_outputs)
        final_outputs = self.activation_function(final_inputs)
        # 误差计算
        output_errors = targets - final_outputs
        hidden_errors = np.dot(self.who.T, output_errors)
        # 反向传播更新权值
        self.who += self.lr * np.dot((output_errors * final_outputs * (1.0 - final_outputs)), np.transpose(hidden_outputs))
        self.wih += self.lr * np.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)),  np.transpose(inputs))
        pass

    def query(self, inputs_list):
        # 输入
        inputs = np.array(inputs_list, ndmin=2).T
        # 隐藏层计算
        hidden_inputs = np.dot(self.wih, inputs)
        hidden_outputs = self.activation_function(hidden_inputs)
        # 输出层计算
        final_inputs = np.dot(self.who, hidden_outputs)
        final_outputs = self.activation_function(final_inputs)
        return final_outputs


if __name__ == '__main__':
    input_nodes = 784
    hidden_nodes = 200
    output_nodes = 10

    learning_rate = 0.2

    nn = NeuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)

    # 加载数据
    train_data_file = open("./mnist_train.csv", "r")
    train_data_list = train_data_file.readlines()
    train_data_file.close()
    print("数据读取完毕")

    # 可视化
    # all_values = train_data_list[0].split(',')
    # image_array = np.asfarray(all_values[1:]).reshape((28, 28))
    # plt.imshow(image_array, cmap="Greys", interpolation='None')
    # plt.show()

    epochs = 2

    for e in range(epochs):
        print("\t===== epochs %d =====\t" % (e+1))
        for record in train_data_list:
            all_values = record.split(',')
            inputs = (np.asfarray(all_values[1:]) / 255 * 0.99) + 0.01

            targets = np.zeros(output_nodes) + 0.01
            targets[int(all_values[0])] = 0.99

            nn.train(inputs, targets)

    # 预测
    test_data_file = open("./mnist_test.csv", "r")
    test_data_list = test_data_file.readlines()
    test_data_file.close()
    print(len(test_data_list))

    t_num = 0
    for line in test_data_list:
        all_values = line.split(',')
        y = all_values[0]
        y_pred = np.argmax(nn.query(np.asfarray(all_values[1:]) / 255 * 0.99 + 0.01))
        if int(y) == int(y_pred):
            t_num += 1

    print(t_num)
    print(t_num * 1.0 / len(test_data_list))

3層ニューラルネットワークmnist手書きデータセットが到達することができ、97%の精度を。

おすすめ

転載: www.cnblogs.com/harrylyx/p/12409097.html