GPT-2: ショートストーリー: GPT-2: 東京の郊外にある中学校、その校舎の片隅にひっそりと存在するコンピュータークラブ。主人公の中学1年生、タケルはこのクラブに所属している。タケルは他の部員が放課後に遊びに行く中、一人でコンピューターに向かっていた。彼は、自宅から持ってきた小さなgpuを搭載したパソコンを前に、静かにキーを叩いていた。タケツの穴から、彼の顔が覗き込まれている。その顔は、まるで、自分の顔のように、大きく、そして、小さく、歪んでいる。 タタツは、「この顔、なんか、変だな」と、思っていた。しかし、彼は、「顔の歪み」を、気にしていた。 「顔」は「顔立ち」ではなく、「表情」である。
(若き日のチャットGPTはこんなだったということです。でもこれはこれでよい。)
GPT-4: ショートストーリー: 1億もの調整可能なパラメーターを持つ巨大なニューラルネットワークを動かしたらどうなるんだろう?
東京の郊外にある中学校、その校舎の片隅にひっそりと存在するコンピュータークラブ。主人公の中学1年生、タケルはこのクラブに所属している。タケルは他の部員が放課後に遊びに行く中、一人でコンピューターに向かっていた。彼は、自宅から持ってきた小さなGPUを搭載したパソコンを前に、静かにキーを叩いていた。
タケルは、最近夢中になっているニューラルネットワークの実験に取り組んでいた。彼は「もし、1億もの調整可能なパラメーターを持つ巨大なニューラルネットワークを動かしたらどうなるんだろう?」という好奇心に突き動かされていた。もちろん、自分の小さなGPUマシンがそんな負荷に耐えられるとは思っていなかったが、どうしても試してみたかった。
「これで準備完了だ…」
彼は息を飲みながら最後のコマンドを入力し、Enterキーを押した。
途端に、コンピューターのファンが急に回転を上げ、うなり声を上げ始めた。GPUがフル稼働し、巨大な重み行列を計算しようとしている。タケルの手は緊張で汗ばみ、彼はモニターをじっと見つめていた。
「動いてくれ…!」
だが、すぐに異変が起きた。モニターに映る計算の進捗バーがほんの少ししか進んでいないのに、コンピューターが悲鳴を上げ始めた。GPUの負荷は限界を超えていた。画面がちらつき、計算コアが次々と焼きつき始めた。タケルはその異音を聞きながら、恐怖と興奮が入り混じる感情に包まれていた。
「頼む…もう少しだけ持ってくれ!」
しかし、焼きつく音は止まらない。タケルの小さなGPUマシンは、文字通り限界を超えていた。彼の手は自然と拳を握りしめ、祈るような気持ちでモニターを見つめた。
ついに、最後の計算が終わりかけたその瞬間、モニターに結果が映し出された。完璧に収束した計算結果が輝くように現れた。
「やった…!」
だが、その直後、GPUが静かに沈黙した。タケルは画面を見つめながら呆然と立ち尽くしていた。コンピューターはもう動かない。全ての計算コアが焼きつき、完全に停止してしまったのだ。
タケルは静かに深呼吸をした。彼の小さなGPUマシンは、最後の力を振り絞って計算結果を出してくれた。そして、それは彼の小さな勝利だった。
「また、作り直すしかないな…」
そうつぶやきながらも、彼の目には確かな輝きがあった。次に挑戦する時のことをすでに考えていたのだ。
タケルの挑戦は終わらない。
TensorFlow.jsとHTMLを使用して、入力サイズが2000のシンプルな2層のニューラルネットワークを構築し、重み行列のサイズを段階的に増やし、ロスと処理時間をプロットするコードです。
コードをメモ帳などのテキストエディタに貼り付け、ファイルを「index.html」などの拡張子が.htmlのファイルとして保存します。その後、保存したファイルをブラウザで開けば、コードが実行されます。
F12でコンソールが開きます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Neural Network with TensorFlow.js</title>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
</head>
<body>
<h2>TensorFlow.jsでニューラルネットワークをトレーニングする</h2>
<button onclick="trainModel(3000)">3,000ニューロンでトレーニング</button>
<button onclick="trainModel(4000)">4,000ニューロンでトレーニング</button>
<button onclick="trainModel(5000)">5,000ニューロンでトレーニング</button>
<canvas id="lossChart" width="400" height="200"></canvas>
<script>
// トレーニング用のランダムな合成データを生成(入力と出力の次元数は2000)
const dataSize = 5000; // データのサンプルサイズ
const inputDim = 2000; // 入力次元
const outputDim = 2000; // 出力次元
const inputData = tf.randomNormal([dataSize, inputDim]); // 入力データ
const outputData = tf.randomNormal([dataSize, outputDim]); // 出力データ
// モデルを作成してトレーニングする関数
async function trainModel(hiddenLayerSize) {
// 既存のチャートをクリア
const ctx = document.getElementById('lossChart').getContext('2d');
// 既存のチャートインスタンスを破棄
if (chart) {
chart.destroy();
}
// ニューラルネットワークモデルを定義
const model = tf.sequential();
model.add(tf.layers.dense({inputShape: [inputDim], units: hiddenLayerSize, activation: 'relu'})); // 隠れ層1
model.add(tf.layers.dense({units: hiddenLayerSize, activation: 'relu'})); // 隠れ層2
model.add(tf.layers.dense({units: outputDim, activation: 'linear'})); // 出力層
// モデルをコンパイル
model.compile({
optimizer: tf.train.adam(),
loss: 'meanSquaredError'
});
// モデルをトレーニングし、ロス値を収集してプロット
const losses = [];
await model.fit(inputData, outputData, {
epochs: 10,
batchSize: 32,
callbacks: {
onEpochEnd: (epoch, logs) => {
console.log(`Epoch ${epoch + 1}: loss = ${logs.loss}`);
losses.push(logs.loss);
plotLossChart(losses); // ロスをプロット
}
}
});
}
// トレーニングロスをCanvasにプロットする関数
function plotLossChart(losses) {
const ctx = document.getElementById('lossChart').getContext('2d');
// 既存のチャートインスタンスを破棄
if (chart) {
chart.destroy();
}
const chartData = {
labels: Array.from({length: losses.length}, (_, i) => i + 1), // エポック数
datasets: [{
label: 'トレーニングロス',
data: losses, // ロスデータ
borderColor: 'blue',
fill: false
}]
};
// 新しいチャートインスタンスを作成
chart = new Chart(ctx, {
type: 'line',
data: chartData,
options: {
responsive: true,
scales: {
x: {
title: {
display: true,
text: 'エポック'
}
},
y: {
title: {
display: true,
text: 'ロス'
}
}
}
}
});
}
// グローバル変数としてチャートのインスタンスを保持
let chart = null;
</script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</body>
</html>
モデル作成:
tf.sequential()でシンプルな2層のニューラルネットワークを作成し、入力サイズ2000に対して、異なるサイズの出力層を持つネットワークを構築しています。
トレーニングと評価:
model.fit()を使用して、ランダムに生成したダミーデータを使ってモデルを訓練しています。
それぞれの出力サイズでのロス値とトレーニングにかかった時間を記録します。
結果のプロット:
Chart.jsを使用して、出力サイズごとのロスとトレーニング時間をプロットしています。