多クラス分類
デジタル表示のアルファベットA,B,Cを判定するニューラルネットを作成します。
訓練用
data_0.txt~2を読み込んで最適化を行い、最適化したニューロンの重みとバイアスをモデル(trained_model.json)に保存します。
data_0~2で3つのクラスを作成します。
import numpy as np
import json
# シグモイド関数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# シグモイド関数の微分
def sigmoid_derivative(x):
return x * (1 - x)
# ニューロン情報付きモデルの保存関数
def save_model_text(file_name, weights_input_hidden, weights_hidden_output, bias_hidden, bias_output):
model_data = {
"hidden_layer": {
f"neuron_{i}": {
"weights": weights_input_hidden[:, i].tolist(),
"bias": bias_hidden[0][i]
}
for i in range(weights_input_hidden.shape[1])
},
"output_layer": {
f"neuron_{i}": {
"weights": weights_hidden_output[:, i].tolist(),
"bias": bias_output[0][i]
}
for i in range(weights_hidden_output.shape[1])
}
}
with open(file_name, "w") as f:
json.dump(model_data, f, indent=4)
print(f"Model with neuron details saved to {file_name}")
# モデルの読み込み関数
def load_model_text(file_name):
with open(file_name, "r") as f:
model_data = json.load(f)
print(f"Model loaded from {file_name}")
hidden_layer_weights = np.array([neuron["weights"] for neuron in model_data["hidden_layer"].values()]).T
hidden_layer_bias = np.array([[neuron["bias"] for neuron in model_data["hidden_layer"].values()]])
output_layer_weights = np.array([neuron["weights"] for neuron in model_data["output_layer"].values()]).T
output_layer_bias = np.array([[neuron["bias"] for neuron in model_data["output_layer"].values()]])
return hidden_layer_weights, output_layer_weights, hidden_layer_bias, output_layer_bias
# # ファイルからトレーニングデータを読み込む関数
def load_training_data(file_name, label, num_classes):
data = []
with open(file_name, "r") as f:
# ファイル内容を空白行で区切り、それぞれを解析
blocks = f.read().strip().split("\n\n")
for block in blocks:
# 各ブロックを8行5列のリストとして読み込む
pattern = [list(map(int, line.strip("[],\n").split(","))) for line in block.split("\n")]
# 配列を1次元化
flattened_pattern = np.array(pattern).flatten()
# ラベルをone-hotエンコーディング
one_hot_label = [1 if i == label else 0 for i in range(num_classes)]
data.append((flattened_pattern, one_hot_label))
return data
# # ファイルからトレーニングデータを読み込む関数
# def load_training_data(file_name, label, num_classes):
# data = []
# with open(file_name, "r") as f:
# # ファイル内容を空白行で区切り、それぞれを解析
# blocks = f.read().strip().split("\n\n")
# for block in blocks:
# try:
# # 各ブロックを8行5列のリストとして読み込む
# pattern = [list(map(int, line.strip("[],\n ").split(","))) for line in block.split("\n") if line.strip()]
# if len(pattern) == 8 and all(len(row) == 5 for row in pattern): # 行数と列数を確認
# # 配列を1次元化
# flattened_pattern = np.array(pattern).flatten()
# # ラベルをone-hotエンコーディング
# one_hot_label = [1 if i == label else 0 for i in range(num_classes)]
# data.append((flattened_pattern, one_hot_label))
# else:
# print(f"Skipped block due to incorrect dimensions: {block}")
# except ValueError as e:
# print(f"Error processing block: {block}, Error: {e}")
# return data
# # ファイルからトレーニングデータを読み込む関数
# def load_training_data(file_name, label, num_classes):
# data = []
# with open(file_name, "r") as f:
# # ファイル内容を空白行で区切り、それぞれを解析
# blocks = f.read().strip().split("\n\n")
# for block in blocks:
# try:
# # 各ブロックを8行5列のリストとして読み込む
# pattern = []
# for line in block.split("\n"):
# # 各行の処理
# line = line.strip("[],\n ")
# if not line: # 空行をスキップ
# continue
# try:
# row = list(map(int, line.split(","))) # 数値に変換
# if len(row) != 5: # 列数が5以外ならエラー
# raise ValueError("Invalid row length")
# pattern.append(row)
# except ValueError:
# print(f"Skipped invalid row: {line}")
# break # 不正な行があればこのブロックをスキップ
# if len(pattern) == 8: # ブロックが8行5列であることを確認
# flattened_pattern = np.array(pattern).flatten() # 1次元化
# # ラベルをone-hotエンコーディング
# one_hot_label = [1 if i == label else 0 for i in range(num_classes)]
# data.append((flattened_pattern, one_hot_label))
# else:
# print(f"Skipped invalid block: {block}")
# except Exception as e:
# print(f"Error processing block: {block}, Error: {e}")
# return data
# トレーニングデータの準備
def prepare_training_data(data_files, num_classes):
all_data = []
for label, file_name in enumerate(data_files):
all_data += load_training_data(file_name, label, num_classes)
np.random.shuffle(all_data) # データをランダムにシャッフル
inputs = np.array([item[0] for item in all_data])
outputs = np.array([item[1] for item in all_data])
return inputs, outputs
# ニューラルネットワークのトレーニング関数
def train_neural_network(training_inputs, training_outputs, input_size, hidden_size, output_size, learning_rate, epochs, model_file):
# 重みとバイアスの初期化
np.random.seed(42)
weights_input_hidden = np.random.uniform(-1, 1, (input_size, hidden_size))
weights_hidden_output = np.random.uniform(-1, 1, (hidden_size, output_size))
bias_hidden = np.random.uniform(-1, 1, (1, hidden_size))
bias_output = np.random.uniform(-1, 1, (1, output_size))
# トレーニングループ
for epoch in range(epochs):
# フォワードパス
hidden_layer_input = np.dot(training_inputs, weights_input_hidden) + bias_hidden
hidden_layer_output = sigmoid(hidden_layer_input)
output_layer_input = np.dot(hidden_layer_output, weights_hidden_output) + bias_output
predicted_output = sigmoid(output_layer_input)
# 誤差計算
error = training_outputs - predicted_output
# バックプロパゲーション
d_predicted_output = error * sigmoid_derivative(predicted_output)
error_hidden_layer = d_predicted_output.dot(weights_hidden_output.T)
d_hidden_layer = error_hidden_layer * sigmoid_derivative(hidden_layer_output)
# 重みとバイアスの更新
weights_hidden_output += hidden_layer_output.T.dot(d_predicted_output) * learning_rate
weights_input_hidden += training_inputs.T.dot(d_hidden_layer) * learning_rate
bias_output += np.sum(d_predicted_output, axis=0, keepdims=True) * learning_rate
bias_hidden += np.sum(d_hidden_layer, axis=0, keepdims=True) * learning_rate
if epoch % 1000 == 0:
print(f"Epoch {epoch}, Error: {np.mean(np.abs(error))}")
# モデルを保存
save_model_text(model_file, weights_input_hidden, weights_hidden_output, bias_hidden, bias_output)
# ファイル名
data_files = [f"data_{i}.txt" for i in range(3)] # 例: 3クラス (0, 1, 2) のファイル
model_file = "trained_model.json"
# ニューラルネットワークの設定
input_size = 8 * 5 # 8行5列の配列を1次元化
hidden_size = 8
output_size = len(data_files) # クラス数に応じて変更
learning_rate = 0.1
epochs = 10000
# トレーニングデータの準備
training_inputs, training_outputs = prepare_training_data(data_files, output_size)
# トレーニングの実行
train_neural_network(training_inputs, training_outputs, input_size, hidden_size, output_size, learning_rate, epochs, model_file)
data_0.txt
[0,0,1,1,0],
[1,0,0,0,1],
[1,0,0,0,1],
[1,0,0,0,1],
[1,1,1,1,1],
[1,0,0,0,1],
[1,0,0,0,1],
[1,0,0,0,1]
[0,1,1,1,0],
[1,0,0,0,1],
[1,0,0,0,1],
[1,1,1,1,1],
[1,0,0,0,1],
[1,0,0,0,1],
[1,0,0,0,1],
[1,0,0,0,0]
data_1.txt
[1,1,1,1,0],
[1,0,0,0,1],
[1,0,0,0,1],
[1,1,1,1,1],
[1,0,0,0,1],
[1,0,0,0,1],
[1,0,0,0,1],
[1,1,1,1,0]
[0,1,1,1,0],
[1,0,0,0,1],
[1,0,0,0,1],
[1,1,1,1,1],
[1,0,0,0,1],
[1,0,0,0,1],
[1,0,0,0,1],
[0,1,1,1,0]
data_2.txt
[0,1,1,1,0],
[1,0,0,0,1],
[1,0,0,0,0],
[1,0,0,0,0],
[1,0,0,0,0],
[1,0,0,0,0],
[1,0,0,0,1],
[0,1,1,1,0]
[0,1,1,1,1],
[1,0,0,0,1],
[1,0,0,0,1],
[1,0,0,0,0],
[1,0,0,0,0],
[1,0,0,0,1],
[0,0,0,0,1],
[0,1,1,1,0]
推論の実施
モデルtrained_model.jsonを読み込んで、data_check.txtの確認用データを推論します。
import numpy as np
import json
import matplotlib.pyplot as plt
# シグモイド関数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# モデルの読み込み関数
def load_model_text(file_name):
with open(file_name, "r") as f:
model_data = json.load(f)
print(f"Model loaded from {file_name}")
hidden_layer_weights = np.array([neuron["weights"] for neuron in model_data["hidden_layer"].values()]).T
hidden_layer_bias = np.array([[neuron["bias"] for neuron in model_data["hidden_layer"].values()]])
output_layer_weights = np.array([neuron["weights"] for neuron in model_data["output_layer"].values()]).T
output_layer_bias = np.array([[neuron["bias"] for neuron in model_data["output_layer"].values()]])
return hidden_layer_weights, output_layer_weights, hidden_layer_bias, output_layer_bias
# ファイルから8行5列のビットデータを読み込む関数
def load_test_data(file_name):
test_data = []
with open(file_name, "r") as f:
blocks = f.read().strip().split("\n\n") # 空白行で区切る
for block in blocks:
try:
# 各ブロックを8行5列のリストとして読み込む
pattern = [list(map(int, line.strip("[],\n ").split(","))) for line in block.split("\n") if line.strip()]
if len(pattern) == 8 and all(len(row) == 5 for row in pattern):
flattened_pattern = np.array(pattern).flatten() # 1次元化
test_data.append(flattened_pattern)
else:
print(f"Skipped invalid block: {block}")
except ValueError as e:
print(f"Error processing block: {block}, Error: {e}")
return test_data
# パターン表示関数
def display_pattern(pattern, title=""):
pattern_reshaped = np.array(pattern).reshape(8, 5) # 8行5列に変換
plt.imshow(pattern_reshaped, cmap="Greys", interpolation="nearest")
plt.title(title)
plt.axis("off")
plt.show()
# モデルを読み込む
weights_input_hidden, weights_hidden_output, bias_hidden, bias_output = load_model_text("trained_model.json")
# テストデータを読み込む
test_data = load_test_data("data_check.txt") # テストファイルを指定
if not test_data:
print("No valid test data found.")
else:
for idx, test_input in enumerate(test_data):
# フォワードパス
test_input = np.array(test_input).reshape(1, -1) # 1次元配列を2次元配列に変換
hidden_layer_input = np.dot(test_input, weights_input_hidden) + bias_hidden
hidden_layer_output = sigmoid(hidden_layer_input)
output_layer_input = np.dot(hidden_layer_output, weights_hidden_output) + bias_output
predicted_output = sigmoid(output_layer_input)
# 推論結果を表示
display_pattern(test_input.flatten(), title=f"Test Input {idx + 1}")
print(f"Test Input {idx + 1}: Predicted Output (Raw):", predicted_output)
# 最も確率の高いクラスを判定
predicted_class = np.argmax(predicted_output)
confidence = predicted_output[0][predicted_class] # 最も高い確率
print(f"Test Input {idx + 1}: Predicted Class: {predicted_class} with confidence {confidence:.2f}")
結果
1
confidence 0.96
2
confidence 0.97
3
confidence 0.95
data_check.txt
[0,1,1,1,0],
[1,0,0,0,1],
[0,0,0,0,1],
[1,1,1,1,1],
[1,0,0,0,1],
[0,0,0,0,1],
[1,0,0,0,1],
[1,0,0,0,0]
[0,1,1,1,0],
[1,0,0,0,1],
[0,0,0,0,1],
[1,0,1,1,1],
[1,0,0,0,1],
[1,0,0,0,1],
[1,0,0,0,1],
[0,1,1,1,0]
[0,0,1,1,1],
[1,0,0,0,1],
[1,0,0,0,1],
[1,0,0,0,0],
[0,0,0,0,0],
[1,0,0,0,1],
[1,0,0,0,1],
[0,1,1,1,0]
追加学習(ファインチューニング)
学習したモデルと、追加したい学習データを用いて追加学習を行います。
仕様:元の学習データに_rをつけたファイルを用意して、データを入力します。
追加データのないファイルでも空で用意します。
追加学習したモデルは、trained_model_r.jsonのように_r付きで出力されます。
このモデルで推論する場合は、上記の推論部のコードの参照モデルを「trained_model_r.json」とします。
import numpy as np
import json
import os
# シグモイド関数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# シグモイド関数の微分
def sigmoid_derivative(x):
return x * (1 - x)
# ニューロン情報付きモデルの保存関数
def save_model_text(file_name, weights_input_hidden, weights_hidden_output, bias_hidden, bias_output):
model_data = {
"hidden_layer": {
f"neuron_{i}": {
"weights": weights_input_hidden[:, i].tolist(),
"bias": bias_hidden[0][i]
}
for i in range(weights_input_hidden.shape[1])
},
"output_layer": {
f"neuron_{i}": {
"weights": weights_hidden_output[:, i].tolist(),
"bias": bias_output[0][i]
}
for i in range(weights_hidden_output.shape[1])
}
}
with open(file_name, "w") as f:
json.dump(model_data, f, indent=4)
print(f"Model saved to {file_name}")
# モデルの読み込み関数
def load_model_text(file_name):
with open(file_name, "r") as f:
model_data = json.load(f)
print(f"Model loaded from {file_name}")
hidden_layer_weights = np.array([neuron["weights"] for neuron in model_data["hidden_layer"].values()]).T
hidden_layer_bias = np.array([[neuron["bias"] for neuron in model_data["hidden_layer"].values()]])
output_layer_weights = np.array([neuron["weights"] for neuron in model_data["output_layer"].values()]).T
output_layer_bias = np.array([[neuron["bias"] for neuron in model_data["output_layer"].values()]])
return hidden_layer_weights, output_layer_weights, hidden_layer_bias, output_layer_bias
# ファイルからトレーニングデータを読み込む関数
def load_training_data(file_name, label, num_classes):
data = []
if not os.path.exists(file_name) or os.path.getsize(file_name) == 0: # ファイルが空または存在しない場合
return data # 空リストを返す
with open(file_name, "r") as f:
blocks = f.read().strip().split("\n\n")
for block in blocks:
pattern = [list(map(int, line.strip("[],\n").split(","))) for line in block.split("\n")]
flattened_pattern = np.array(pattern).flatten()
one_hot_label = [1 if i == label else 0 for i in range(num_classes)]
data.append((flattened_pattern, one_hot_label))
return data
# トレーニングデータの準備
def prepare_training_data(data_files, num_classes):
all_data = []
for label, file_name in enumerate(data_files):
all_data += load_training_data(file_name, label, num_classes)
np.random.shuffle(all_data)
inputs = np.array([item[0] for item in all_data])
outputs = np.array([item[1] for item in all_data])
return inputs, outputs
# ニューラルネットワークのトレーニング関数
# def train_neural_network(training_inputs, training_outputs, weights_input_hidden, weights_hidden_output, bias_hidden, bias_output, learning_rate, epochs, model_file):
# for epoch in range(epochs):
# # フォワードパス
# hidden_layer_input = np.dot(training_inputs, weights_input_hidden) + bias_hidden
# hidden_layer_output = sigmoid(hidden_layer_input)
# output_layer_input = np.dot(hidden_layer_output, weights_hidden_output) + bias_output
# predicted_output = sigmoid(output_layer_input)
# # 誤差計算
# error = training_outputs - predicted_output
# # バックプロパゲーション
# d_predicted_output = error * sigmoid_derivative(predicted_output)
# error_hidden_layer = d_predicted_output.dot(weights_hidden_output.T)
# d_hidden_layer = error_hidden_layer * sigmoid_derivative(hidden_layer_output)
# # 重みとバイアスの更新
# weights_hidden_output += hidden_layer_output.T.dot(d_predicted_output) * learning_rate
# weights_input_hidden += training_inputs.T.dot(d_hidden_layer) * learning_rate
# bias_output += np.sum(d_predicted_output, axis=0, keepdims=True) * learning_rate
# bias_hidden += np.sum(d_hidden_layer, axis=0, keepdims=True) * learning_rate
# if epoch % 1000 == 0:
# print(f"Epoch {epoch}, Error: {np.mean(np.abs(error))}")
# # 出力ファイル名を更新し保存
# output_model_file = model_file.replace(".json", "_r.json")
# save_model_text(output_model_file, weights_input_hidden, weights_hidden_output, bias_hidden, bias_output)
def train_neural_network(training_inputs, training_outputs, weights_input_hidden, weights_hidden_output, bias_hidden, bias_output, learning_rate, epochs, model_file):
if training_inputs.size == 0 or training_outputs.size == 0: # データが空の場合
print("No training data provided. Skipping training.")
return # 学習をスキップ
for epoch in range(epochs):
# フォワードパス
hidden_layer_input = np.dot(training_inputs, weights_input_hidden) + bias_hidden
hidden_layer_output = sigmoid(hidden_layer_input)
output_layer_input = np.dot(hidden_layer_output, weights_hidden_output) + bias_output
predicted_output = sigmoid(output_layer_input)
# 誤差計算
error = training_outputs - predicted_output
# バックプロパゲーション
d_predicted_output = error * sigmoid_derivative(predicted_output)
error_hidden_layer = d_predicted_output.dot(weights_hidden_output.T)
d_hidden_layer = error_hidden_layer * sigmoid_derivative(hidden_layer_output)
# 重みとバイアスの更新
weights_hidden_output += hidden_layer_output.T.dot(d_predicted_output) * learning_rate
weights_input_hidden += training_inputs.T.dot(d_hidden_layer) * learning_rate
bias_output += np.sum(d_predicted_output, axis=0, keepdims=True) * learning_rate
bias_hidden += np.sum(d_hidden_layer, axis=0, keepdims=True) * learning_rate
if epoch % 1000 == 0:
print(f"Epoch {epoch}, Error: {np.mean(np.abs(error))}")
# 出力ファイル名を更新し保存
output_model_file = model_file.replace(".json", "_r.json")
save_model_text(output_model_file, weights_input_hidden, weights_hidden_output, bias_hidden, bias_output)
# 元データファイルと追加データファイルの準備
additional_files = [f"data_{i}_r1.txt" for i in range(3)] # 追加データファイル
# モデルファイル
model_file = "trained_model.json"
# モデルを読み込む
weights_input_hidden, weights_hidden_output, bias_hidden, bias_output = load_model_text(model_file)
# トレーニングデータの準備(追加データのみ)
training_inputs, training_outputs = prepare_training_data(additional_files, len(additional_files))
# 追加学習の実行
learning_rate = 0.1
epochs = 10000
train_neural_network(training_inputs, training_outputs, weights_input_hidden, weights_hidden_output, bias_hidden, bias_output, learning_rate, epochs, model_file)
githubデータ
GitHub - WOCae/E112
Contribute to WOCae/E112 development by creating an account on GitHub.
コメント