【C++】シグモイド関数を実装してみる

シグモイド関数の実装

「ゼロから作るDeep Learning」という本を買ったのでこの本を参考に勉強していこうと思います。Pythonのソースコードもついているので参考にします。

1. 活性化関数

ニューラルネットワークは層を重ねることで非線形の問題も解くことができますが、そのためには各層の出力を「活性化関数」という非線形関数を通す必要があります。その中でも「シグモイド関数」はよく使われます。

2. シグモイド関数

シグモイド関数は以下の式で表されます。

\[\frac{1}{1+e^{-x}}\]

この関数は入力値を0~1までの値に変換してくれます。
まずは入力された行列データを変換する関数を実装します。ソースコードは以下の通りです。
MatrixXf」はfloat型の行列変数、各要素をスカラー倍する場合は「array()」を付けます。
指数関数を計算する場合は「exp()」を付けます。

// シグモイド関数
void sigmoid(MatrixXf& mat_input, MatrixXf& mat_output) {
	mat_output = (1.0 / (1.0 + ((-1.0)*mat_input.array()).exp()));
}

3. グラフを描画してみる

上記で実装したシグモイド関数と前回作成したグラフ描画用のクラスを使って実際にグラフを描画してみます。ここでは入力値-5.0~5.0まで0.1間隔で設定して変換してみます。
また、ここでは省略しますが入力値と出力値を表示する際に表示が途切れてしまうのでsleepを入れています。

#include <iostream>
#include <thread>
#include "Eigen\\Core"
#include "Class_Gnuplot.h"

// 定数
#define D_MATRIX_ROWS_SIZE	101
#define D_GNUPLOT_FILE_NAME	"Gnuplot\\gnuplot.exe"

using namespace std;
using namespace Eigen;

// シグモイド関数
void sigmoid(MatrixXf& mat_input, MatrixXf& mat_output) {
	mat_output = (1.0 / (1.0 + ((-1.0)*mat_input.array()).exp()));
}

int main() {
	int i;
	classGnuplot clGnuplot;
	T_GNUPLOT_POINT tData[D_MATRIX_ROWS_SIZE];
	string strFile = D_GNUPLOT_FILE_NAME;
	// float型で101×1のベクトル設定
	MatrixXf mat_x = MatrixXf::Zero(D_MATRIX_ROWS_SIZE, 1);
	MatrixXf mat_y = MatrixXf::Zero(D_MATRIX_ROWS_SIZE, 1);

	float fStart = -5.0;
	for (i = 0; i < D_MATRIX_ROWS_SIZE; i++) {
		// -5.0~5.0まで0.1刻みでセット
		mat_x(i, 0) = fStart + (i * 0.1);
	}

	sigmoid(mat_x, mat_y);

	for (i = 0; i < D_MATRIX_ROWS_SIZE; i++) {
		// 表示が間に合わないのでSleepを入れる
		this_thread::sleep_for(chrono::milliseconds(10));
		cout << mat_x(i, 0) << ", " << mat_y(i, 0) << endl;
		tData[i].x = mat_x(i, 0);
		tData[i].y = mat_y(i, 0);
		clGnuplot.Set_Data(tData[i]);
	}

	// グラフ描画
	// Gnuplotを起動
	if (clGnuplot.Open_Gnuplot(strFile) > 0) {
		// X軸範囲-5.0~5.0
		clGnuplot.Set_XRange(-5.0, 5.0);
		// Y軸範囲0.0~1.0
		clGnuplot.Set_YRange(0.0, 1.0);
		// グラフ描画
		clGnuplot.Plot(1);
		// Gnuplotを閉じる
		clGnuplot.Close_Gnuplot();
	}
	else {
		cout << "Gnuplotの起動に失敗しました" << endl;
	}

	return 0;
}

実際に描画したグラフはこちら。
入力値が0~1の値に変換されていることが分かります。

Sigmoid関数描画結果

4. 参考書籍

ゼロから作るDeep Learning

コメント

タイトルとURLをコピーしました