梯度下降
求导 W 梯度
找到误差最小的点,梯度躺平
但是不仅只有一个躺平的点,全局最优解。局部最优也可。
神经网络多个参数W
神经网络的黑盒不黑
- 输入
- 代表特征
- 中间层多次计算
- 输出层
迁移学习:保留代表特征转换能力。保留神经网络的理解能力。拆掉输出层,再套上另一个神经网络进行训练。
pyTorch学习
对比
tensorflow是先搭建一个静态的流程图,然后把数据放进去进行计算。
pytorch是动态的,边搭图边进行计算。
torchvision是库,预训练好的模块
numpy与torch
import torch
import numpy as np
#numpy 和 tensor数据转换
np_data = np.arange(6).reshape((2,3)) 创建两行三列的数据
torch_data = torch.from_numpy(np_data)
tensor2array = torch_data.numpy()
print(np_data,torch_data,tensor2array)
numpy: [ [0 1 2]
[3 4 5] ]
torch: 0 1 2
3 4 5
torch.LongTensor of size 2x3
tensor2array: [ [0 1 2] [3 4 5] ]
#abs sin mean
data = [-1,-2 1,2 ]
tensor = torch.FloatTensor(data) # 32bit 转成32位浮点数 tensor
print(np.abs(data),torch.abs(tensor))
numpy: [1 2 1 2]
torch: 1 2 1 2 size 4
#矩阵
data = [[1,2], [3,4]]
tensor = torch.FloatTensor(data) # 32bit 转成32位浮点数 tensor
print( np.matmul(data,data), torch.mm(tensor, tensor))
numpy: [ [7 10]
[15 22] ]
torch:
7 10
15 22 size 2x2
变量
import torch
from torch.autograd import Variable
#新版本variable 和 tensor合并了
tensor = torch.FloatTensor([1,2] , [3,4])
#查看初始 变量可以反向传播,更新参数
tensor.requires_grad
#要设置可以进行反向传播的话
tensor.requires_grad_(requires_grad=True)
#链式法则,反向传播计算梯度会顺着计算链计算到variable
v_out = torch.mean(variabler*variable) # x^2
v_out.backward()
print(variable.grad) #会影响到前面variable的值
print(variable.data)
print(variable.data.numpy) #转换成numpy的形式 [[],[]]
激励函数 Activation
线性 Linear
非线性 Nonlinear
激励函数套在线性的结果上,将线性变成非线性。
y=Wx
y=AF(Wx)
AF()就是激励函数,relu,sigmoid,tanh 掰弯利器
多层的神经网络要谨慎选择激励函数
import torch
import torch.nn.functional as F
#import torch.nn.Module (1.11 神经网络模块)
import matplotlib.pyplot as plt
from torch.autograd import Variable
#fake data
x= torch.linspace(-5,5,200) # -5到5 中间分为200个点
x=Variable(x)
x_np = x.data.numpy() #为了画图,转化数据的格式
y_relu = F.relu(x).data.numpy() #激励函数
y_sigmoid = F.sigmoid(x).data.numpy()
y_tanh = F.tanh(x).data.numpy()
y_softplus = F.softplus(x).data.numpy() #softmax做概率的图 分类 不能用来做线图
#y_softmax = F.softmax(x)
#画图
plt.figure(1,figsize=(8,6))
plt.subplot(221)
plt.plot(x_np,y_relu,c='red',label='relu')
plt.ylim((-1,5))
plt.legend(loc='best')
plt.show()
关系拟合(回归)regression
import torch
from torch.autograd import Variable
import torch.nn.functional as F
#import torch.nn.Module (1.11 神经网络模块)
import matplotlib.pyplot as plt
x = torch.unsqueeze(torch.linspace(-1,1,100), dim=1) # unsqueeze 将一维的数据变成二维的数据 [[1,2,3,4] ]
y = x.pow(2) + 0.2*torch.rand(x.size()) # y加一些噪点
#tensor和variable合并了
plt.scatter(x.data.numpy(), y.data.numpy()) #打印散点图
plt.show()
#搭建网络 继承module的功能
class Net(torch.nn.Module):
def __init__(self,n_features, n_hidden, n_output): #搭建层需要的信息 多少输入和输出 定义
super(Net, self).__init__() #继承Net的信息
self.hidden = torch.nn.Linear(n_features,n_hidden) #隐藏层 输入特征数,输出隐藏层神经元的个数
self.predict = torch.nn.Linear(n_hidden, n_output) #输入隐藏层n_hidden个神经元,预测结果输出一个值
def forward(self,x): #网络层的过程 搭建 输入X data
x = F.relu(self.hidden(x)) #激活 加工隐藏层的输出结果
x = self.predict(x) #output输出 预测不用激励函数,回归问题
return x
net = Net(1, 10 , 1)
输入一个值 隐藏层10个神经元 输出一个值
print(net)
net (
hidden : 1->10
predict: 10->1
)
plt.ion()
plt.show()
#优化神经网络
optimizer = torch.optim.SGD(net.parameters(), lr=0.5) #随机梯度下降 学习效率lr
loss_func = torch.nn.MSELoss() #均方差 回归问题
#开始进行训练
for t in range(100): #训练100步
prediction = net(x) #输出结果
loss = loss_func(prediction, y) #预测值和真实值的对比 计算误差
#优化步骤
optimizer.zero_grad() #所有参数梯度先降为零,每次更新完会保存在net
loss.backward() #开始这次的反向传播 计算梯度
optimizer.step() #以学习效率0.5优化这个梯度
if t%5 == 0:
#每学习5步打印一次
plt.cla() #动图
plt.scatter(x.data.numpy(), y.data.numpy()) #原始数据
plt.plot(...) #预测的结果 画线
plt.text(...) #打印误差多少
plt.pause(0.1)
plt.ioff()
plt.show()
分类问题 classification
import torch
from torch.autograd import Variable
import torch.nn.functional as F
#import torch.nn.Module (1.11 神经网络模块)
import matplotlib.pyplot as plt
#y是分类标签,横纵坐标都包含在二维张量x里
n_data = torch.ones(100,2) #一个100*2的全为1的张量 一列横坐标 一列竖坐标
x0 = torch.normal(2*n_data, 1) #class0 x data tensor shape=(100,2) #1是标准差,normal返回的是第一个参数附近的随机值
y0 = torch.zeros(100) #class0 y data tensor shape=(100,1) #标签是0
x1 = torch.normal(-2*n_data,1) #class1 x data tensor shape=(100,1)
y1 = torch.ones(100) #class1 y data tensor shape=(100,1) #标签是1
#以上是两类数据,需要机器学习哪个是0还是1
#合并在一起
x = torch.cat((x0,x1), 0).type(torch.FloatTensor) #数据 32位浮点数
y = torch.cat((y0,y1), ).type(torch.LongTensor) #标签 64位integer
#搭建网络 继承module的功能
class Net(torch.nn.Module):
def __init__(self,n_features, n_hidden, n_output): #搭建层需要的信息 多少输入和输出 定义
super(Net, self).__init__() #继承Net的信息
self.hidden = torch.nn.Linear(n_features,n_hidden) #隐藏层 输入特征数,输出隐藏层神经元的个数
self.predict = torch.nn.Linear(n_hidden, n_output) #输入隐藏层n_hidden个神经元,预测结果输出一个值
def forward(self,x): #网络层的过程 搭建 输入X data
x = F.relu(self.hidden(x)) #激活 加工隐藏层的输出结果
x = self.predict(x) #output输出 预测不用激励函数,回归问题
return x
#输入两个特征,输出标签也是两个[0,1] [1,0] (one-hot 编码)
net = Net(2,10,2)
#优化神经网络
optimizer = torch.optim.SGD(net.parameters(), lr=0.02) #随机梯度下降 学习效率lr
loss_func = torch.nn.CrossEntropyLoss() #交叉熵 预测值和真实值之间的差
[0.1 , 0.2 , 0.3 ] 分类问题 概率
#开始进行训练
for t in range(100): #训练100步
out = net(x) #输出结果 [-0.2, -1, 20] 数字不是概率
loss = loss_func(out, y) #预测值和真实值的对比 计算误差 交叉熵输入就是out 求损失值需要用到200*2的张量
#优化步骤
optimizer.zero_grad() #所有参数梯度先降为零,每次更新完会保存在net
loss.backward() #开始这次的反向传播 计算梯度
optimizer.step() #以学习效率0.5优化这个梯度
if t%5 == 0:
prediction = torch.max(F.softmax(out), 1 )[1] #将输出结果变为概率,max【最大值,最大值的索引】,这里取的是索引。 这里一个值就好了。
pred_y = prediction.data.numpy().squeeze()
target_y = y.data.numpy()
accuracy = sum(pred_y == target_y ) / 200
快速搭建网络的方法
#方法一
如上图定义的class类
hidden 类的属性 F.relu()相当于一个函数
net1 = (
hidden : 2->10
predict: 10->2 )
#方法二
net2 = torch.nn.Sequential(
torch.nn.Linear(2,10) #直接定义网络
torch.nn.ReLU(),
torch.nn.Linear(10,2), )
net2 = (
0: Linear 2->10
1: ReLU () 相当于一个类有名字
2: Linear 10->2
保存提取
def save():
# save net1
net1 = torch.nn.Sequential(
torch.nn.Linear(1,10)
torch.nn.ReLU(),
torch.nn.Linear(10,1),
)
optimizer = torch.optim.SGD(net1.parameters(), lr=0.5)
loss_func = torch.nn.MSELoss()
for t in range(100):
prediction = net1(x)
loss = loss_func(prediction,y) #这里是一维的可以
optimizer.zero_grad()
loss.backward()
optimizer.step()
torch.save(net1, 'net.pkl') #保存整个网络
torch.save(net1.state_dict(), 'net_params.pkl') #保存节点参数 parameters
def restore_net():
net2 = torch.load('net.pkl')
def restore_params():
#先建立一个一模一样的网络
net3 = torch.nn.Sequential(
torch.nn.Linear(1,10)
torch.nn.ReLU(),
torch.nn.Linear(10,1),
)
#传入参数
net3.load_state_dict(torch.load('net_params.pkl'))
save()
restore_net()
restore_params()
批训练 mini-batch training
import torch
import torch.utils.data as Data
BATCH_SIZE = 5 #每一小批是5条数据
x = torch.linspace(1, 10, 10)
y = torch.linsapce(10, 1, 10)
torch_dataset = Data.TensorDataset(data_tensor=x, target_tensor=y)
#torch_dataset = Data.TensorDataset(x,y) 新版本
loader = Data.DataLoader(
dataset = torch_dataset,
batch_size = BATCH_SIZE,
shuffle = True, #打乱顺序拆分 False是一模一样的顺序
num_workers=2, #两个进程和线程提取 多进程更有效率
)
for epoch in range(3): #整大批训练3次
for step, (batch_x, batch_y)in enumerate(loader): #10组数据,一小批是5组, 每epoch训练两次,更新梯度用的是拆分后的小批数据。step = 总数据 / Batch_size enumerate函数提取的时候有索引
#training
print('Epoch:' , epoch,
'| Step ' , step,
' | batch x : ', batch_x.numpy(),
' | batch y :', batch_y.numpy()
)
优化器加速神经网络训练
- SGD 每次只用一个小样本数据
- Momentum 在更新参数上做改动
W += - learning rate * dx
|
m=b1*m - learning rate * dx
W += m - AdaGrad 在学习率上做改动 调整步幅
v += dx^2
W += - learning rate * dx / 根号v - RMSProp
v=b1*v + (1-b1)*dx^2
w += -learning rate *dx / 根号v - Adam
m = b1*m + (1-b1)*dx
v = b2 *v + (1-b2) *dx^2
w += -learning rate *m/根号v
优化器
import torch
#hyper parameters 超参数
LR = 0.01 #学习率
BATCH_SIZE = 32 #每一小批32组数据
EPOCH = 12 #训练12轮次
x = torch.unsqueeze(torch.linspace(-1,1,1000), dim=1) # unsqueeze 将一维的数据变成二维的数据 [[1,2,3,4] ]
y = x.pow(2) + 0.1*torch.normal(torch.zeros(*x.size()))
#*x.size() 不带*得到的是列表,带上*相当于把列表解包,得到的是两个数
torch_dataset = Data.TensorDataset(x,y)
loader = Data.DataLoader(dataset=torch_dataset, batch_size=BATCH_SIZE, shuffle=True,num_workers=0)
#网络
class Net(torch.nn.Module):
def __init__(self,n_features, n_hidden, n_output): #搭建层需要的信息 多少输入和输出 定义
super(Net, self).__init__() #继承Net的信息
self.hidden = torch.nn.Linear(n_features,n_hidden) #隐藏层 输入特征数,输出隐藏层神经元的个数
self.predict = torch.nn.Linear(n_hidden, n_output) #输入隐藏层n_hidden个神经元,预测结果输出一个值
def forward(self,x): #网络层的过程 搭建 输入X data
x = F.relu(self.hidden(x)) #激活 加工隐藏层的输出结果
x = self.predict(x) #output输出 预测不用激励函数,回归问题
return x
#建立四个不同的神经网络
net_SGD = Net()
net_Momentum = Net()
net_RMSProp = Net()
net_Adam = Net()
nets = [net_SGD, net_Momentum, net_RMSProp, net_Adam]
#四个不同的优化器
opt_SGD = torch.optim.SGD(net_SGD.parameters(), lr=LR)
opt_Momentum = torch.optim.SGD(net_Momentum.parameters(), lr=LR, momentum=0.8)
opt_RMSProp = torch.optim.RMSProp(net_RMSProp.parameters(), lr=LR, alpha = 0.9)
opt_Adam = torch.optim.Adam(net_Adam.parameters(), lr=LR, betas=(0.9, 0.99))
optimizer = [opt_SGD, opt_Momentum, opt_RMSprop,opt_Adam]
loss_func = torch.nn.MSELoss()
losses_his = [[], [], [], [] ] #记录四个损失函数
for epoch in range(EPOCH):
print(epoch)
for step,(batch_x, batch_y) in enumerate(loader):
for net, opt, l_his in zip(nets, optimizers, losses_his):
output = net(b_x)
loss = loss_func(output, b_y)
opt.zero_grad() #clear
loss.backward() #compute
opt.step() #apply
l_his.append(loss.data[0]) #loss recoder loss.item()