1.numpy和pytorch实现梯度下降法
我这里实现的是 y=x**2 的梯度下降,步骤如下:
- 设定初始值,我这里将初始值设置为了1
- 求取梯度
- 在梯度方向进行参数的更新
代码如下:
x_tensor=torch.FloatTensor([1]) #设置初始值为1
x=Variable(x_tensor,requires_grad=True)
for i in range(5):
y=x**2
y.backward() #反向传播
grad1=x.grad #求取梯度
x=x-0.4*grad1 #更新参数
x=Variable(x,requires_grad=True)
print(x)
代码结果如下:
可以看到迭代了5次后基本到达了最低点(最低点为0)。
2.numpy和pytorch实现线性回归
2.1 x和y都是一维的情况
代码如下,其中x有两个特征,所以对应的是w有两个,
def linear_model(x,w,b):
return x.mm(w)+b
def get_loss(y_,y):
return torch.mean((y_-y)**2)
x=torch.Tensor([[1,1],[2,2],[3,3]])
y=torch.Tensor([[2],[4],[6]])
w=Variable(torch.Tensor([[1],[1]]),requires_grad=True)
b=Variable(torch.Tensor([[1]]),requires_grad=True)
y_=linear_model(x,w,b)
loss=get_loss(y_,y)
for i in range(100000):
loss=get_loss(y_,y)
loss.backward()
w.data=w.data-0.001*w.grad.data #参数更新
b.data=b.data-0.001*b.grad.data
y_=linear_model(x,w,b)
w.grad.zero_() #梯度归零
b.grad.zero_()
print("loss:",loss.data[0])
print("w:",w.data)
print("b:",b.data)
结果如下:
3.实现简单神经网络
3.1生成数据
生成数据代码如下:
import torch
import numpy as np
from torch import nn
from torch.autograd import Variable
import torch.nn.functional as F
import matplotlib.pyplot as plt
np.random.seed(1)
np.random.seed(1)
m = 400 # 样本数量
N = int(m/2) # 每一类的点的个数
D = 2 # 维度
x = np.zeros((m, D))
y = np.zeros((m, 1), dtype='uint8') # label 向量,0 表示红色,1 表示蓝色
a = 4
for j in range(2):
ix=range(N*j,N*(j+1))
t=np.linspace(j*3.12,(j+1)*3.12,N)+np.random.randn(N)*0.2 #np.linspace 间隔采样(开始,结束,步伐)
r=a*np.sin(4*t)+np.random.randn(N)*0.2
x[ix]=np.c_[r*np.sin(t),r*np.cos(t)] #按行连接两个矩阵
y[ix]=j
plt.scatter(x[:,0],x[:,1],c=y.reshape(-1),s=40,cmap=plt.cm.Spectral)
x = torch.from_numpy(x).float()
y = torch.from_numpy(y).float()
结果如下:
3.2 Sequential 方法
这种方法建立网络和运算的代码如下:
criterion=nn.BCEWithLogitsLoss()
seq_net = nn.Sequential(
nn.Linear(2, 4), # PyTorch 中的线性层,wx + b
nn.Tanh(),
nn.Linear(4, 1)
)
#通过 parameters 可以取得模型的参数
param = seq_net.parameters()
#定义优化器
optim = torch.optim.SGD(param, 1.)
for e in range(10000):
out = seq_net(Variable(x))
loss = criterion(out, Variable(y))
optim.zero_grad()
loss.backward()
optim.step()
if (e + 1) % 1000 == 0:
print('epoch: {}, loss: {}'.format(e+1, loss.data[0]))
结果如下:
3.3 Module方法
Module方法模板如下:
class 网络名字(nn.Module):
def __init__(self, 一些定义的参数):
super(网络名字, self).__init__()
self.layer1 = nn.Linear(num_input, num_hidden)
self.layer2 = nn.Sequential(...)
...
定义需要用的网络层
def forward(self, x): # 定义前向传播
x1 = self.layer1(x)
x2 = self.layer2(x)
x = x1 + x2
...
return x
注意,Module 里面也可以使用 Sequential,同时 Module 非常灵活,具体体现在 forward 中,如何复杂的操作都能直观的在 forward 里面执行。这种方法计算本数据代码如下:
class module_net(nn.Module):
def __init__(self, num_input, num_hidden, num_output):
super(module_net, self).__init__()
self.layer1 = nn.Linear(num_input, num_hidden)
self.layer2 = nn.Tanh()
self.layer3 = nn.Linear(num_hidden, num_output)
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
return x
criterion=nn.BCEWithLogitsLoss()
mo_net = module_net(2, 4, 1)
optim = torch.optim.SGD(mo_net.parameters(), 1.)
for e in range(10000):
out = mo_net(Variable(x)) #这里省略了 mo_net.forward()
loss = criterion(out, Variable(y))
optim.zero_grad()
loss.backward()
optim.step()
if (e + 1) % 1000 == 0:
print('epoch: {}, loss: {}'.format(e+1, loss.data[0]))
结果如下: