前言:
既然前人已经开发了torch,那我们为什么要自己写反向传播算法等等?为什么不直接站在巨人的肩膀上呢?本文通过最基础的多层感知机搭建,介绍了反向传播算法,SGD等优化器方案,最后总结了一点自己的感悟(这沟槽的神经元数量究竟多少比较好!)。
这比亚迪神经元数量选择选了大半个小时。有的时候神经元不是越多越好,往往会聪明反被聪明误。
(正则化由于太过短小,所以想了想还是没发了。)
导入库:
import torch
import torch.nn as nn
from torch.nn.init import normal_
import matplotlib.pyplot as plt
import numpy as np
torch_activation_dict={
'identity':lambda x:x,
'sigmoid':torch.sigmoid,
'tanh':torch.tanh,
'relu':torch.relu
}
数据的输入与处理:
核心点已经在代码注释中写出,可以自行更改。
data=np.loadtxt('<文件名>',delimiter='<分隔符>')
ratio=0.8 #测试集与训练集的比值
np.random.seed(0)
data=np.random.permutation(data) #第一句表示设定一定的种子,确保多次重复实验划分的数据集相同。第二句表示将data数据集打乱
split=int(ratio*len(data)) #确定打乱后的训练集与测试集的划分线
x_train,y_train=data[:split,:2],data[:split,-1].reshape(-1,1)
#注意,文中本次训练有两个x_train参数,故为:2,有多个输入参数时要进行相应更改。
x_test,y_test=data[split:,:2],datap[split:,-1].reshape(-1,1)
对深度学习类的构建:
一般而言,通常会将一个深度学习网络构建为一个类,类中会含有对应的处理方法。本文也如此处理。然而一定要注意,这个类是nn.Module的派生类,如此才能调用torch里面的方法。而torch自带了backward反向传播,所以无需过多考虑。
class MLP_torch(nn.Module): #仅需实现forward,torch可实现反向传播与梯度计算
def __init__(
self,
layer_sizes, #神经元层数
use_bias=True, #是否含有偏置量
activation='relu', #激活函数选择,目前常用的有sigmoid,ReLu,Tanh
out_activation='identity'
):
super().__init__() #注意到,这里以torch.nn.Module为父类的类,所以需要调用父类的init进行处理。以下均是相同道理,需要将类调用torch.nn.Module
self. Activation=torch_activation_dict[activation]
self.out_activation=torch_activation_dict[out_activation]
self.layers=nn.ModuleList() #注意,神经元是父类,也就是torch自带的nn里面的。torch只能处理由他们派生的神经元
num_in=layer_sizes[0]
for num_out in layer_sizes[1:]:
self.layers.append(nn.Linear(num_in,num_out,bias=use_bias))
#对每一层神经元后append,即加入下一层的神经元
normal_(self.layers[-1].weight,std=1.0)
#本句对神经元的权重进行赋值。值得注意的是,由于在这个for中,每一层是衔接在上一层的,也就是说,在运行for时新加的一层永远是