PyTorch学习2

设立计算图并自动计算
1.numpy 和pytorch 实现梯度下降法
a.设定初始值
b.求取梯度
c.在梯度方向上进行参数的更新
numpy 和实现线性回归
2.实现一个简单的神经网络

1.numpy 和pytorch 实现梯度下降法

import torch
import numpy as np
from torch.autograd import Variable
torch.manual_seed(2019)
# 读入数据
x_train = np.array([[3.49], [4.48], [5.53], [6.81], [6.93], [4.168],
                    [9.779], [6.182], [7.59], [2.167], [7.042],
                    [10.791], [5.313], [7.997], [3.1]], dtype=np.float32)

y_train = np.array([[1.7], [2.76], [2.09], [3.19], [1.694], [1.573],
                    [3.366], [2.596], [2.53], [1.221], [2.827],
                    [3.465], [1.65], [2.904], [1.3]], dtype=np.float32)

# 画出图像
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(x_train, y_train, 'bo')

在这里插入图片描述

# 转换成Tensor
x_train = torch.from_numpy(x_train)
y_train = torch.from_numpy(y_train)

# 定义参数w和b
# 随机初始化
w = Variable(torch.randn(1), requires_grad=True) 
# 初始化0
b = Variable(torch.zeros(1), requires_grad=True)

# 构建线性回归模型
x_train = Variable(x_train)
y_train = Variable(y_train)

def linear_model(X):
    return X * w + b

y_ = linear_model(x_train)

经过上面的步骤我们就定义好了模型,在进行参数更新之前,我们可以先看看模型的输出结果.

plt.plot(x_train.data.numpy(), y_train.data.numpy(), 'bo', label='real')
plt.plot(x_train.data.numpy(), y_.data.numpy(), 'ro', label='estimated')
plt.legend()

在这里插入图片描述
思考:红色的点表示预测值,似乎排列成一条直线,请思考一下这些点是否在一条直线上
这个时候需要计算误差函数.

# 计算误差
def get_loss(y_, y):
    return torch.mean((y_ - y) ** 2)
loss = get_loss(y_, y_train)
print(loss)

tensor(0.6700, grad_fn=)
定义好了误差,接下来需要计算w和b的梯度了,这时得益于PyTorch的自动求导,不需要手动去算梯度

# 自动求导
loss.backward()
# 查看w, b梯度
print(w.grad)  # tensor([8.6568])
print(b.grad) # tensor([1.0541])
# 更新一次参数
w.data = w.data - 1e-2 * w.grad.data
b.data = b.data - 1e-2 * b.grad.data
# 更新完参数后,我们再一次看看模型输出的结果
y_ = linear_model(x_train)
plt.plot(x_train.data.numpy(),y_train.data.numpy(), 'bo', label='real')
plt.plot(x_train.data.numpy(),y_.data.numpy(), 'ro', label='estimated')
plt.legend()

在这里插入图片描述
从上面的例子可以看出,更新之后红色的线跑到了蓝色的线下面,没有特别好的拟合蓝色的真实值,所以我们需要进行几次更新

for epoch in range(10):
    y_ = linear_model(x_train)
    loss = get_loss(y_, y_train)
    # 归零梯度
    w.grad.zero_()
    b.grad.zero_()
    loss.backward()
    w.data = w.data - 1e-2*w.grad.data
    b.data = b.data - 1e-2*b.grad.data
    print('epoch: {}, loss: {}'.format(epoch, loss.data[0]))

经过10次更新,发现红色的预测结果已经比较好的拟合了蓝色的真实值
2.实现一个简单的神经网络
神经网络可以使用touch.nn来构建。nn依赖于autograd来定义模型,并且对其求导。一个nn.Module包含网络的层(layers),同时forward(input)可以返回output。

数字图像进行分类为例一个简单的前馈网络。它接受输入,然后一层一层向前传播,最后输出一个结果。

训练神经网络的典型步骤如下:

(1) 定义神经网络,该网络包含一些可以学习的参数(如权重)

(2) 在输入数据集上进行迭代

(3) 使用网络对输入数据进行处理

(4) 计算loss(输出值距离正确值有多远)

(5) 将梯度反向传播到网络参数中

(6) 更新网络的权重,使用简单的更新法则:weight = weight - learning_rate* gradient,即:新的权重=旧的权重-学习率*梯度值。
numpy 实现简单的神经网络
我们通常需要自己来实现前向计算和反向计算的逻辑, 下面我们来实现一个具有两层隐藏层的简单网络:

import numpy as np

# N 为batch size, D_in 为输入维度
# H 为隐藏层的维度, D_out 为输出的维度
N, D_in, H, D_out = 64, 1000, 100, 10

# 创建随机的输入和输出数据
x = np.random.randn(N, D_in) # N × D_in 的矩阵
y = np.random.randn(N, D_out) # N × D_out 的矩阵

# 对两个隐藏层w1,w2进行初始化
w1 = np.random.randn(D_in, H)
w2 = np.random.randn(H, D_out)

# 设置学习率
learning_rate = 1e-6
for t in range(500):
    # 前向传播: 计算预测结果 y_pred
    h = x.dot(w1) # x维度为64 × 1000, w1维度为 1000 × 100, 计算完以后, h维度为 64 × 100
    h_relu = np.maximum(h,0)
    y = h_relu.dot(w2) # h_relu维度为 64×100, w2维度为100×10, y的维度为64×10

    # 计算损失
    loss = np.square(y_pred - y).sum()
    print(t, loss)

    # 反向传播根据loss更新w1和w2的值
    grad_y_pred = 2.0*(y_pred - y) # 对y_pred求导
    grad_w2 = h_relu.T.dot(grad_y_pred) # 对w2求导, 微分矩阵应该与w2的size相同
    grad_h_relu = grad_y_pred.dot(w2.T) # 对h_relu求导
    grad_h = grad_h_relu.copy()
    grad_h[h < 0] = grad_h_relu # 经过relu, 将小于0的梯度归0
    grad_w1 = x.T.dot(grad_h)

    # Update weights
    w1 = w1 - learning_rate * grad_w1
    w2 = w2 - learning_rate * grad_w2

PyTorch实现数字分类

import torch
import numpy as np
import matplotlib.pyplot as plt
from torch.autograd import Variable


train_x_1=torch.linspace(0.1,0.5)  #数字归一化,非常重要

train_x_2=torch.linspace(0.5,1.0)  #数字归一化,非常重要

train_x=torch.cat((train_x_1,train_x_2))
print(train_x.size())
train_x=torch.unsqueeze(train_x,1)
print(train_x.size())




#print(train_x)

label_1=torch.zeros_like(train_x_1).type(torch.LongTensor)
label_2=torch.ones_like(train_x_2).type(torch.LongTensor)
label=torch.cat((label_1,label_2))
#label=torch.unsqueeze(label,1)


model=torch.nn.Sequential(
    torch.nn.Linear(1,5),
    torch.nn.Linear(5,2),

    torch.nn.Softmax()
)

criterion=torch.nn.CrossEntropyLoss()
optimizer=torch.optim.SGD(model.parameters(),lr=0.1)

train_x=Variable(train_x)
label=Variable(label)
for echo in range(10000):
    print(train_x.data.size())
    predict=model(train_x)
    loss=criterion(predict,label)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    print('Loss:',loss)

for echo in range(200):
    x=float(input('输入测试数据'))
    x=torch.FloatTensor([[x]])
    x=Variable(x)
   # x=torch.unsqueeze(x,0)
    print('预测结果:',model(x))

参考博客
https://blog.csdn.net/qjk19940101/article/details/79561471
https://blog.csdn.net/zzlyw/article/details/78769001

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值