はじめに: ニューラル ネットワークとは
Le 人工ニューラルネットワーク それらは現代の深層学習の基礎を表しています。 人間の脳の構造にインスピレーションを得たこれらの計算アーキテクチャは、次のことが可能です。 と呼ばれる反復的な最適化プロセスを通じてデータから複雑なパターンを学習します。 バックプロパゲーション。画像分類から機械翻訳まで、 ニューラル ネットワークは、世界で最も先進的な人工知能アプリケーションを強化します。
このシリーズの最初の記事では ディープラーニングとニューラルネットワーク、出発します 歴史的な起源から パーセプトロン (1958) 基本的な概念に到達する ネットワークが学習できるようにするもの: 重み、バイアス、活性化関数、勾配降下 そしてバックプロパゲーション。最後に、Python と PyTorch でニューラル ネットワークを最初から実装します。
何を学ぶか
- ニューラル ネットワークの歴史: パーセプトロンから現代の深層学習まで
- ニューラル ネットワークのアーキテクチャ: 入力層、隠れ層、出力層
- 活性化関数: ReLU、Sigmoid、Tanh、および視覚的比較
- バックプロパゲーション: ネットワークが勾配を計算し、重みを更新する方法
- 損失関数: さまざまなタスクの MSE とクロスエントロピー
- NumPy と PyTorch での実際の実装
パーセプトロン: 最初の人工ニューロン
1958 年にフランク ローゼンブラットは パーセプトロン、最初のニューロン モデル 人工的な。このアイデアはシンプルですが革命的でした。数値入力を受け取る計算ユニットです。 それらを神で増やす 重み (重み付け)、結果を加算し、バイナリ出力を生成します。 閾値関数を介して。
数学的には、パーセプトロンは次のように計算します。
# Percettrone semplice in Python
import numpy as np
class Perceptron:
def __init__(self, n_inputs, learning_rate=0.01):
self.weights = np.random.randn(n_inputs)
self.bias = 0.0
self.lr = learning_rate
def predict(self, x):
"""Forward pass: somma pesata + soglia"""
linear_output = np.dot(x, self.weights) + self.bias
return 1 if linear_output >= 0 else 0
def train(self, X, y, epochs=100):
"""Regola di apprendimento del percettrone"""
for _ in range(epochs):
for xi, yi in zip(X, y):
prediction = self.predict(xi)
error = yi - prediction
self.weights += self.lr * error * xi
self.bias += self.lr * error
# Esempio: AND gate
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([0, 0, 0, 1])
p = Perceptron(n_inputs=2)
p.train(X, y, epochs=50)
print([p.predict(xi) for xi in X]) # [0, 0, 0, 1]
パーセプトロンは問題に対して非常に効果的です 線形分離可能 AND や OR のように。 しかし、1969 年にミンスキーとパパートは、単一のパーセプトロンでは問題を解決できないことを証明しました。 問題 XOR、クラスが直線で分離できない場合。この発見は ニューラル ネットワークの研究は 10 年以上にわたって停滞しました。 のAI冬.
XOR の限界とディープラーニングの必要性
XOR 問題はそれらが必要であることを証明しました 複数の層 (非表示レイヤー) を解決する 非線形の問題。この直感が開発につながりました。 多層パーセプトロン (MLP) そして数十年後、現代のディープラーニングへ。今日では、隠れ層を 1 つだけ追加するだけでも、 非線形活性化関数、ニューラル ネットワークは任意の連続関数を近似できます (普遍近似定理)。
ニューラル ネットワークのアーキテクチャ: レイヤーとニューロン
ニューラル ネットワークは次のように構成されます。 レイヤー 相互接続されたニューロンの(層)。アーキテクチャ クラシックには 3 種類のレイヤーが含まれています。
- 入力層:生データを受信します。各ニューロンはデータセットの特徴を表します (例: 画像のピクセル、テキストの単語)
- 非表示レイヤー: 処理が行われる 1 つ以上の中間層。各ニューロンは前の層から入力を受け取り、重みとバイアスを適用し、その結果を活性化関数に渡します。
- 出力層: 最終的な予測を生成します。二項分類の場合: シグモイドを持つ 1 つのニューロン。マルチクラスの場合: ソフトマックスを備えた N 個のニューロン
Il フォワードパス データが入力から出力に流れるプロセス すべてのレイヤー。各ニューロンの計算は、入力の加重和、バイアスの加算という 3 つのステップに従います。 そして活性化関数の適用。
活性化関数: ReLU、Sigmoid、Tanh
Le 活性化関数 ネットワークに非線形性が導入され、ネットワークに次のことが可能になります。 データの複雑な関係を学びます。これらがなければ、N 層のネットワークは次のものと同等になります。 深さに関係なく、単一の線形レイヤー。
シグモイド
機能 シグモイド (0, 1) の範囲内の任意の値を圧縮します。歴史的に 現在標準のアクティベーションとして使用されており、主に分類用の出力層で使用されています。 バイナリ。その主な問題は、 消失勾配: 非常に高い値の場合 または非常に低い場合、勾配はほぼゼロになり、学習が大幅に遅くなります。
タン
機能 タン (双曲線正接) 範囲 (-1, 1) の値をマップします。 ゼロを中心とするため、シグモイドよりも強い勾配が得られるため、隠れ層での使用に適しています。 ただし、極値に対する勾配消失の問題にも悩まされます。
ReLU (整流線形ユニット)
ReLU そして現代の深層学習で最も広く使用されている活性化関数です。 その式は非常に単純です: f(x) = max(0, x)。利点は数多くあります。効率的な計算、 正の値に対して勾配が消えることはなく、スパース表現が促進されます。唯一の人 デメリットと問題点 死んだニューロン (瀕死の ReLU): 受信ニューロン 負の入力は常に学習を停止します。
import numpy as np
import matplotlib.pyplot as plt
# Implementazione delle funzioni di attivazione
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def tanh(x):
return np.tanh(x)
def relu(x):
return np.maximum(0, x)
def leaky_relu(x, alpha=0.01):
return np.where(x > 0, x, alpha * x)
# Derivate per backpropagation
def sigmoid_derivative(x):
s = sigmoid(x)
return s * (1 - s)
def relu_derivative(x):
return np.where(x > 0, 1, 0)
# Confronto visivo
x = np.linspace(-5, 5, 200)
fig, axes = plt.subplots(1, 4, figsize=(16, 4))
for ax, func, name in zip(axes, [sigmoid, tanh, relu, leaky_relu],
['Sigmoid', 'Tanh', 'ReLU', 'Leaky ReLU']):
ax.plot(x, func(x), linewidth=2)
ax.set_title(name)
ax.grid(True, alpha=0.3)
ax.axhline(y=0, color='k', linewidth=0.5)
ax.axvline(x=0, color='k', linewidth=0.5)
plt.tight_layout()
plt.savefig('activation_functions.png', dpi=150)
損失関数: 測定誤差
La 損失関数 (損失関数) ネットワークがどの程度予測するかを定量化します。 実際の値から逸脱します。トレーニング中の学習を促進するのはエラー信号です。
MSE (平均二乗誤差)
問題に使用される 回帰、MSE は、次の二乗の平均を計算します。 予測値と実際の値の差。大きなエラーにさらにペナルティを課し、センシティブになります 外れ値に。
クロスエントロピー
問題について 分類、クロスエントロピーは、 予測された確率分布と実際の確率分布。二項分類の場合、 バイナリクロスエントロピー、マルチクラスlaの場合 カテゴリカルクロスエントロピー。 ネットワークが非常に安全であるが間違っており、加速している場合、クロスエントロピーはより強い勾配を生成します。 修正。
バックプロパゲーション: ネットワークがどのように学習するか
La バックプロパゲーション (誤差逆伝播) と基本的なアルゴリズム ニューラルネットワークが学習できるようになります。 1986年にルメルハート、ヒントン、ウィリアムズによって発明されました。 を適用します 連鎖ルール 微分積分の勾配を計算する ネットワークの各重みに対する損失関数の値。
このプロセスは 4 つのフェーズに分かれています。
- フォワードパス: データは入力から出力までネットワークを流れ、各層の活性化を計算します。
- 損失の計算: 予測出力と実際の値との誤差を測定します。
- バックワードパス: 勾配は出力から入力に向かって計算され、誤差が逆方向に伝播されます。
- 重みの更新: 各重みは、学習率に比例して、勾配とは反対の方向に変更されます。
勾配降下法: 基本的なオプティマイザー
Il 勾配降下法 次の式に従って重みを更新します: w = w - lr * dL/dw。 最新の亜種には次のものがあります。 勢いのあるシンガポールドル (その方向に速度を上げる 勾配の)、 アダム (各パラメータの適応学習率) e アダム・W (正しい体重減衰を持つアダム)。 Adam とデフォルトのオプティマイザー ほとんどの深層学習アプリケーションで。
完全な実装: PyTorch での MLP
を実装してすべてをまとめてみましょう 多層パーセプトロン 分類用 PyTorch を使用した手書き数字 (MNIST データセット):
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
# Definizione del modello MLP
class MLP(nn.Module):
def __init__(self, input_size=784, hidden_sizes=[256, 128], num_classes=10):
super().__init__()
self.flatten = nn.Flatten()
self.network = nn.Sequential(
nn.Linear(input_size, hidden_sizes[0]),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(hidden_sizes[0], hidden_sizes[1]),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(hidden_sizes[1], num_classes)
)
def forward(self, x):
x = self.flatten(x)
return self.network(x)
# Setup dataset e dataloader
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
train_dataset = datasets.MNIST('./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST('./data', train=False, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=1000, shuffle=False)
# Training
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = MLP().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
for epoch in range(10):
model.train()
total_loss = 0
for batch_x, batch_y in train_loader:
batch_x, batch_y = batch_x.to(device), batch_y.to(device)
optimizer.zero_grad()
output = model(batch_x)
loss = criterion(output, batch_y)
loss.backward()
optimizer.step()
total_loss += loss.item()
# Valutazione
model.eval()
correct = 0
with torch.no_grad():
for batch_x, batch_y in test_loader:
batch_x, batch_y = batch_x.to(device), batch_y.to(device)
output = model(batch_x)
pred = output.argmax(dim=1)
correct += (pred == batch_y).sum().item()
accuracy = 100. * correct / len(test_dataset)
print(f'Epoch {epoch+1}: Loss={total_loss/len(train_loader):.4f}, '
f'Accuracy={accuracy:.2f}%')
このモデルは約 98%の精度 10 エポック後の MNIST 上。ネットワークには、 2 つの隠れ層 (256 ニューロンと 128 ニューロン)、活性化として ReLU を使用し、正則化にドロップアウトを使用し、 学習率 0.001 の Adam オプティマイザー。
ディープラーニング: 複数のレイヤーが機能する理由
Il ディープラーニング ネットワークを使用する点で従来の機械学習とは異なります。 多くの隠れ層があります。しかし、なぜ深さがそれほど重要なのでしょうか?
答えは次のとおりです 機能の階層的構成。各層は次のことを学びます 抽象化レベルを上げながらパターンを認識します。
- レイヤー1: エッジ、グラデーション、単純なテクスチャを検出します
- レイヤー2: エッジを幾何学的形状 (コーナー、カーブ) に結合します。
- レイヤー3:物体の一部(目、車輪、窓)を認識します。
- レイヤー4+: 完全なオブジェクトと複合シーンを識別します
この表現の階層が、ディープネットワークが次のようなものになる理由です。 レスネット (152 レイヤー) 画像分類において超人的なパフォーマンスを達成できますが、 単一のレイヤーでは同じ複雑さを捉えることはできません。
ただし、深さには課題も伴います。 消失勾配 難しくする エラー信号は多くの層を通過すると減衰するため、非常に深いネットワークを学習させることはできません。 最新のソリューションには以下が含まれます 接続をスキップする (レスネット)、 バッチ正規化 より安定した勾配を維持する ReLU のような活性化関数。
シリーズの次のステップ
- 次の記事では、 畳み込みニューラル ネットワーク (CNN)、コンピュータビジョンに革命をもたらしたアーキテクチャ
- 畳み込みとプーリングを使用して画像から空間特徴を抽出する方法を見ていきます。
- VGG や ResNet などの古典的なアーキテクチャを PyTorch に実装します







