MATLAB,Python,Scilab,Julia比較 第4章 その17【決定境界直線の安定化④】

MATLAB,Python,Scilab,Julia比較 第4章 その17【決定境界直線の安定化④】 数値計算
MATLAB,Python,Scilab,Julia比較 第4章 その17【決定境界直線の安定化④】

バックナンバーはこちら。
https://www.simulationroom999.com/blog/compare-matlabpythonscilabjulia4-backnumber/

はじめに

形式ニューロンの決定境界直線がギリギリのところにある問題の対策としてカスタムヘヴィサイド(造語)を使用したプログラムを作成。
今回はMATLAB。

登場人物

博識フクロウのフクさん

指差しフクロウ

イラストACにて公開の「kino_k」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=iKciwKA9&area=1

エンジニア歴8年の太郎くん

技術者太郎

イラストACにて公開の「しのみ」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=uCKphAW2&area=1

【再掲】カスタムヘヴィサイド(造語)

太郎くん
太郎くん

とりあえず形式ニューロンをカスタムヘヴィサイド(造語)にしたものMATLABでやる感じだね。

フクさん
フクさん

カスタムヘヴィサイド関数を再掲しておこう。

\(
\begin{cases}
y=0&(x\le -2.5) \\
y=1&(2.5\le x) \\
y=2x+0.5&(-2.5\lt x \lt 2.5)
\end{cases}
\)

MATLABコード

フクさん
フクさん

MATLABコードは以下。

custom_heaviside.m

function output = custom_heaviside(x)
    output = (x < -0.25) .* 0 + (x >= -0.25 & x <= 0.25) .* ( 2*x + 0.5 ) + (x > 0.25) .* 1;
end
% データセットの入力
X = [0, 0; 0, 1; 1, 0; 1, 1];
% データセットの出力
Y = [0; 0; 0; 1];

% パラメータの初期値
W = zeros(2, 1); % 重み
b = 0; % バイアス
num_epochs = 10000; % 学習のエポック数
learning_rate = 0.1; % 学習率
min_loss = realmax;
learning_range = 4;
n=length(Y)

% 重みの総当たり計算
for w1 = -learning_range:learning_rate:learning_range
    for w2 = -learning_range:learning_rate:learning_range
        for b = -learning_range:learning_rate:learning_range
            % フォワードプロパゲーション
            Z = X * [w1; w2] + b; % 重みとバイアスを使用して予測値を計算
            A=custom_heaviside(Z); % ヘヴィサイド活性化関数を適用

            % 損失の計算
            loss = 1/n * sum((A - Y).^2); % 平均二乗誤差

            % 最小損失の更新
            if loss < min_loss
                min_loss = loss;
                best_w1 = w1;
                best_w2 = w2;
                best_b = b;
            end
        end
    end
    % ログの表示
	  fprintf('loss: %f\n', min_loss);
	  fprintf('weight: w1 = %f, w2 = %f\n', best_w1, best_w2);
	  fprintf('bias: b = %f\n', best_b);
end

% 最小損失の重みを更新
W = [best_w1; best_w2];
b = best_b;

% 学習結果の表示
fprintf('learning completed\n');
fprintf('weight: w1 = %f, w2 = %f\n', W(1), W(2));
fprintf('bias: b = %f\n', b);

% 出力結果確認
fprintf('X=');
disp(X);
fprintf('X=');
disp(custom_heaviside(X*[W(1);W(2)]+b));

% 決定境界線のプロット
x1 = linspace(-0.5, 1.5, 100); % x1の値の範囲
x2 = -(W(1) * x1 + b) / W(2); % x2の計算

figure;
hold on;
scatter(X(Y == 0, 1), X(Y == 0, 2), 'filled', 'MarkerFaceColor', 'r');
scatter(X(Y == 1, 1), X(Y == 1, 2), 'filled', 'MarkerFaceColor', 'b');
x1 = [min(X(:, 1))-1 max(X(:, 1))+1];
x2 = -(W(1)*x1 + b) / W(2);
plot(x1, x2, 'k', 'LineWidth', 2);
xlim([-0.5 1.5]);
ylim([-0.5 1.5]);
title(sprintf('Loss: %.4f', loss));
legend('Class 0', 'Class 1', 'Decision Boundary');
grid;
hold off;

処理結果

フクさん
フクさん

処理結果は以下。

カスタムヘヴィサイド(造語)で形式ニューロン(MATLAB)
weight: w1 = 0.600000, w2 = 0.600000
bias: b = -0.900000
X=     0     0
     0     1
     1     0
     1     1

Y=     0
     0
     0
     1

考察

太郎くん
太郎くん

ばっちり決定境界直線がいい感じのところに移動したね。
変更点はヘヴィサイド関数をカスタムヘヴィサイド関数に差し替えただけか。

フクさん
フクさん

そうだね。
他は全く弄ってない。
傾斜を付けたから、より正しいパラメータを見つけることができるようになった。

太郎くん
太郎くん

自動でこういうふうに見つけられるはおもしろい。

まとめ

フクさん
フクさん

まとめだよ。

  • 形式ニューロンの活性化関数をカスタムヘヴィサイド(造語)関数にしたものをMATLABで作成。
  • 狙い通りの位置に決定境界直線が移動。
  • コードはヘヴィサイド関数をカスタムヘヴィサイド関数に変えただけ。

バックナンバーはこちら。

コメント

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