Pytorch 入门

Posted wang豪

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pytorch 入门相关的知识,希望对你有一定的参考价值。

Pytorch 入门

文章目录


参考

一、常见的Tensor形式

  1. scaler
    通常为一个数值
x = tensor(42.)
  1. vector
    常见的向量
v = tensor([1,2,3])
  1. matrix
    一般是矩阵,通常是多维的
M = tensor([[1,2],[4,5]])
  1. n-dimensional tensor
    通常指更高纬度的表示

实现简单的线性回归Demo

主要通过该案例去理解Pytorch中的autograd机制

训练模型并保存模型

import torch
import torch.nn as nn
import numpy as np
# 数据准备
x_values = [i for i in range(11)]
x_train = np.array(x_values, dtype=np.float32)
x_train = x_train.reshape(-1, 1)

y_values = [i*2 + 2 for i in range(11)]
y_train = np.array(y_values, dtype=np.float32)
y_train = y_train.reshape(-1,1)

class LinearRegressionModel(nn.Module):
  def __init__(self, input_dim, output_dim):
    super(LinearRegressionModel, self).__init__()
    self.linear = nn.Linear(input_dim, output_dim)

  def forward(self, x):
    out = self.linear(x)
    return out

input_dim = 1
output_dim = 1

model = LinearRegressionModel(input_dim, output_dim)
epochs = 1000
learning_rate = 0.01
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
criterion = nn.MSELoss()

# 模型训练
for epoch in range(epochs):
    epoch += 1
    # 注意转行成tensor
    inputs = torch.from_numpy(x_train)
    labels = torch.from_numpy(y_train)

    # 梯度要清零每一次迭代
    optimizer.zero_grad() 

    # 前向传播
    outputs = model(inputs)

    # 计算损失
    loss = criterion(outputs, labels)

    # 返向传播
    loss.backward()

    # 更新权重参数
    optimizer.step()
    if epoch % 50 == 0:
        print('epoch , loss '.format(epoch, loss.item()))
torch.save(model.state_dict(), 'model.pkl')

加载模型并预测

input_dim = 1
output_dim = 1

model = LinearRegressionModel(input_dim, output_dim)
model.load_state_dict(torch.load('model.pkl'))

import matplotlib.pyplot as plt

pred = model(torch.from_numpy(x_train).requires_grad_()).data.numpy()
plt.plot(x_values, pred, 'ro')

预测结果

用神经网络进行气温预测

数据处理

导入数据

import numpy as np
import torch
import pandas as pd
import torch.optim as optim
import matplotlib.pyplot as plt
import warnings

warnings.filterwarnings('ignore')

features = pd.read_csv("./temps.csv")
print(features.head())


对时间数据进行转化并可视化

import datetime

years = features["year"]
months = features["month"]
days = features["day"]

# datetime格式
dates = [str(int(year)) + '-' + str(int(month)) + '-' + str(int(day)) for year, month, day in zip(years, months, days)]
dates = [datetime.datetime.strptime(date, '%Y-%m-%d') for date in dates]

plt.style.use('fivethirtyeight')

# 设置布局
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2, figsize = (10,10))
fig.autofmt_xdate(rotation = 45)

# 标签值
ax1.plot(dates, features['actual'])
ax1.set_xlabel(''); ax1.set_ylabel('Temperature'); ax1.set_title('Max Temp')

# 昨天
ax2.plot(dates, features['temp_1'])
ax2.set_xlabel(''); ax2.set_ylabel('Temperature'); ax2.set_title('Previous Max Temp')

# 前天
ax3.plot(dates, features['temp_2'])
ax3.set_xlabel('Date'); ax3.set_ylabel('Temperature'); ax3.set_title('Two Days Prior Max Temp')


ax4.plot(dates, features['friend'])
ax4.set_xlabel('Date'); ax4.set_ylabel('Temperature'); ax4.set_title('Friend Estimate')

plt.tight_layout(pad=2)


获得训练集

# 对部分数据进行独热编码
features = pd.get_dummies(features)

#标签
labels = np.array(features['actual'])
# 在特征中去掉标签
features = features.drop('actual', axis = 1)
# 名字单独保存
features_list = list(features.columns)

# 转换成合适的格式
features = np.array(features)

# 标准化处理
from sklearn.preprocessing import StandardScaler
input_features = StandardScaler().fit_transform(features)

# 获得训练集和测试集
x = torch.tensor(input_features, dtype = float)
y = torch.tensor(labels, dtype = float)

在处理好数据后我们可以通过下面两种方式搭建模型

1. 较为复杂的构建形式(有助于理解)

下面我们手动去进行梯度下降,而不是使用torch 中内置的方法。

## 权重参数初始化
weights = torch.randn((14, 128), dtype = float, requires_grad = True)
biases = torch.randn(128, dtype = float, requires_grad = True)
weights2 = torch.randn((128, 1), dtype = float, requires_grad = True)
biases2 = torch.randn(1, dtype = float, requires_grad = True)

learning_rate = 0.001
losses = []

for i in range(10000):
  # 计算隐层
  hidden = x.mm(weights) + biases
  # 加入激活函数
  hidden = torch.relu(hidden)
  # 计算输出层
  output = hidden.mm(weights2) + biases2
  # 计算损失
  loss = torch.mean((output - y) ** 2)
  losses.append(loss.data.numpy())
  # 计算梯度
  loss.backward()

  #更新参数
  weights.data.add_(- learning_rate * weights.grad.data)  
  biases.data.add_(- learning_rate * biases.grad.data)
  weights2.data.add_(- learning_rate * weights2.grad.data)
  biases2.data.add_(- learning_rate * biases2.grad.data)

  # 清空梯度
  weights.grad.zero_()
  biases.grad.zero_()
  weights2.grad.zero_()
  biases2.grad.zero_()
  # 打印损失值
  if i % 100 == 0:
      print('loss:', loss)

2.较为简单的构建方式

可以将这种写法跟上面的方法一进行对比

input_size = input_features.shape[1]
hidden_size = 128
output_size = 1
batch_size = 16
my_nn = torch.nn.Sequential(
  torch.nn.Linear(input_size, hidden_size),
  torch.nn.Sigmoid(),
  torch.nn.Linear(hidden_size, output_size)
)
# 定义损失函数
cost = torch.nn.MSELoss(reduction = 'mean')
# 可以通过这个进行链式的梯度下降
optimizer = torch.optim.Adam(my_nn.parameters(), lr = 0.001)

# 训练网络
losses = []

for i in range(1000):
  batch_loss = []
  # MINI-BATCH 方法来进行训练
  # 每次仅用一部分数据投入训练
  for start in range(0, len(input_features), batch_size):
    end = start + batch_size if start + batch_size < len(input_features) else len(input_features)
    x_batch = torch.tensor(input_features[start:end], dtype = torch.float, requires_grad = True)
    y_batch = torch.tensor(labels[start:end], dtype = torch.float, requires_grad = True)
    # 前向传播
    y_pred = my_nn(x_batch)
    # 计算损失
    loss = cost(y_pred, y_batch)
    batch_loss.append(loss.item())
    # 反向传播
    loss.backward()
    # 更新参数
    optimizer.step()
    # 清空梯度
    optimizer.zero_grad()
    batch_loss.append(loss.data.numpy())
  
  # 打印损失
  if i % 100 == 0:
    losses.append(np.mean(batch_loss))
    print('loss:', np.mean(batch_loss))

使用模型预测

x = torch.tensor(input_features, dtype = torch.float)
predict = my_nn(x).data.numpy()

# 转换日期格式
dates = [str(int(year)) + '-' + str(int(month)) + '-' + str(int(day)) for year, month, day in zip(years, months, days)]
dates = [datetime.datetime.strptime(date, '%Y-%m-%d') for date in dates]

# 创建一个表格来存日期和其对应的标签数值
true_data = pd.DataFrame(data = 'date': dates, 'actual': labels)
pre_data = pd.DataFrame(data = 'date': dates, 'actual': predict.reshape(-1))

# 真实值
plt.plot(true_data['date'], true_data['actual'], 'b-', label = 'True')

# 预测值
plt.plot(pre_data['date'], pre_data['actual'], 'r-', label = 'Prediction')
plt.xticks(rotation = "60") 

plt.legend()
plt.xlabel('Date') 
plt.ylabel('Maximum Temperature (F)') 
plt.title('Actual and Predicted Values')

手写体识别(线性模型)

加载数据并查看

from pathlib import Path
import requests
import matplotlib.pyplot as plt

DATA_PATH = Path("data")
PATH = DATA_PATH / "mnist"

PATH.mkdir(parents=True, exist_ok=True)

URL = "http://deeplearning.net/data/mnist/"
FILENAME = "mnist.pkl.gz"

if not (PATH / FILENAME).exists():
        content = requests.get(URL + FILENAME).content
        (PATH / FILENAME).open("wb").write(content)


import pickle
import gzip

with gzip.open((PATH / FILENAME).as_posix(), "rb") as f:
        ((x_train, y_train), (x_valid, y_valid), _) = pickle.load(f, encoding="latin-1")
       
plt.imshow(x_train[1].reshape(28, 28), cmap="gray")

数据格式化处理

# 将数据格式进行转化
x_train, y_train, x_valid, y_valid = map(
    torch.tensor, (x_train, y_train, x_valid, y_valid)
)
n,c = x_train.shape
x_train, x_train.shape, y_train.min(), y_train.max()

bs = 64
xb = x_train[0:bs]
yb = y_train[0:bs]
weights = torch.randn([784, 10], dtype=torch.float ,requires_grad=True)
bs = 64
bias = torch.zeros(10, requires_grad=True)

from torch.utils.data import DataLoader, TensorDataset


train_ds = TensorDataset(x_train, y_train)
train_dl = DataLoader(train_ds, batch_size=bs, shuffle=True)

valid_ds = TensorDataset(x_valid, y_valid)
valid_dl = DataLoader(valid_ds, batch_size=bs *2)

网络构建

创建一个model 来简化代码

  • 必须继承nn.Module 且在其构造函数中需调用nn.Module 中的构造函数
  • 无需写反向传播函数, nn.Module 能够利用autograd自动实现反向传播
  • Module 中可学习参数可以通过named_parameters()或者parameters()返回迭代器
from torch import nn
import torch.nn.functional as F

class Mnist_NN(nn.Module):
  """
  	## 网络结构搭建
  	
  """
  def __init__(self):
    super().__init__()
    self.hidden1 = nn.Linear(784, 128)
    self.hidden2 = nn.Linear(128, 256)
    self.out = nn.Linear(256, 10)

  def forward(self, xb):
    """
      ## 尽心前向传播
    """
    xb = F.relu(self.hidden1(xb))
    xb = F.relu(self.hidden2(xb))
    xb = self.out(xb)
    return xb
    
def loss_batch(mode, loss_func, xb, yb, opt = None):
  """
    ## 计算损失值的时候,同时进行反向传播
  """
  loss = loss_func(mode(xb), yb)
  if opt is not None:
    loss.backward()
    opt.step()
    opt.zero_grad()
  return loss.item(), len(xb)

def getModel():
  """
    ## 获取模, 并获得优化函数
  """
  model = Mnist_NN()
  return model<

以上是关于Pytorch 入门的主要内容,如果未能解决你的问题,请参考以下文章

PyTorch自定义损失函数实现

[PyTorch] 笔记03:神经网络

识别手写数字增强版 - pytorch从入门到入道

pytorch入门Pytorch神经网络工具

【Pytorch+torchvision】MNIST手写数字识别(代码附最详细注释)

pytorch lightning 手写数字分类实例