1.个人理解
对于无限多的模型,显然不可能所有模型均为线性关系,多层感知机正是为了克服线性回归的局限性而引入的,同时多层感知机引入了隐藏层,也可以称作中间层,对隐藏层使用激活函数来破坏线性关系。激活函数一定用在隐藏层,输入数据和输出数据均不使用激活函数。
激活函数目前遇到三种:
(1).ReLU激活函数:
(2).sigmoid激活函数:
(3).tanh激活函数:
本多层感知机的实现和上一个softmax regression的实现过程基本一致,最大的区别体现在net中加入了隐藏层,并且对隐藏层使用了激活函数进行处理。
2.数字标签转换为文本标签
#导出文本标签
def get_labels(labels):
#返回文本标签
text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
return [text_labels[i] for i in labels]
3.定义激活函数
#激活函数
def relu(X):
a = torch.zeros_like(X)
return torch.max(a,X)
torch.zeros_like(x),返回与x的shape一致的全0张量
4.定义softmax函数
#softmax函数
def softmax(X):
X_exp = torch.exp(X)
X_exp_sum = X_exp.sum(axis=1,keepdims=True)
return X_exp/X_exp_sum
5.定义网络
#net
def net(X,W1,W2,b1,b2):
X = X.reshape(-1,W1.shape[0])
H = relu(X@W1+b1) #hidden
return softmax(H@W2+b2) #输出
对x进行reshape,一行表示一个数据。
隐藏层使用激活函数,最终输出需经过softmax函数处理
6.交叉熵损失
#交叉熵损失
def cross(y_hat,y):
loss = -torch.log(y_hat[range(len(y_hat)),y])
return loss
y_hat [ range ( len ( y_hat ) ) , y ]:二维索引检索真实标签的预测概率
7.批量梯度下降
#批量梯度下降
def bgd(W1,W2,b1,b2,lr,batch_size):
with torch.no_grad():
W1 -= lr * W1.grad/batch_size
W2 -= lr * W2.grad/batch_size
b1 -= lr * b1.grad/batch_size
b2 -= lr * b2.grad/batch_size
W1.grad.zero_()
W2.grad.zero_()
b1.grad.zero_()
b2.grad.zero_()
return W1,W2,b1,b2
8.正确率函数
#准确率评价accuracy
def accuracy(y_hat,y):
y_hat = y_hat.argmax(axis=1) #获取每行最大元素的索引
test = (y_hat == y)
return test.sum()/len(y)
9.训练
#训练
def train(train_pic,epoch,lr,batch_size,train_W1,train_W2,train_b1,train_b2):
for i in range(epoch):
for X,y in train_pic:
y_hat = net(X,train_W1,train_W2,train_b1,train_b2)
loss = cross(y_hat,y)
loss.sum().backward()
train_W1,train_W2,train_b1,train_b2 = bgd(train_W1,train_W2,train_b1,train_b2,lr,batch_size) #批量梯度下降
acc = accuracy(y_hat,y)
print('epoch '+str(i+1)+', accuracy is :',acc)
print('loss sum is :',loss.sum())
return train_W1,train_W2,train_b1,train_b2
10.预测
#预测
def predict(test_pic,final_W1,final_W2,final_b1,final_b2):
for X,y in test_pic:
y_hat = net(X,final_W1,final_W2,final_b1,final_b2)
pre = y_hat.argmax(axis=1) #确定每行最大元素的index
print('\n')
print('predict labels :',get_labels(pre))
print('true labels :',get_labels(y))
print('accuracy is :',accuracy(y_hat,y))
11.封装
#MLP
def MLP():
batch_size = 256
train_pic, test_pic = d2l.load_data_fashion_mnist(batch_size)
input_size = 784
output_size = 10 # 输出10个类别
hidden_size = 128
W1 = torch.normal(0,0.1,size=(input_size,hidden_size),requires_grad=True)
W2 = torch.normal(0,0.1,size=(hidden_size,output_size),requires_grad=True)
b1 = torch.normal(0,0.1,size=(1,hidden_size),requires_grad=True)
b2 = torch.normal(0,0.1,size=(1,output_size),requires_grad=True)
epoch = 50
lr = 0.1
final_W1,final_W2,final_b1,final_b2 = train(train_pic,epoch,lr,batch_size,W1,W2,b1,b2)
predict(test_pic,final_W1,final_W2,final_b1,final_b2)
return
12.拟合并预测
#拟合
MLP()
13.运行结果
经过10个epoch的训练,训练集上的正确率可以保持在0.9左右
在测试集上的表现也较为理想