0

ガラクタネット

55
0
$$$$

ガラクタなニューラルネットワーク?

ガラクタのようなニューラルネットワークを作ってみた。

学習率が間違っていました。
本当にすいません。
これでは再現性がありませんでした。
lr=0.3ではなく、lr=0.5でした。
申し訳ありません。

      
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
# 1. データセットの準備 (三日月データ)
X_2d, y = make_moons(n_samples=600, noise=0.1, random_state=42)
X_3d = np.hstack([X_2d, np.zeros((X_2d.shape[0], 1))])
y = y + 1  # ラベルを1と2に変換
# 2. ネットワークの初期化
np.random.seed(42)
layer_sizes = [1000, 10, 2]
network = []
for size in layer_sizes:
    layer = {
        'a': np.random.uniform(-1.5, 2.5, (size, 3)), 
        'A': np.random.uniform(1, 2, (size, 3))        
    }
    network.append(layer)
lr = 0.5
epochs = 10
epsilon = 0.001
# --- 統計記録用の変数 ---
layer_satisfied_dims = [0, 0, 0] 
total_checks = 0 
# 3. 推論および学習の関数
def forward_backward(x, target_label=None, train=True):
    global layer_satisfied_dims, total_checks
    if train:
        total_checks += 1
        # 学習時は正解ラベルからターゲットベクトルを作成
        target_A = np.full(3, float(target_label))
        
    current_input = x.copy()
    
    # 各層を順番に伝播
    for l, layer in enumerate(network):
        a_mats = layer['a'] 
        A_mats = layer['A'] 
        
        # 1. 最も近いユニットを1つ選択
        l2_dists = np.linalg.norm(a_mats - current_input, axis=1)
        closest_idx = np.argmin(l2_dists)
        
        best_a = a_mats[closest_idx] 
        best_A = A_mats[closest_idx] 
        
        # 2. 個々の次元ごとに条件判定
        satisfied_mask = np.abs(current_input - best_a) < epsilon 
        
        # 【統計記録】学習時のみ加算
        if train:
            layer_satisfied_dims[l] += np.sum(satisfied_mask)
        
        next_input = np.zeros(3)
        
        for d in range(3):
            if satisfied_mask[d]:
                # 条件を満たした次元
                next_input[d] = best_A[d]
            else:
                # 条件を満たさない次元は update 
                if train:
                    layer['a'][closest_idx, d] += lr * (current_input[d] - layer['a'][closest_idx, d])
                    layer['A'][closest_idx, d] += lr * (target_A[d] - layer['A'][closest_idx, d])
                next_input[d] = layer['A'][closest_idx, d]
                
        current_input = next_input
            
    # --- 最終判定ロジック (推論・学習共通) ---
    # 3層目を通過した最終的なシグナルが、クラス1(1.0) と クラス2(2.0) のどちらに近いかで判定
    dist_to_1 = np.linalg.norm(current_input - np.full(3, 1.0))
    dist_to_2 = np.linalg.norm(current_input - np.full(3, 2.0))
    
    return 1 if dist_to_1 < dist_to_2 else 2
# 4. トレーニングループ
print("Training...")
for epoch in range(epochs):
    correct = 0
    # カウンタのリセット
    layer_satisfied_dims = [0, 0, 0]
    total_checks = 0
    
    for i in range(len(X_3d)):
        pred = forward_backward(X_3d[i], y[i], train=True)
        if pred == y[i]:
            correct += 1
            
    print(f"Epoch {epoch+1}/{epochs} - Accuracy: {correct / len(X_3d) * 100:.2f}%")
    
    # --- 到達度・条件達成率の出力 ---
    print(f"--- 各層での条件達成の状況(Epoch {epoch+1}) ---")
    print(f" 3層目(最終層)へ到達したデータ数: {total_checks} サンプル")
    total_possible_dims = total_checks * 3 
    for l in range(3):
        sat_dims = layer_satisfied_dims[l]
        ratio = (sat_dims / total_possible_dims) * 100
        print(f" [Layer {l+1}] 条件を満たしてUpdateを回避した次元数: {sat_dims} / {total_possible_dims} ({ratio:.2f}%)")
    print("--------------------------------------------------\n")
# 5. 決定境界の描画用予測関数
def predict(X):
    preds = []
    for x in X:
        # 推論時は target_label=None, train=False
        preds.append(forward_backward(x, target_label=None, train=False)) 
    return np.array(preds)
# 6. グリッドデータの生成とプロット
print("Plotting decision boundary...")
x_min, x_max = X_2d[:, 0].min() - 0.5, X_2d[:, 0].max() + 0.5
y_min, y_max = X_2d[:, 1].min() - 0.5, X_2d[:, 1].max() + 0.5
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.05), np.arange(y_min, y_max, 0.05))
grid_points_2d = np.c_[xx.ravel(), yy.ravel()]
grid_points_3d = np.hstack([grid_points_2d, np.zeros((grid_points_2d.shape[0], 1))])
Z = predict(grid_points_3d)
Z = Z.reshape(xx.shape)
plt.figure(figsize=(10, 6))
plt.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.coolwarm)
scatter = plt.scatter(X_2d[:, 0], X_2d[:, 1], c=y, cmap=plt.cm.coolwarm, edgecolors='k')
plt.title("RBF-like Custom Network Decision Boundary (Fixed)")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.legend(handles=scatter.legend_elements()[0], labels=["Label 1", "Label 2"])
plt.show()
    

出力結果:
Training...
Epoch 1/1 - Accuracy: 100.00%
--- 各層での条件達成の状況(Epoch 1) ---
3層目(最終層)へ到達したデータ数: 600 サンプル
[Layer 1] 条件を満たしてUpdateを回避した次元数: 317 / 1800 (17.61%)
[Layer 2] 条件を満たしてUpdateを回避した次元数: 108 / 1800 (6.00%)
[Layer 3] 条件を満たしてUpdateを回避した次元数: 1102 / 1800 (61.22%)


今回は決定境界をここに描いていませんが・・・・
興味のある方は上のコードをグーグルコラボなどで確かめてみてください!


下はネットワークの内部を調べたコード

      all_outputs = []
for x in X_3d:
    current = x.copy()
    for layer in network:
        a = layer['a']
        A = layer['A']
        idx = np.argmin(
            np.linalg.norm(a-current, axis=1)
        )
        current = A[idx]
    all_outputs.append(tuple(np.round(current, 4)))
print(len(set(all_outputs)))
    

出力結果
2

      unique_outputs = sorted(set(all_outputs))
print(unique_outputs)
    

出力結果
[(np.float64(1.0), np.float64(1.0), np.float64(1.0)), (np.float64(2.0), np.float64(2.0), np.float64(2.0))]

投稿日:14日前
更新日:14日前
数学の力で現場を変える アルゴリズムエンジニア募集 - Mathlog served by OptHub

この記事を高評価した人

高評価したユーザはいません

この記事に送られたバッジ

バッジはありません。

投稿者

Owl
1
210

コメント

他の人のコメント

コメントはありません。
読み込み中...
読み込み中