import torch
import time
from torch.autograd import Variable
import torch.nn.functional as F
x = torch.unsqueeze(torch.linspace(-2, 2, 10), dim=1)
y = x.pow(2) + 0.2 * torch.rand(x.size())
#math.pow(100, 2) : 10000.0
#t.unsqueeze(di) //在di个维度处升维
#t=T.rand(t.size()) //均匀分布
#t=T.randn(t.size()) //标准正态分布
#torch.randn(*sizes, out=None)
#返回一个张量,包含了从标准正态分布(mean=0, std=1)中抽取一组随机数,形状 #由可变参数sizes定义。
#t=T.linspace(m,n,step_num) //[m,n]中以m为首项,n为末项,均分区间为step_num段
x, y = Variable(x), Variable(y)
#Variable就是 变量 的意思。实质上也就是可以变化的量,区别于int变量,它是一种可以变化的变量,这正好就符合了反向传播,参数更新的属性
#把鸡蛋放到篮子里, requires_grad是参不参与误差反向传播, 要不要计算梯度
#tensor不能反向传播,variable可以反向传播。
class Net(torch.nn.Module):
def __init__(self, n_features, n_hidden, n_output):
super(Net, self).__init__()
self.hidden = torch.nn.Linear(n_features, n_hidden)
self.predict = torch.nn.Linear(n_hidden, n_output)
def forward(self, x):
x = F.relu(self.hidden(x))
x = self.predict(x)
return x
model=Net(1,1,1)
optimizer = torch.optim.SGD(model.parameters(), lr=0.3)
loss_func = torch.nn.MSELoss()
for t in range(10):
prediction = model(x)
loss = loss_func(prediction,y)
print(loss)
optimizer.zero_grad()
loss.backward()
optimizer.step()
一般神经网络的类都继承自torch.nn.Module,init()和forward()两个函数是自定义类的主要函数。在__init__()中都要添加一句super(Net, self).init(),这是固定的标准写法,用于继承父类的初始化函数。init()中只是对神经网络的模块进行了声明,真正的搭建是在forwad()中实现。自定义类中的成员都通过self指针来进行访问,所以参数列表中都包含了self。
训练网络之前我们需要先定义优化器和损失函数。torch.optim包中包括了各种优化器,这里我们选用最常见的SGD作为优化器。因为我们要对网络的参数进行优化,所以我们要把网络的参数net.parameters()传入优化器中,并设置学习率(一般小于1)。
由于这里是回归任务,我们选择torch.nn.MSELoss()作为损失函数。
由于优化器是基于梯度来优化参数的,并且梯度会保存在其中。所以在每次优化前要通过optimizer.zero_grad()把梯度置零,然后再后向传播及更新。
torch.nn.module
定义自已的网络:
需要继承nn.Module类,并实现forward方法。
一般把网络中具有可学习参数的层放在构造函数__init__()中,
不具有可学习参数的层(如ReLU)可放在构造函数中,也可不放在构造函数中(而在forward中使用nn.functional来代替)
只要在nn.Module的子类中定义了forward函数,backward函数就会被自动实现(利用Autograd)。
在forward函数中可以使用任何Variable支持的函数,毕竟在整个pytorch构建的图中,是Variable在流动。还可以使用if,for,print,log等python语法.
pytorch中torch.view()的用法:
把原先tensor中的数据按照行优先的顺序排成一个一维的数据(这里应该是因为要求地址是连续存储的),然后按照参数组合成其他维度的tensor。比如说是不管你原先的数据是[[[1,2,3],[4,5,6]]]还是[1,2,3,4,5,6],因为它们排成一维向量都是6个元素,所以只要view后面的参数一致,得到的结果都是一样的。比如,
a=torch.Tensor([[[1,2,3],[4,5,6]]])
b=torch.Tensor([1,2,3,4,5,6])
print(a.view(1,6))
print(b.view(1,6))
得到的结果都是tensor([[1., 2., 3., 4., 5., 6.]])
torch.view(a,b)
将一个多维度的矩阵拼接成a×b
torch.squeeze()
用于将矩阵进行压缩,
有0和1两种参数分别表示第一维度和第二维度,torch.sequeeze(0)表示若第一维度的值为1,则去掉。第二维度同理。
若参数为矩阵,即torch.squeeze(a)则表示去掉a矩阵维数为1的维度。
torch.unsqueeze()
用于矩阵维度的扩充,
torch.unsqueeze(a, N)对矩阵a在指定维度N加上一维。