ニューラルネットワークの一般的な処理は次のとおりです。
- 学習可能なパラメータのネットワーク構造を定義します(レイヤーのスタックとレイヤーデザイン)。
- データセットの作成と入力。
- 入力を処理します(定義されたネットワーク層によって処理されます)。これは主にネットワークの順方向伝搬に反映されます。
- 損失を計算します。これは、損失レイヤーによって計算されます。
- 勾配を見つけるための逆伝播。
- 勾配に従ってパラメータ値を変更します。実装する最も簡単な方法(SGD)は次のとおりです
。weight= weight-learning_rate * gradient
pytorchとauto_grad(トーチ自動派生関数)を使用します。
import torch
#import numpy
#from torch.autograd import Variable
EPOCH = 500
LEARNING_RATE = 1e-6
N , D_in , H , D_out = 64 , 1000, 100 , 10
# N代表的是样本个数,D_in是样本的维度,H是隐藏层的维度,D_out是输出层的维度
X = torch.randn(N,D_in)
Y = torch.randn(N,D_out)
# 先用随机值初始化两层神经网络的权重
w1 = torch.randn(D_in,H,requires_grad=True)
w2 = torch.randn(H,D_out,requires_grad=True)
"""h = w1 * x
h_relu = relu(h)
y = w2 * x"""
for step in range(EPOCH):
#前向传播
h = torch.mm(X, w1) # 隐层 h = w1 * x
h_relu = h.clamp(min=0) # relu 将小于0的部分修正为0 大于0的部分则不变
y_pred = torch.mm(h_relu, w2) # 输出层 y = w2 * h_relu
# 损失函数计算误差
loss = (y_pred - Y).pow(2).sum()
if step % 100 == 0:
print('epoch: {} loss: {:.5f}'.format(step, loss.item()))#loss为(1,)的tensor
# 反向传播 计算导数
loss.backward() # 会自动计算所有参数的导数(包括W1、W2、X)
#更新参数
with torch.no_grad():
#随机梯度下降
w1 -= LEARNING_RATE * w1.grad
w2 -= LEARNING_RATE * w2.grad
#更新完梯度之后要手动置0。不置0会一直叠加
w1.grad.zero_()
w2.grad.zero_()
pytorchを使用します(逆伝播には独自の派生が必要です):
import torch
EPOCH = 500
LEARNING_RATE = 1e-6
#超参数初始化
N , D_in , H , D_out = 64 , 1000, 100 , 10 # N代表的是样本个数,D_in是样本的维度,H是隐藏层的维度,D_out是输出层的维度
#训练数据和参数初始化
X = torch.randn(N,D_in)
Y = torch.randn(N,D_out)
# 先用随机值初始化两层神经网络的权重
w1 = torch.randn(D_in,H)
w2 = torch.randn(H,D_out)
#print("X:",X,"Y:",Y,w1,w2)
for step in range(500):
#前向传播
h = X.mm(w1) #(N,H)
h_relu = h.clamp(min=0)#(N,H)
y_pred = h_relu.mm(w2) #(N,D_out)
#定义损失函数
loss = (y_pred - Y).pow(2).sum().item()
if step % 100 == 0:
print('epoch: {} loss: {:.5f}'.format(step, loss))#loss为(1,)的tensor
#反向传播
grad_y_pred = 2.0 * (y_pred - Y)#(N,D_out)
grad_w2 = h_relu.t().mm(grad_y_pred)#(H,D_out)
grad_h_relu = grad_y_pred.mm(w2.t())#(N,H)
grad_h[h > 0] = grad_h_relu[h > 0].clone()#大于0时导数不变
grad_h[h < 0] = 0#小于0时导数变0
grad_w1 = X.t().mm(grad_h)#要grad_w1的矩阵维度和w1维度相同,才能相减
#参数更新
w1 -= LEARNING_RATE * grad_w1
w2 -= LEARNING_RATE * grad_w2
このように書くと、逆伝播の導出が最大の難しさです。式を導出するために順方向伝搬と逆方向伝搬を理解してから、コードを使用して式を実装する必要があります。逆伝播の計算方法を理解するには、Wu Endaの機械学習ビデオの最初の3つの章(コスト関数と勾配の導出)とニューラルネットワークの部分を見るのが最善です。しかし、そのビデオのアクティベーション機能は異なります。このコードでrelu関数の逆伝播を実現する必要があります。
ここに私は手書きの導出プロセスを投稿しました:
以下は、次元から理解するために、ニューラルネットワークのいくつかのテンサーの出力です
import torch
lr = 1e-6
EPOCH = 500
LEARNING_RATE = 1e-6
#超参数初始化
N , D_in , H , D_out = 3 , 4, 2 ,1 # N代表的是样本个数,D_in是样本的维度,H是隐藏层的维度,D_out是输出层的维度
#训练数据和参数初始化
X = torch.randn(N,D_in)
Y = torch.randn(N,D_out)
# 先用随机值初始化两层神经网络的权重
w1 = torch.randn(D_in,H)
w2 = torch.randn(H,D_out)
print("X:",X)#3样本 4特征
print("Y:",Y)#3结果
print("w1:",w1)
print("w2",w2)
h = X.mm(w1)
print("h:",h)
h_relu = h.clamp(min=0)#(N,h_dim)
print("h_relu",h_relu)
経営成績と個人的な理解を添付してください。
X: tensor([[ 1.3393, -0.3668, -0.3531, 1.4490],
[-0.2834, 0.3056, 1.0691, 1.7448],
[ 0.1956, 0.9079, 0.4525, -1.1220]])
Y: tensor([[-1.8117],
[-0.4406],
[ 1.1850]])
w1: tensor([[ 1.4459, -0.1429],
[-0.8366, -0.5614],
[-1.4148, -0.4373],
[ 0.4911, -1.1529]])
w2 tensor([[-0.6083],
[-0.2623]])
h: tensor([[ 3.4545, -1.5016],
[-1.3210, -2.6101],
[-1.6679, 0.5581]])
h_relu tensor([[3.4545, 0.0000],
[0.0000, 0.0000],
[0.0000, 0.5581]])
- ニューラルネットワークの概略図は、変数ではなく、単位としての特徴(寸法)に基づいています。
- Xには3つの変数があり、各変数には4つの特性(次元)があります。W1には、4つの機能のそれぞれに2つの重みがあります
- 隠れ層には3つの変数と2つの単位(寸法)があります
- 変数×重み1の4つの特徴を追加した後、隠れ層ユニットの対応する変数の特徴値1が取得されます。
- 変数×重み2の4つの特徴を追加した後、隠れ層ユニットの対応する変数の特徴値2が取得されます。
参照:
- ウーエンダ機械学習ビデオ:https://www.bilibili.com/video/av50747658?from = search&seid = 8008773056378130405
- https://blog.csdn.net/qq_30057549/article/details/103018003
- Wu Endaの機械学習ビデオに関する個人的なメモ(次の記事が公開され、Huang Haiguang博士から参照が変更されました)
やっと
実は、これは年初の1月に行われたもので、久しぶりです。今考えてみると、これはまだ入門的な深層学習のベストプラクティスの1つです。入門的な深層学習の最初のコードはこれでなければなりません。
その後、Enda Wuの機械学習ビデオは、今年の前半に終了しました。HaiguangHuang博士のブログにあるEndaWu機械学習ノートを少し変更しました。
しかし、その後、ローカルのマークダウンブログをcsdnに直接表示できず、内部の写真を送信することが困難であることが発見されました。更新されません。必要に応じてご連絡ください。