PyTorch 笔记 (二)

# 线性神经网络

# 小批量随机梯度下降:在每次需要计算更新的时候随机抽取一小批样本

import math
import time
import numpy as np
import torch
from d2l import torch as d2l
import matplotlib
import matplotlib.pyplot as plt
import random
from torch.utils import data
from torch import nn

# 正态分布于平方损失
def normal (x, mu, sigma) :
    p = 1 / math.sqrt(2 * math.pi * sigma ** 2)
    return p * np.exp(-0.5 / sigma ** 2 * (x - mu) ** 2)

x = np.arange(-7, 7, 0.01)
print(x)

# 均值和标准差对
params = [(0, 1), (0, 2), (3, 1)]
# plt.plot(x, [normal(x, mu, sigma) for mu, sigma in params], xlabel='x', ylabel='p(x)', figsize=(4.5, 2.5), legend=[f'mean {mu}, std {sigma}' for mu, sigma in params])
# d2l.plot(x, [normal(x, mu, sigma) for mu, sigma in params], xlabel = 'x',
#          ylabel = 'p(x)', figsize = (4.5, 2.5),
#          legend = [f'mean {mu}, std {sigma}' for mu, sigma in params])

plt.plot(x, normal(x, 0, 1), x, normal(x, 0, 2), x, normal(x, 3, 1))

# plt.show()

# 均方误差损失函数可以用于线性回归的一个原因是:我们假设了观测中包含噪声,
# 其中噪声服从正态分布。

# 线性回归从零开始实现
# 从零实现整个方法,包括流水线、模型、损失函数和小批量随机梯度下降优化器

# 生成数据集
def synthetic_data (w, b, num_examples) : #@save
    '''生成 y = Xw + b + 噪声'''
    '''torch.normal(means, std, out = None)
        返回一个张量,means 和 std 均为张量,包含从给定参数的离散正态分布中抽取随机数
        out 可选的输出张量
    '''
    X = torch.normal(0, 1, (num_examples, len(w)))
    '''torch.matmul 没有强制规定维度和大小,可以利用广播机制进行不同维度的相乘操作'''
    y = torch.matmul(X, w) + b
    y += torch.normal(0, 0.01, y.shape)
    return X, y.reshape((-1, 1))

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)
print('features : ', features[0], '\nlabel : ', labels[0])

# plt.set_figsize()
plt.scatter(features[:, (1)].detach().numpy(), labels.detach().numpy(), 1)
# plt.show()

# 读取数据集
def data_iter (batch_size, features, labels) :
    num_examples = len(features)
    indices = list(range(num_examples))
    # 这些样本是随机读取的,没有特定顺序
    random.shuffle(indices)
    for i in range(0, num_examples, batch_size) :
        batch_indices = torch.tensor(indices[i:min(i + batch_size, num_examples)])
        yield features[batch_indices], labels[batch_indices]

batch_size = 10
for X, y in data_iter(batch_size, features, labels) :
    print(X, '\n', y)

# 下面代码中通过从均值为 0,标准差为 0.01 的正态分布中采样随机数来初始化权重,并将偏置初始化为 0
w = torch.normal(0, 0.01, size = (2, 1), requires_grad = True)
b = torch.zeros(1, requires_grad = True)
print(w, '\n', b)

# 定义模型
def linreg (X, w, b) :
    '''线性回归模型'''
    return torch.matmul(X, w) + b

# 定义损失函数
def squared_loss (y_hat, y) :
    '''均方损失'''
    return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2

# 定义优化算法
def sgd(params, lr, batch_size) :
    '''小批量随机梯度下降'''
    with torch.no_grad() :
        for param in params :
            param -= lr * param.grad / batch_size
            param.grad.zero_()

# 训练
# 在每个迭代周期 epoch 中,我们使用 data_iter 函数便利整个数据集,并将训练数据集中所有样本
# 都使用一次
lr = 0.03
num_epochs = 3
net = linreg
loss = squared_loss

for epoch in range (num_epochs) :
    for X, y in data_iter(batch_size, features, labels) :
        l = loss(net(X, w, b), y)  # X 和 y 的小批量损失
        l.sum().backward()
        sgd([w, b], lr, batch_size)  # 使用参数的地图更新参数
    with torch.no_grad() :
        train_l = loss(net(features, w, b), labels)
        print(f'epoch {epoch + 1}, loss {float(train_l.mean()) : f}')

print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')
print(f'b的估计误差: {true_b - b}')

# 线性回归的简洁实现

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000)
print(features, '\n', labels)

# 读取数据
def load_array (data_arrays, batch_size, is_train = True) :
    '''构造一个 PyTorch 数据迭代器'''
    dataset = data.TensorDataset(*data_arrays)
    return data.DataLoader(dataset, batch_size, shuffle = is_train)

batch_szie = 0
data_iter = load_array((features, labels), batch_size)

print(next(iter(data_iter)))

# 定义模型
# 对于标准操作,我们使用框架的预定义好的层
net = nn.Sequential(nn.Linear(2, 1))

# 初始化模型参数
net[0].weight.data.normal_(0, 0.01)
net[0].bias.data.fill_(0)

# 定义损失函数
loss = nn.MSELoss()

# 定义优化算法
trainer = torch.optim.SGD(net.parameters(), lr = 0.03)

# 训练
num_epochs = 3
for epoch in range (num_epochs) :
    for X, y in data_iter :
        l = loss(net(X), y)
        trainer.zero_grad()
        l.backward()
        trainer.step()
    l = loss (net(features), labels)
    print(f'epoch {epoch + 1}, loss {l : f}')

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值