Chainerでのニューラルネットワーク構築方法について実践的な方法を勉強するために、ニューラルネットワークを使って関数フィッティングに挑戦してみる。
以前、CNTKやTensorFlowを使って同様のニューラルネットワーク構築を行なったことがある。
解くべき問題 - 関数フィッティング
以下のような関数を持つデータが存在し、この関数にフィッティングできるようなニューラルネットワークを構築する。
データは以下のようなプログラムを使って発生させる。function()が生成したい関数である。
float function (float x) { return -1.0f * sinf (x) + 0.2f; } int main() { std::ofstream fp; std::random_device rnd; fp.open ("input_data.txt"); for (int i = 0; i < 100000; i++) { float float_rand = ((static_cast<float>(rnd()) / UINT32_MAX) - 0.5f) * 4.0f; fp << float_rand << ", " << function(float_rand) << '\n'; } fp.close(); return 0; }
以下のようなデータセットが生成される。
0.137679, 0.0627557 -0.413383, 0.60171 -1.20963, 1.13548 1.16802, -0.719974 1.9593, -0.725477 0.0846508, 0.11545 1.08912, -0.686222 -1.14595, 1.1111 0.875998, -0.568183 -1.22355, 1.14031
Chainerでのネットワーク構築方法
Chainerでのネットワークの構築は、Pythonで計算データフローを構築しているのに似ている。
class Function3DimentionModel(chainer.FunctionSet): def __init__(self): super(Function3DimentionModel, self).__init__( fc1=chainer.functions.Linear( 1,16), fc2=chainer.functions.Linear(16,32), fc3=chainer.functions.Linear(32, 1), ) def forward(self, x): h1 = self.fc1(x) h2 = self.fc2(h1) h3 = self.fc3(h2) return h3
ここでは、入力値1つを受け取り、それを16次元→32次元→1次元へと収束させるネットワークを構築している。このあたりは、以下のサイトを参考にさせて頂いている。
トレーニング関数
トレーニング関数では、トレーニングデータセットを入力し、解答との誤差を最小にするように仕向ける。
def train(self, x_data, y_data): x = chainer.Variable(x_data.astype(np.float32), volatile=False) y = chainer.Variable(y_data.astype(np.float32), volatile=False) h = self.forward(x) optimizer.zero_grads() # error = chainer.functions.sigmoid(h, y) error = F.mean_squared_error(h, y) error.backward() optimizer.update()
これをデータセット分だけ繰替えす訳だ。
for epoch in six.moves.range(1, n_epoch + 1): print('epoch', epoch) perm = np.random.permutation(N) for i in six.moves.range(0, N, batchsize): x_part = x_train[perm[i:i + batchsize]].reshape(batchsize, 1) y_part = y_train[perm[i:i + batchsize]].reshape(batchsize, 1) model.train (x_part, y_part)
実際にトレーニングさせた結果でテストデータを入力すると、以下のような結果になってしまった。
単なる一次元のデータじゃないか!どこかで間違えているのか、学習量が足りないのか、まだ精査していく必要がある。