PyTorch技术和深度学习——三、深度学习快速入门

文章目录

      • 1.线性回归
        • 1)介绍
        • 2)加载自由泳冠军数据集
        • 3)从0开始实现线性回归模型
        • 4)使用自动求导训练线性回归模型
        • 5)使用优化器训练线性回归模型
      • 2.使用torch.nn模块构建线性回归模型
        • 1)使用torch.nn.Linear训练线性回归模型
        • 2)使用torch.nn.Sequential类训练线性回归模型
        • 3)使用torch.nn.Module训练线性回归模型
      • 3.逻辑回归
        • 1)介绍
        • 2)从0开始实现逻辑回归模型
        • 3)使用Pytorch实现逻辑回归模型
      • 4.softmax回归
        • 1)介绍
        • 2)从头开始实现softmax回归
        • 3)使用Pytorch实现softmax回归
      • 5.神经网络
        • 1)神经元
        • 2)激活函数
          • 1.绘制Sigmoid激活函数
          • 2.绘制双曲正切Tanh激活函数
          • 3.绘制ReLU激活函数
          • 4.绘制LeakyReLU激活函数
          • 5.softmax函数
          • 6.选择正确的激活函数
        • 3)神经网络原理
        • 4)Pytorch实现神经网络
        • 5)神经网络应用示例一
        • 6)神经网络应用示例二
        • 7)两层神经网络解决异或问题
        • 8)Fizz Buzz神经网络实现

1.线性回归

1)介绍

模型构建步骤:

1.定义:找到目标函数,将输入属性映射为输出属性。

2.模型假设:用一条直线拟合数据

3.模型评估:采用损失函数来评价预测值和真实值的接近程度。argmin是机器学习常用的函数,用来寻找使损失函数最小时的参数取值。

4.梯度下降算法:也叫最速下降法。用来求代价函数(损失函数或者叫目标函数)的最小值。基本思想:随机选择一组参数初始值,计算损失或者代价,然后寻找能让代价下降最多的另一组参数,反复迭代直至达到一个局部最优。

2)加载自由泳冠军数据集

数据集为奥运会自由泳冠军数据,

创建文件display_olympics_freestyle100m.py
添加代码如下:

import torch
from matplotlib import pyplot as plt
import pandas as pd
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falsedef main():# 加载奥运会数据file_path = "../datasets/Freestyle100m.csv"dataset = pd.read_csv(file_path)dataset_tensor = torch.tensor(dataset.values)  # 转换为tensorx = dataset_tensor[:, :-1]y = dataset_tensor[:, -1]# 绘图plt.plot(x.numpy(), y.numpy(), 'o')plt.xlabel(u'奥运会年')plt.ylabel(u'取胜时间(秒)')plt.show()if __name__ == "__main__":main()

运行结果:
在这里插入图片描述

横坐标为奥运举办年份,纵坐标为取胜时间

3)从0开始实现线性回归模型

思路:

1.建立线性回归模型;

2.损失函数及损失函数求导

3.利用损失函数求导,实现梯度函数

梯度下降的收敛可以通过设置最大迭代次数或者判断参数不再改变来确定已经收敛。更新参数使用全部样本成为批量梯度下降法(BGD);使用一个样本成为随机梯度下降法(SGD);使用部分样本叫小批量梯度下降法,兼顾前两种优缺点。

4.重复:计算预测值(前向传播),然后计算损失和梯度;更新参数;

创建文件linear_regression_from_scratch.py
实现代码如下:

# -*- coding: utf-8 -*-
"""
从头开始实现线性回归模型
"""
import torch
from matplotlib import pyplot as plt
import pandas as pd
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falsedef model(x, w, b):""" 回归模型 """return w * x + bdef loss_fn(y_pred, y):""" 损失函数 """loss = (y_pred - y) ** 2return loss.mean()def grad_loss_fn(y_pred, y):""" 损失函数求导 """return 2 * (y_pred - y)def grad_fn(x, y, y_pred):""" 梯度函数 """grad_w = grad_loss_fn(y_pred, y) * xgrad_b = grad_loss_fn(y_pred, y)return torch.stack([grad_w.mean(), grad_b.mean()])def model_training(x, y, n_epochs, learning_rate, params, print_params=True):""" 训练 """for epoch in range(1, n_epochs + 1):w, b = params# 前向传播y_pred = model(x, w, b)# 计算损失loss = loss_fn(y_pred, y)# 梯度grad = grad_fn(x, y, y_pred)# 更新参数params = params - learning_rate * gradif epoch == 1 or epoch % 500 == 1:print('轮次:%d,\t损失:%f' % (epoch, float(loss)))if print_params:print(f'参数:{params.detach().numpy()}')print(f'梯度:{grad.detach().numpy()}')return paramsdef main():# 加载奥运会数据file_path = "../datasets/Freestyle100m.csv"dataset = pd.read_csv(file_path)dataset_tensor = torch.tensor(dataset.values)  # 转换为tensorxx = dataset_tensor[:, 0]y = dataset_tensor[:, -1]# 为方便数值运算,将原来的举办年减去第一届奥运会年x = xx - xx[0]# 模型参数初始化w = torch.zeros(1)b = torch.zeros(1)# 直接用未优化的模型来预测y_pred = model(x, w, b)print('未优化的模型的预测结果:', y_pred.detach().numpy())loss = loss_fn(y_pred, y)print('未优化的模型的损失:', loss.detach().numpy())params = model_training(x=x,y=y,n_epochs=50000,learning_rate=0.00017,params=torch.tensor([0.0, 0.0]))print('梯度下降找到的w和b:%f %f \n' % (params[0], params[1]))y_pred = model(x, *params)print(f'优化后的模型的预测结果:{y_pred.detach().numpy()}\n')# 绘图plt.plot(xx.numpy(), y_pred.detach().numpy(), label=u'模型')plt.plot(xx.numpy(), y.numpy(), 'o', label=u'数据')plt.xlabel(u'奥运会年')plt.ylabel(u'取胜时间(秒)')plt.legend()plt.show()if __name__ == "__main__":main()

运行结果:

在这里插入图片描述

4)使用自动求导训练线性回归模型

pytorch提供自动求导功能,计算梯度。只要提供前向表达式,就可以计算任意节点梯度。

只需要在张量的构造中添加requires_grad=True参数即可。

detach().requires_grad_()表示将张量分离同时设置requires_grad=True。

创建文件linear_regression_autograd.py
完整实现代码如下:

# -*- coding: utf-8 -*-
"""
使用自动求导训练线性回归模型
"""import torch
from matplotlib import pyplot as plt
import pandas as pd
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falsedef model(x, w, b):""" 回归模型 """return w * x + bdef loss_fn(y_pred, y):""" 损失函数 """loss = (y_pred - y) ** 2return loss.mean()def model_training(x, y, params, n_epochs, learning_rate):""" 训练 """for epoch in range(1, n_epochs + 1):# 梯度清零if params.grad is not None:params.grad.zero_()# 前向传播y_pred = model(x, *params)# 计算损失loss = loss_fn(y_pred, y)# 反向传播loss.backward()# 更新参数params = (params - learning_rate * params.grad).detach().requires_grad_()if epoch == 1 or epoch % 500 == 0:print('轮次:%d,\t损失:%f' % (epoch, float(loss)))return paramsdef main():# 加载奥运会数据file_path = "../datasets/Freestyle100m.csv"dataset = pd.read_csv(file_path)dataset_tensor = torch.tensor(dataset.values)  # 转换为tensorxx = dataset_tensor[:, 0]y = dataset_tensor[:, -1]# 为方便数值运算,将原来的举办年减去第一届奥运会年x = xx - xx[0]# 初始化模型参数params = torch.tensor([0.0, 0.0], requires_grad=True)print('params.grad is None: ', params.grad is None)loss = loss_fn(model(x, *params), y)loss.backward()print(params.grad)if params.grad is not None:params.grad.zero_()params = model_training(x=x,y=y,params=torch.tensor([0.0, 0.0], requires_grad=True),n_epochs=50000,learning_rate=0.00017)print('梯度下降找到的w和b:%f %f \n' % (params[0], params[1]))y_pred = model(x, *params)print(f'优化后的模型的预测结果:{y_pred.detach().numpy()}\n')# 绘图plt.plot(xx.numpy(), y_pred.detach().numpy(), label=u'模型')plt.plot(xx.numpy(), y.numpy(), 'o', label=u'数据')plt.xlabel(u'奥运会年')plt.ylabel(u'取胜时间(秒)')plt.legend()plt.show()if __name__ == "__main__":main()
5)使用优化器训练线性回归模型

优化器(optimizer)用来优化梯度计算。包括SGD 优化,Adam。

创建文件linear_regression_optimizers.py
完整实现代码如下:

# -*- coding: utf-8 -*-
"""
使用优化器训练线性回归模型 
"""import torch
import torch.optim as optim
import pandas as pd
from matplotlib import pyplot as plt
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falsedef model(x, w, b):""" 回归模型 """return w * x + bdef loss_fn(y_pred, y):""" 损失函数 """loss = (y_pred - y) ** 2return loss.mean()def model_training(x, y, params, n_epochs, optimizer):""" 训练 """for epoch in range(1, n_epochs + 1):# 前向传播p_pred = model(x, *params)# 计算损失loss = loss_fn(p_pred, y)# 梯度清零optimizer.zero_grad()# 反向传播loss.backward()# 更新参数optimizer.step()if epoch == 1 or epoch % 500 == 0:print('轮次:%d,\t损失:%f' % (epoch, float(loss)))return paramsdef main():# 加载奥运会数据file_path = "../datasets/Freestyle100m.csv"dataset = pd.read_csv(file_path)dataset_tensor = torch.tensor(dataset.values)  # 转换为tensorxx = dataset_tensor[:, 0]y = dataset_tensor[:, -1]# 为方便数值运算,将原来的举办年减去第一届奥运会年x = xx - xx[0]# 参数params = torch.tensor([0.0, 0.0], requires_grad=True)learning_rate = 0.00017# 使用optim模块中的现成优化器optimizer = optim.SGD([params], lr=learning_rate)# 手工做一次优化y_pred = model(x, *params)loss = loss_fn(y_pred, y)# 梯度清零optimizer.zero_grad()# 优化loss.backward()optimizer.step()# 打印一次优化后的参数print('一次优化后的参数:', params)# 手工再做一次优化params = torch.tensor([0.0, 0.0], requires_grad=True)optimizer = optim.SGD([params], lr=learning_rate)y_pred = model(x, *params)loss = loss_fn(y_pred, y)# 梯度清零optimizer.zero_grad()# 优化loss.backward()optimizer.step()# 打印再一次优化后的参数print('再一次优化后的参数:', params)print('\n使用SGD训练模型')params = torch.tensor([0.0, 0.0], requires_grad=True)optimizer = optim.SGD([params], lr=learning_rate)params = model_training(x=x,y=y,params=params,n_epochs=50000,optimizer=optimizer)print('SGD优化器找到的w和b:%f %f \n' % (params[0], params[1]))print('\n使用Adam再训练一次模型')# 注意学习率和训练轮次都不同于SGD,说明Adam是高级优化函数params = torch.tensor([0.0, 0.0], requires_grad=True)learning_rate = 1e-1optimizer = optim.Adam([params], lr=learning_rate)params = model_training(x=x,y=y,params=params,n_epochs=2000,optimizer=optimizer)print('Adam优化器找到的w和b:%f %f \n' % (params[0], params[1]))# 再做一次预测y_pred = model(x, *params)# 绘图plt.plot(xx.numpy(), y_pred.detach().numpy(), label=u'模型')plt.plot(xx.numpy(), y.numpy(), 'o', label=u'数据')plt.xlabel(u'奥运会年')plt.ylabel(u'取胜时间(秒)')plt.legend()plt.show()if __name__ == "__main__":main()

2.使用torch.nn模块构建线性回归模型

pytorch提供nn模块,包含有Lineaar、Sequential、Model和各种损失函数。

1)使用torch.nn.Linear训练线性回归模型

步骤:

1.加载数据集,划分划分训练集验证集

2.定义线性模型

3.设置优化器

4.分别使用自定义的损失函数和nn模块使用开箱即用的损失函数

# -*- coding: utf-8 -*-
"""
使用torch.nn.Linear训练线性回归模型
"""import torch
import torch.optim as optim
import torch.nn as nn
from matplotlib import pyplot as plt
import pandas as pd
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falsedef loss_fn(y_pred, y):""" 损失函数 """loss = (y_pred - y) ** 2return loss.mean()def model_training(x_train, y_train, x_val, y_val, n_epochs, optimizer, model, loss_fn):""" 训练 """for epoch in range(1, n_epochs + 1):# 前向传播y_pred_train = model(x_train)loss_train = loss_fn(y_pred_train, y_train)with torch.no_grad():y_pred_val = model(x_val)loss_val = loss_fn(y_pred_val, y_val)# 梯度清零optimizer.zero_grad()# 反向传播loss_train.backward()# 更新参数optimizer.step()if epoch == 1 or epoch % 100 == 0:print(f'轮次:{epoch},\t训练损失:{float(loss_train)},\t验证损失:{float(loss_val)}')def main():# 加载奥运会数据file_path = "../datasets/Freestyle100m.csv"dataset = pd.read_csv(file_path)dataset_tensor = torch.tensor(dataset.values)  # 转换为tensorxx = dataset_tensor[:, 0]y = dataset_tensor[:, -1]# 为方便数值运算,将原来的举办年减去第一届奥运会年x = xx - xx[0]# 扩充一维,变为nn可以接受的shape和数据类型x = x.unsqueeze(1).float()y = y.unsqueeze(1).float()# 划分训练集验证集n_samples = x.shape[0]n_train = int(0.7 * n_samples)# 随机置乱shuffled_idx = torch.randperm(n_samples)train_idx = shuffled_idx[:n_train]val_idx = shuffled_idx[n_train:]x_train = x[train_idx]y_train = y[train_idx]x_val = x[val_idx]y_val = y[val_idx]# 定义模型linear_model = nn.Linear(1, 1)# 使用optim模块中的现成优化器learning_rate = 1e-1epochs = 3000optimizer = optim.Adam(linear_model.parameters(), lr=learning_rate)# 使用自定义的损失函数model_training(x_train=x_train,y_train=y_train,x_val=x_val,y_val=y_val,n_epochs=epochs,optimizer=optimizer,model=linear_model,loss_fn=loss_fn)print()print(linear_model.weight)print(linear_model.bias)linear_model = nn.Linear(1, 1)optimizer = optim.Adam(linear_model.parameters(), lr=learning_rate)# 使用开箱即用的损失函数model_training(x_train=x_train,y_train=y_train,x_val=x_val,y_val=y_val,n_epochs=epochs,optimizer=optimizer,model=linear_model,loss_fn=nn.MSELoss())print('优化后的模型参数')print(linear_model.weight)print(linear_model.bias)# 绘图plt.plot(xx.numpy(), y.numpy(), 'go', label=u'数据')x_range = torch.arange(min(xx), max(xx)).unsqueeze(1)plt.plot(x_range.numpy(), linear_model(x_range - xx[0]).detach().numpy(), 'r-', label=u'模型')plt.plot(xx.numpy(), linear_model(x).detach().numpy(), 'bx', label=u'预测')plt.xlabel(u'奥运会年')plt.ylabel(u'取胜时间(秒)')plt.legend()plt.show()if __name__ == "__main__":main()
2)使用torch.nn.Sequential类训练线性回归模型

Sequential是一种容器,添加并连接模块,最终形成一个网络模型。

创建文件linear_regression_nn_sequential.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
使用torch.nn.Sequential类训练线性回归模型"""import torch
import torch.optim as optim
import torch.nn as nn
from matplotlib import pyplot as plt
import pandas as pd
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falsedef model_training(x_train, y_train, x_val, y_val, n_epochs, optimizer, model, loss_fn):""" 训练 """for epoch in range(1, n_epochs + 1):# 前向传播y_pred_train = model(x_train)loss_train = loss_fn(y_pred_train, y_train)y_pred_val = model(x_val)loss_val = loss_fn(y_pred_val, y_val)# 梯度清零optimizer.zero_grad()# 反向传播loss_train.backward()# 更新参数optimizer.step()if epoch == 1 or epoch % 100 == 0:print(f'轮次:{epoch},\t训练损失:{float(loss_train)},\t验证损失:{float(loss_val)}')def main():learning_rate = 1e-1# 设置随机数种子seed = 1torch.manual_seed(seed)torch.cuda.manual_seed_all(seed)# 加载奥运会数据file_path = "../datasets/Freestyle100m.csv"dataset = pd.read_csv(file_path)dataset_tensor = torch.tensor(dataset.values)  # 转换为tensorxx = dataset_tensor[:, 0]y = dataset_tensor[:, -1]# 为方便数值运算,将原来的举办年减去第一届奥运会年x = xx - xx[0]# 扩充一维,变为nn可以接受的shape和数据类型x = x.unsqueeze(1).float()y = y.unsqueeze(1).float()# 划分训练集验证集n_samples = x.shape[0]n_trin = int(0.7 * n_samples)# 随机置乱shuffled_idx = torch.randperm(n_samples)train_idx = shuffled_idx[:n_trin]val_idx = shuffled_idx[n_trin:]x_train = x[train_idx]y_train = y[train_idx]x_val = x[val_idx]y_val = y[val_idx]# 定义模型# 读者可尝试使用两种模型定义中的一种,看看有什么区别# 第一种定义# seq_model = nn.Sequential(#         nn.Linear(1, 10),#         nn.LogSigmoid(),#         nn.Linear(10, 1)# )# 第二种定义from collections import OrderedDictseq_model = nn.Sequential(OrderedDict([('hidden_linear', nn.Linear(1, 10)),('hidden_activation', nn.LogSigmoid()),('output_linear', nn.Linear(10, 1))]))# 打印模型信息print(seq_model)for name, param in seq_model.named_parameters():print("{:21} {:19} {}".format(name, str(param.shape), param.numel()))optimizer = optim.Adam(seq_model.parameters(), lr=learning_rate)# 使用开箱即用的损失函数model_training(x_train=x_train,y_train=y_train,x_val=x_val,y_val=y_val,n_epochs=3000,optimizer=optimizer,model=seq_model,loss_fn=nn.MSELoss())print('优化后的模型参数')for name, param in seq_model.named_parameters():print(name, param)# 绘图plt.plot(xx.numpy(), y.numpy(), 'go', label=u'数据')x_range = torch.arange(min(xx), max(xx)).unsqueeze(1)plt.plot(x_range.numpy(), seq_model(x_range - xx[0]).detach().numpy(), 'r-', label=u'模型')plt.plot(xx.numpy(), seq_model(x).detach().numpy(), 'bx', label=u'预测')plt.xlabel(u'奥运会年')plt.ylabel(u'取胜时间(秒)')plt.legend()plt.show()if __name__ == "__main__":main()
3)使用torch.nn.Module训练线性回归模型

使用nn.Module实现自定义线性模型。

创建文件linear_regression_nn_module.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
使用torch.nn.Module训练线性回归模型
"""import torch
import torch.optim as optim
import torch.nn as nn
from matplotlib import pyplot as plt
import pandas as pd
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falseclass LinearModel(nn.Module):""" 自定义模型 """def __init__(self):super().__init__()self.hidden_linear = nn.Linear(1, 10)self.activation = nn.LogSigmoid()self.output_linear = nn.Linear(10, 1)def forward(self, input):output = self.hidden_linear(input)output = self.activation(output)output = self.output_linear(output)return outputdef model_training(x_train, y_train, x_val, y_val, n_epochs, optimizer, model, loss_fn):""" 训练 """for epoch in range(1, n_epochs + 1):# 前向传播y_pred_train = model(x_train)loss_train = loss_fn(y_pred_train, y_train)y_pred_val = model(x_val)loss_val = loss_fn(y_pred_val, y_val)# 梯度清零optimizer.zero_grad()# 反向传播loss_train.backward()# 更新参数optimizer.step()if epoch == 1 or epoch % 100 == 0:print(f'轮次:{epoch},\t训练损失:{float(loss_train)},\t验证损失:{float(loss_val)}')def main():learning_rate = 1e-1# 设置随机数种子seed = 1torch.manual_seed(seed)torch.cuda.manual_seed_all(seed)# 加载奥运会数据file_path = "../datasets/Freestyle100m.csv"dataset = pd.read_csv(file_path)dataset_tensor = torch.tensor(dataset.values)  # 转换为tensorxx = dataset_tensor[:, 0]y = dataset_tensor[:, -1]# 为方便数值运算,将原来的举办年减去第一届奥运会年x = xx - xx[0]# 扩充一维,变为nn可以接受的shape和数据类型x = x.unsqueeze(1).float()y = y.unsqueeze(1).float()# 划分训练集验证集n_samples = x.shape[0]n_trin = int(0.7 * n_samples)# 随机置乱shuffled_idx = torch.randperm(n_samples)train_idx = shuffled_idx[:n_trin]val_idx = shuffled_idx[n_trin:]x_train = x[train_idx]y_train = y[train_idx]x_val = x[val_idx]y_val = y[val_idx]# 定义模型linear_model = LinearModel()# 打印模型信息print(linear_model)for name, param in linear_model.named_parameters():print("{:21} {:19} {}".format(name, str(param.shape), param.numel()))optimizer = optim.Adam(linear_model.parameters(), lr=learning_rate)# 使用开箱即用的损失函数model_training(x_train=x_train,y_train=y_train,x_val=x_val,y_val=y_val,n_epochs=3000,optimizer=optimizer,model=linear_model,loss_fn=nn.MSELoss())print('优化后的模型参数')for name, param in linear_model.named_parameters():print(name, param)# 绘图plt.plot(xx.numpy(), y.numpy(), 'go', label=u'数据')x_range = torch.arange(min(xx), max(xx)).unsqueeze(1)plt.plot(x_range.numpy(), linear_model(x_range - xx[0]).detach().numpy(), 'r-', label=u'模型')plt.plot(xx.numpy(), linear_model(x).detach().numpy(), 'bx', label=u'预测')plt.xlabel(u'奥运会年')plt.ylabel(u'取胜时间(秒)')plt.legend()plt.show()if __name__ == "__main__":main()

3.逻辑回归

线性回归解决回归问题;逻辑回归主要解决分类问题。区别在于前者目标值连续;后者是离散的。

可以将逻辑回归视为神经网络的一个神经元

1)介绍

思路:

1.假设函数:使用激活函数求输出。Sigmoid函数很好模拟了阶跃函数

2.代价函数:求代价使用负对数似然代价函数表示。

3.逻辑回归梯度下降算法

2)从0开始实现逻辑回归模型

创建文件logistic_regression_from_scratch.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
从头开始实现逻辑回归模型
"""import torch
import numpy as np
from matplotlib import pyplot as plt
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = Falsedef sigmoid(z):""" S型激活函数 """g = 1 / (1 + torch.exp(-z))return gdef model(x, w, b):""" 逻辑回归模型 """return sigmoid(x.mv(w) + b)def loss_fn(y_pred, y):""" 损失函数 """loss = - y.mul(y_pred.view_as(y)) - (1 - y).mul(1 - y_pred.view_as(y))return loss.mean()def grad_loss_fn(y_pred, y):""" 损失函数求导 """return y_pred.view_as(y) - ydef grad_fn(x, y, y_pred):""" 梯度函数 """grad_w = grad_loss_fn(y_pred, y) * xgrad_b = grad_loss_fn(y_pred, y)return torch.cat((grad_w.mean(dim=0), grad_b.mean().unsqueeze(0)), 0)def model_training(x, y, n_epochs, learning_rate, params, print_params=True):""" 训练 """for epoch in range(1, n_epochs + 1):w, b = params[: -1], params[-1]# 前向传播y_pred = model(x, w, b)# 计算损失loss = loss_fn(y_pred, y)# 梯度grad = grad_fn(x, y, y_pred)# 更新参数params -= learning_rate * gradif epoch == 1 or epoch % 10 == 1:print('轮次:%d,\t损失:%f' % (epoch, float(loss)))if print_params:print(f'参数:{params.detach().numpy()}')print(f'梯度:{grad.detach().numpy()}')return paramsdef generate_data():""" 随机生成数据 """np.random.seed(0)# 使用二个高斯分布来生成随机数据phi = 0.6means = [[0.0, -3.2], [1.0, 3.5]]covs = np.zeros((2, 2, 2))covs[0] = [[0.58, -0.05], [-0.05, 1.55]]covs[1] = [[0.65, -0.15], [-0.15, 1.12]]priors = [1 - phi, phi]n = 100x = np.zeros((n, 2))y = np.zeros((n, 1))# 选择一个高斯,并随机抽样数据for i in range(n):comp = np.random.choice(2, p=priors)x[i] = np.random.multivariate_normal(means[comp], covs[comp], 1)y[i] = compreturn torch.from_numpy(x).float(), torch.from_numpy(y).float()def plot_decision_boundary(x, y, theta):"""绘制二元分类问题的决策边界输入参数x:输入,y:输出,theta:参数输出参数无"""plt.figure()neg_x = x[np.where(y[:, 0] == 0)]pos_x = x[np.where(y[:, 0] == 1)]neg = plt.scatter(neg_x[:, 0], neg_x[:, 1], c='b', marker='o')pos = plt.scatter(pos_x[:, 0], pos_x[:, 1], c='r', marker='+')# 绘制决策边界# 只需要两点便可以定义一条直线,选择两个端点plot_x = np.array([min(x[:, 0]), max(x[:, 0])])# 计算决策边界线,theta0 + theta1*x + theta2*y = 0# 已知x,可计算yplot_y = np.dot(np.divide(-1, theta[1]), (theta[2] + np.dot(theta[0], plot_x)))lr, = plt.plot(plot_x, plot_y, 'g')  # 绘制拟合直线# 坐标plt.xlabel('x1')plt.ylabel('x2')# 图例plt.legend([neg, pos, lr], ['负例', '正例', u'决策边界'], loc='lower right')plt.show()def main():# 随机生成数据x, y = generate_data()# 模型参数初始化w = torch.zeros(2)b = torch.zeros(1)# 直接用未优化的模型来预测y_pred = model(x, w, b)print('未优化的模型的预测结果:', y_pred.detach().numpy())loss = loss_fn(y_pred, y)print('未优化的模型的损失:', loss.detach().numpy())params = model_training(x=x,y=y,n_epochs=500,learning_rate=0.1,params=torch.tensor([0.0, 0.0, 0.0]))print(f'梯度下降找到的w和b:{params.numpy()} \n')y_pred = model(x, params[: -1], params[-1])print(f'优化后的模型的预测结果:{y_pred.detach().numpy()}\n')# 绘制决策边界plot_decision_boundary(x, y, params)if __name__ == "__main__":main()

运行结果:
在这里插入图片描述

3)使用Pytorch实现逻辑回归模型

使用nn.Sequential定义模型;nn.Sigmoid定义激活函数。

创建文件logistic_regression_concise.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
简洁实现逻辑回归模型
"""
import torch
import torch.optim as optim
import torch.nn as nn
import numpy as np
from matplotlib import pyplot as plt
import matplotlib as mpl# 防止plt汉字乱码
mpl.rcParams[u'font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
def model_training(x, y, n_epochs, optimizer, model, loss_fn):""" 训练 """for epoch in range(1, n_epochs + 1):# 前向传播y_pred = model(x)# 计算损失loss = loss_fn(y_pred, y)# 梯度清零optimizer.zero_grad()# 反向传播loss.backward()# 更新参数optimizer.step()if epoch == 1 or epoch % 10 == 1:print('轮次:%d,\t损失:%f' % (epoch, float(loss)))def generate_data():""" 随机生成数据 """np.random.seed(0)# 使用二个高斯分布来生成随机数据phi = 0.6means = [[0.0, -3.2], [1.0, 3.5]]covs = np.zeros((2, 2, 2))covs[0] = [[0.58, -0.05], [-0.05, 1.55]]covs[1] = [[0.65, -0.15], [-0.15, 1.12]]priors = [1 - phi, phi]n = 100x = np.zeros((n, 2))y = np.zeros((n, 1))# 选择一个高斯,并随机抽样数据for i in range(n):comp = np.random.choice(2, p=priors)x[i] = np.random.multivariate_normal(means[comp], covs[comp], 1)y[i] = compreturn torch.from_numpy(x).float(), torch.from_numpy(y).float()def plot_decision_boundary(x, y, model):"""绘制二元分类问题的决策边界输入参数x:输入,y:输出,model:模型输出参数无"""plt.figure()neg_x = x[np.where(y[:, 0] == 0)]pos_x = x[np.where(y[:, 0] == 1)]neg = plt.scatter(neg_x[:, 0], neg_x[:, 1], c='b', marker='o')pos = plt.scatter(pos_x[:, 0], pos_x[:, 1], c='r', marker='+')# 绘制决策边界# 网格范围u = np.linspace(min(x[:, 0]), max(x[:, 0]), 150)v = np.linspace(min(x[:, 1]), max(x[:, 1]), 150)uu, vv = np.meshgrid(u, v)  # 生成网格数据z = model(torch.cat((torch.from_numpy(uu.ravel()).float().unsqueeze(1),torch.from_numpy(vv.ravel()).float().unsqueeze(1)), 1))# 保持维度一致z = z.detach().numpy().reshape(uu.shape)# 画图plt.contour(uu, vv, z, 0)# 坐标plt.xlabel('x1')plt.ylabel('x2')# 图例plt.legend([neg, pos], ['负例', '正例'], loc='lower right')plt.show()def main():# 随机生成数据x, y = generate_data()# 定义模型seq_model = nn.Sequential(nn.Linear(2, 1),nn.Sigmoid())# 打印模型信息print(seq_model)# 模型参数初始化print('\n使用SGD训练模型')learning_rate = 0.1# 使用optim模块中的现成优化器optimizer = optim.SGD(seq_model.parameters(), lr=learning_rate)model_training(x=x,y=y,n_epochs=500,optimizer=optimizer,model=seq_model,loss_fn=nn.BCELoss())print('优化后的模型参数')for name, param in seq_model.named_parameters():print(name, param)y_pred = seq_model(x)print(f'优化后的模型的预测结果:{y_pred.detach().numpy()}\n')# 绘制决策边界plot_decision_boundary(x, y, seq_model)if __name__ == "__main__":main()

4.softmax回归

解决多元分类问题可以使用softmax回归。softmax回归的输出单元数k>2,对应k个类别的预测概率分布。训练好模型后,选择概率最大的类别作为预测类别。

1)介绍

思想:

1.假设函数,概率分布归一化

2.代价函数使用交叉熵

2)从头开始实现softmax回归

创建文件softmax_regression_from_scratch.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
从头开始实现softmax回归
"""import torch
import torchvision
import torchvision.transforms as transforms
from torch.utils import data
import numpy as np# 超参数
num_inputs = 784
num_outputs = 10def softmax(z):"""实现Softmax激活函数。每一个Z减去一个max值是为了避免数值溢出输入参数:z:二维Tensor数组返回:a:softmax(z)输出,与z的shape一致"""z_rescale = z - torch.max(z, dim=1, keepdim=True)[0]a = torch.exp(z_rescale) / torch.sum(torch.exp(z_rescale), dim=1, keepdim=True)assert (a.shape == z.shape)return adef model(x, w, b):""" 定义Softmax模型 """return softmax(torch.mm(x.view((-1, num_inputs)), w) + b)def cross_entropy(y_hat, y):""" 计算交叉熵 """return - torch.log(y_hat.gather(1, y.view(-1, 1)))def grad_loss_fn(y_pred, y):""" 损失函数求导 """return y_pred - torch.nn.functional.one_hot(y, num_classes=10)def grad_fn(x, y, y_pred):""" 梯度函数 """grad_w = torch.mm(x.view((-1, num_inputs)).T, grad_loss_fn(y_pred, y))grad_b = grad_loss_fn(y_pred, y)return [grad_w, grad_b.mean(dim=0)]def accuracy(y_hat, y):""" 计算分类准确率 """_, pred_y = torch.max(y_hat, 1)return (pred_y == y).mean().item()def evaluate_accuracy(data_iter, net, w, b):""" 计算准确率 """correct_acc, n = 0.0, 0for x, y in data_iter:_, pred_y = torch.max(net(x, w, b).data, 1)correct_acc += (pred_y == y).sum().item()n += y.shape[0]return correct_acc / ndef train(net, train_iter, test_iter, loss, num_epochs, params, lr):""" 模型训练 """w, b = paramsfor epoch in range(num_epochs):train_loss_sum, train_acc_sum, n = 0.0, 0.0, 0for x, y in train_iter:# 前向传播y_pred = net(x, w, b)# 计算损失loss_mini_batch = loss(y_pred, y).sum()# 梯度grad = grad_fn(x, y, y_pred)# 更新参数for i in range(len(params)):params[i] -= lr * grad[i]# 统计train_loss_sum += loss_mini_batch.item()train_acc_sum += (y_pred.argmax(dim=1) == y).sum().item()n += y.shape[0]# 测试准确率test_acc = evaluate_accuracy(test_iter, net, w, b)print('轮次:%d,损失%.4f,训练准确率:%.3f,测试准确率:%.3f'% (epoch + 1, train_loss_sum / n, train_acc_sum / n, test_acc))def get_labels_by_indices(labels):""" 返回目标索引对应的标签字符串 """text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat', 'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']return [text_labels[int(i)] for i in labels]def main():# 超参数num_epochs, learning_rate, batch_size = 5, 0.001, 32# 加载数据集mnist_train = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=True, download=False,transform=transforms.ToTensor())train_iter = data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True)mnist_test = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=False, download=False,transform=transforms.ToTensor())test_iter = data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False)# 参数w = torch.tensor(np.random.normal(0, 0.01, (num_inputs, num_outputs)), dtype=torch.float, requires_grad=False)b = torch.zeros(num_outputs, dtype=torch.float, requires_grad=False)# 训练模型train(model, train_iter, test_iter, cross_entropy, num_epochs, [w, b], learning_rate)# 显示部分测试数据的真实标签和预测标签x, y = next(iter(test_iter))true_labels = get_labels_by_indices(y.numpy())pred_labels = get_labels_by_indices(model(x, w, b).argmax(dim=1).numpy())for true_label, pred_label in zip(true_labels, pred_labels):print(f"真实标签:{true_label}\t预测标签:{pred_label}")if __name__ == '__main__':main()
3)使用Pytorch实现softmax回归

使用Pytorch的自动求导功能。

创建文件softmax_regression.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
softmax回归实现
"""import torch
import torchvision
import torchvision.transforms as transforms
from torch import nn
from torch.utils import data
import torch.nn.functional as Fclass Net(nn.Module):""" 定义Softmax模型 """def __init__(self):super(Net, self).__init__()self.fc1 = nn.Linear(784, 10)def forward(self, x):# 展平数据 (n, 1, 28, 28) --> (n, 784)x = x.view(-1, 784)return F.softmax(self.fc1(x), dim=1)def train(epochs, train_loader, model, optimizer, loss_fn, print_every):""" 迭代训练模型 """for epoch in range(epochs):# 每次输入batch_idx个数据loss_acc = 0.0  # 累计损失for batch_idx, (data, target) in enumerate(train_loader):# 梯度清零optimizer.zero_grad()# 前向传播output = model(data)# 损失loss = loss_fn(output, target)# 反向传播loss.backward()# 更新参数optimizer.step()loss_acc += loss.item()if batch_idx % print_every == print_every - 1:print('[%d, %5d] 损失: %.3f' % (epoch + 1, batch_idx + 1, loss_acc / print_every))loss_acc = 0.0print('完成训练!')def test(model, test_loader):""" 测试 """correct = 0total = 0# 预测不需要梯度来修改参数with torch.no_grad():for data in test_loader:images, labels = dataoutputs = model(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print('在测试集中的预测准确率: {:.2%}'.format(correct / total))def main():# 超参数num_epochs = 5batch_size = 16print_every = 200learning_rate = 0.001# 加载数据集mnist_train = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=True, download=False,transform=transforms.ToTensor())train_loader = data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True)mnist_test = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=False, download=False,transform=transforms.ToTensor())test_loader = data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False)model = Net()# 交叉熵损失函数loss_fn = nn.CrossEntropyLoss()# 优化算法optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)train(num_epochs, train_loader, model, optimizer, loss_fn, print_every)test(model, test_loader)if __name__ == '__main__':main()

运行结果:

轮次:1,损失0.6634,训练准确率:0.782,测试准确率:0.805
轮次:2,损失0.5175,训练准确率:0.826,测试准确率:0.817
轮次:3,损失0.4881,训练准确率:0.835,测试准确率:0.827
轮次:4,损失0.4720,训练准确率:0.840,测试准确率:0.830
轮次:5,损失0.4616,训练准确率:0.844,测试准确率:0.830
真实标签:ankle boot 预测标签:ankle boot
真实标签:pullover 预测标签:pullover
真实标签:trouser 预测标签:trouser
真实标签:trouser 预测标签:trouser
真实标签:shirt 预测标签:shirt
真实标签:trouser 预测标签:trouser
真实标签:coat 预测标签:coat
真实标签:shirt 预测标签:shirt
真实标签:sandal 预测标签:sandal
真实标签:sneaker 预测标签:sneaker
真实标签:coat 预测标签:coat
真实标签:sandal 预测标签:sandal
真实标签:sneaker 预测标签:sandal
真实标签:dress 预测标签:dress
真实标签:coat 预测标签:coat
真实标签:trouser 预测标签:trouser
真实标签:pullover 预测标签:pullover
真实标签:coat 预测标签:pullover
真实标签:bag 预测标签:bag
真实标签:t-shirt 预测标签:t-shirt
真实标签:pullover 预测标签:pullover
真实标签:sandal 预测标签:sneaker
真实标签:sneaker 预测标签:sneaker
真实标签:ankle boot 预测标签:sneaker
真实标签:trouser 预测标签:trouser
真实标签:coat 预测标签:pullover
真实标签:shirt 预测标签:shirt
真实标签:t-shirt 预测标签:t-shirt
真实标签:ankle boot 预测标签:ankle boot
真实标签:dress 预测标签:dress
真实标签:bag 预测标签:bag
真实标签:bag 预测标签:bag

5.神经网络

1)神经元

线性回归实际上就是一个线性神经元。多变量线性回归实现了加权求和计算。增加了激活函数的神经元直接称为神经元

2)激活函数
1.绘制Sigmoid激活函数

创建文件plot_sigmoid.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
绘制Sigmoid激活函数"""import matplotlib.pyplot as plt
import numpy as np
import torch# x取值,start到stop范围内间隔均匀的100个数
x_vals = np.linspace(start=-10., stop=10., num=100)activation = torch.nn.Sigmoid()# Sigmoid激活函数
print(activation(torch.Tensor([-1., 0., 1.])))
y_vals = activation(torch.Tensor(x_vals))# 绘制Sigmoid激活函数图像
plt.plot(x_vals, y_vals, "r--", label="Sigmoid", linewidth=1.5)
plt.ylim([-0.5, 1.5])
plt.legend(loc="upper left")
plt.grid(axis="y")
plt.show()

运行结果:
在这里插入图片描述

2.绘制双曲正切Tanh激活函数

它是Sigmoid函数的变体,放大并平移

# -*- coding: utf-8 -*-
"""
绘制双曲正切Tanh激活函数
"""import matplotlib.pyplot as plt
import numpy as np
import torch# x取值,start到stop范围内间隔均匀的100个数
x_vals = np.linspace(start=-10., stop=10., num=100)activation = torch.nn.Tanh()# 双曲正切激活函数
print(activation(torch.Tensor([-1., 0., 1.])))
y_vals = activation(torch.Tensor(x_vals))# 绘制Tanh激活函数图像
plt.plot(x_vals, y_vals, "r--", label="Tanh", linewidth=1.5)
plt.ylim([-1.5, 1.5])
plt.legend(loc="upper left")
plt.grid(axis="y")
plt.show()

运行结果:
在这里插入图片描述

3.绘制ReLU激活函数

创建文件display_olympics_freestyle100m.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
绘制ReLU激活函数
"""import matplotlib.pyplot as plt
import numpy as np
import torch# x取值,start到stop范围内间隔均匀的100个数
x_vals = np.linspace(start=-10., stop=10., num=100)relu = torch.nn.ReLU()
relu6 = torch.nn.ReLU6()# ReLU激活函数
print("ReLU: ", relu(torch.Tensor([-5., 5., 10.])))
y_relu = relu(torch.Tensor(x_vals))# ReLU-6激活函数
print("ReLU-6: ", relu6(torch.Tensor([-5., 5., 10.])))
y_relu6 = relu6(torch.Tensor(x_vals))# 绘制ReLU激活函数图像
plt.plot(x_vals, y_relu, "r:", label="ReLU", linewidth=1.5)
plt.plot(x_vals, y_relu6, "b-.", label="ReLU6", linewidth=1.5)
plt.ylim([-1, 8])
plt.legend(loc="upper left")
plt.grid(axis="y")
plt.show()

运行结果:

在这里插入图片描述

4.绘制LeakyReLU激活函数

创建文件display_olympics_freestyle100m.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
绘制LeakyReLU激活函数
"""import matplotlib.pyplot as plt
import numpy as np
import torch# x取值,start到stop范围内间隔均匀的100个数
x_vals = np.linspace(start=-10., stop=10., num=100)leaky_relu = torch.nn.LeakyReLU()
elu = torch.nn.ELU()# ReLU激活函数
print("Leaky ReLU: ", leaky_relu(torch.Tensor([-5., 5., 10.])))
y_leaky_relu = leaky_relu(torch.Tensor(x_vals))# ELU激活函数
print("ELU: ", elu(torch.Tensor([-5., 5., 10.])))
y_elu = elu(torch.Tensor(x_vals))# 绘制ReLU激活函数图像
plt.plot(x_vals, y_leaky_relu, "r:", label="Leaky ReLU", linewidth=1.5)
plt.plot(x_vals, y_elu, "b-.", label="ELU", linewidth=1.5)
plt.ylim([-1, 8])
plt.legend(loc="upper left")
plt.grid(axis="y")
plt.show()

运行结果:

在这里插入图片描述

5.softmax函数

主要用于神经网络最后一层,解决多元分类问题

6.选择正确的激活函数

中间层选ReLU;二元分类选Sigmoid;多元分类选Softmax函数;深层网络一般避免Tanh函数和Sigmoid函数;如果出现较多死亡神经元,用Leaky ReLU和ELU函数代替

3)神经网络原理

主要思想:

1.神经网络表示和结构;

2.前向传播;

3.代价函数:训练权重和偏置。一般采用交叉熵代价函数

4.BP算法:即反向传播算法。用于优化神经网络参数算法,推荐使用Pytorch的自动求导解决方案。

4)Pytorch实现神经网络

nn.Sequential定义一个简单的神经网络模型;

另一种方式是使用nn.Module定义神经网络。

两种方式实现如下,

创建文件neural_networks_initialization.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
PyTorch定义神经网络及参数初始化
"""import torch
from torch import nn
from torch.nn import initnum_inputs, num_hiddens, num_outputs = 4, 5, 3# nn.Sequential定义一个简单的神经网络模型
seq_model = nn.Sequential(nn.Linear(num_inputs, num_hiddens),nn.ReLU(),nn.Linear(num_hiddens, num_hiddens),nn.ReLU(),nn.Linear(num_hiddens, num_outputs),nn.Softmax(dim=1),
)class Net(nn.Module):""" 定义一个简单的神经网络模型 """def __init__(self):super().__init__()self.fc1 = nn.Linear(num_inputs, num_hiddens)self.act1 = nn.ReLU()self.fc2 = nn.Linear(num_hiddens, num_hiddens)self.act2 = nn.ReLU()self.fc3 = nn.Linear(num_hiddens, num_outputs)self.act3 = nn.Softmax(dim=1)def forward(self, x):x = self.act1(self.fc1(x))x = self.act2(self.fc2(x))return self.act3(self.fc3(x))def weights_init(m):""" 初始化网络权重 """if isinstance(m, nn.Conv2d):init.normal_(m.weight.data)# init.xavier_normal_(m.weight.data)# init.kaiming_normal_(m.weight.data)  # 卷积层参数初始化m.bias.data.fill_(0)elif isinstance(m, nn.Linear):m.weight.data.normal_()  # 全连接层参数初始化def main():# 初始化for params in seq_model.parameters():init.normal_(params, mean=0, std=0.01)print("nn.Sequential定义的网络:")print(seq_model)for name, param in seq_model.named_parameters():print(name, param.shape)# 随机初始化输入xx = torch.randn(10, 4)y_hat = seq_model(x)print(y_hat)model = Net()# 网络参数初始化model.apply(weights_init)  # apply函数会递归搜索网络中的子模块并应用初始化print("nnn.Module定义的网络:")print(model)y_hat = model(x)print(y_hat)if __name__ == "__main__":main()
5)神经网络应用示例一

需求:FashionMNIST分类问题。

创建文件neural_networks_demo1.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
PyTorch实现神经网络示例一
"""import torch
import torchvision
import torchvision.transforms as transforms
from torch import nn
from torch.utils import data
from torch.nn import initnum_inputs, num_hiddens, num_outputs = 784, 256, 10# nn.Sequential模型
net = nn.Sequential(nn.Linear(num_inputs, num_hiddens),nn.ReLU(),nn.Linear(num_hiddens, num_outputs),
)for params in net.parameters():init.normal_(params, mean=0, std=0.01)def train(epochs, train_loader, model, optimizer, loss_fn, print_every):""" 迭代训练模型 """for epoch in range(epochs):loss_acc = 0.0  # 累计损失# 每次输入第batch_idx批数据for batch_idx, (data, target) in enumerate(train_loader):# 梯度清零optimizer.zero_grad()# 前向传播output = model(data.view(data.shape[0], -1))# 损失loss = loss_fn(output, target)# 反向传播loss.backward()# 更新参数optimizer.step()loss_acc += loss.item()if batch_idx % print_every == print_every - 1:print('[%d, %5d] 损失: %.3f' % (epoch + 1, batch_idx + 1, loss_acc / print_every))loss_acc = 0.0print('完成训练!')def test(model, test_loader):""" 模型测试 """correct = 0total = 0# 预测不需要梯度来修改参数with torch.no_grad():for data in test_loader:images, labels = dataoutputs = model(images.view(images.shape[0], -1))_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print('在测试集中的预测准确率: {:.2%}'.format(correct / total))def main():# 超参数num_epochs = 5batch_size = 16print_every = 200learning_rate = 0.001# 加载数据集mnist_train = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=True, download=False,transform=transforms.ToTensor())train_loader = data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True)mnist_test = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=False, download=False,transform=transforms.ToTensor())test_loader = data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False)# 交叉熵损失函数loss_fn = nn.CrossEntropyLoss()# 优化算法optimizer = torch.optim.Adam(net.parameters(), lr=learning_rate)# 训练与评估train(num_epochs, train_loader, net, optimizer, loss_fn, print_every)test(net, test_loader)if __name__ == '__main__':main()
6)神经网络应用示例二

示例二使用nn.Module定义网络模型

创建文件neural_networks_demo2.py
添加代码如下:

# -*- coding: utf-8 -*-
"""
PyTorch实现神经网络示例二
"""import torch
import torchvision
import torchvision.transforms as transforms
from torch import nn
from torch.utils import data
import torch.nn.functional as Fnum_inputs, num_hiddens, num_outputs = 784, 256, 10class Net(nn.Module):""" nn.Module定义网络模型 """def __init__(self):super(Net, self).__init__()self.fc1 = nn.Linear(num_inputs, num_hiddens)self.fc2 = nn.Linear(num_hiddens, num_outputs)def forward(self, x):# 展平数据 (n, 1, 28, 28) --> (n, 784)x = x.view(x.shape[0], -1)x = F.relu(self.fc1(x))return F.log_softmax(self.fc2(x), dim=1)def train(epochs, train_loader, model, optimizer, loss_fn, print_every):""" 迭代训练模型 """for epoch in range(epochs):loss_acc = 0.0  # 累计损失# 每次输入第batch_idx批数据for batch_idx, (data, target) in enumerate(train_loader):# 梯度清零optimizer.zero_grad()# 前向传播output = model(data)# 损失loss = loss_fn(output, target)# 反向传播loss.backward()# 更新参数optimizer.step()loss_acc += loss.item()if batch_idx % print_every == print_every - 1:print('[%d, %5d] 损失: %.3f' % (epoch + 1, batch_idx + 1, loss_acc / print_every))loss_acc = 0.0print('完成训练!')def test(model, test_loader):""" 模型测试 """correct = 0total = 0# 预测不需要梯度来修改参数with torch.no_grad():for data in test_loader:images, labels = dataoutputs = model(images)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print('在测试集中的预测准确率: {:.2%}'.format(correct / total))def main():# 超参数num_epochs = 5batch_size = 16print_every = 200learning_rate = 0.001# 加载数据集mnist_train = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=True, download=False,transform=transforms.ToTensor())train_loader = data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True)mnist_test = torchvision.datasets.FashionMNIST(root='../datasets/FashionMNIST', train=False, download=False,transform=transforms.ToTensor())test_loader = data.DataLoader(mnist_test, batch_size=batch_size, shuffle=False)model = Net()# 负对数似然损失函数loss_fn = nn.NLLLoss()# 优化算法optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)# 训练与评估train(num_epochs, train_loader, model, optimizer, loss_fn, print_every)test(model, test_loader)if __name__ == '__main__':main()
7)两层神经网络解决异或问题
# -*- coding: utf-8 -*-
"""
两层神经网络解决异或问题
"""import torch
from torch import nndef main():# 设置随机数种子seed = 1torch.manual_seed(seed)torch.cuda.manual_seed_all(seed)# 定义输入单元数、隐藏层单元数、输出层单元数n_in, n_h, n_out = 2, 2, 1# 创建XOR数据集x = torch.tensor([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]])y = torch.tensor([[0.0], [1.0], [1.0], [0.0]])# 创建模型model = nn.Sequential(nn.Linear(n_in, n_h),nn.Sigmoid(),nn.Linear(n_h, n_out),nn.Sigmoid())# 损失函数criterion = nn.MSELoss()# 优化器optimizer = torch.optim.Adam(model.parameters(), lr=0.01)# 梯度下降for epoch in range(1, 1001):# 前向传播y_pred = model(x)# 计算损失loss = criterion(y_pred, y)if epoch == 1 or epoch % 100 == 0:print(f'轮次:{epoch},\t损失:{loss.item()}')# 梯度置零optimizer.zero_grad()# 反向传播loss.backward()# 更新参数optimizer.step()# 预测y_pred = model(x)print("输入为:\n{}".format(x))print('输出为:\n{}'.format(y_pred))if __name__ == "__main__":main()
8)Fizz Buzz神经网络实现
# -*- coding: utf-8 -*-
"""
Fizz Buzz神经网络实现
"""import numpy as np
import torchdef binary_encode(i, num_digits):""" 将输入的十进制i转换为位数是num_digits的二进制 """return np.array([i >> d & 1 for d in range(num_digits)])def fizz_buzz_encode(i):""" 将输入数字编码为标签 """if i % 3 == 0 and i % 5 == 0:return 3elif i % 5 == 0:return 2elif i % 3 == 0:return 1else:return 0def fizz_buzz_decode(i, encode):""" 解码为人类可读的输出 """return [str(i), "Fizz", "Buzz", "FizzBuzz"][encode]# 超参数
learning_rate = 0.05
epochs = 3000
batch_size = 128
num_digits = 10
num_hidden = 100# 构建训练集。使用101~1024作为训练数据
train_x = torch.tensor([binary_encode(i, num_digits) for i in range(101, 2 ** num_digits)]).float()
train_y = torch.tensor([fizz_buzz_encode(i) for i in range(101, 2 ** num_digits)]).long()
# 随机置乱
torch.manual_seed(123)
rand_idx = torch.randperm(len(train_y))
train_x = train_x[rand_idx, :]
train_y = train_y[rand_idx]# 定义网络模型
model = torch.nn.Sequential(torch.nn.Linear(num_digits, num_hidden),torch.nn.ReLU(),torch.nn.Linear(num_hidden, 4)
)# 定义损失函数和优化器
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)# 模型训练
model.train()
for epoch in range(epochs):for start in range(0, len(train_x), batch_size):end = start + batch_sizebatch_x = train_x[start:end]batch_y = train_y[start:end]y_hat = model(batch_x)loss = criterion(y_hat, batch_y)optimizer.zero_grad()loss.backward()optimizer.step()# 计算训练损失loss = criterion(model(train_x), train_y).item()print(f'Epoch:{epoch}\tLoss:{loss}')# 预测1~100
model.eval()
test_x = torch.tensor([binary_encode(i, num_digits) for i in range(1, 101)]).float()
test_y = torch.tensor([fizz_buzz_encode(i) for i in range(1, 101)]).long()
with torch.no_grad():pred_y = model(test_x)
predictions = zip(range(1, 101), list(pred_y.max(1)[1].data.tolist()))print("预测:", [fizz_buzz_decode(i, x) for (i, x) in predictions])
acc = np.sum(pred_y.max(1)[1].numpy() == np.array(test_y)) / len(test_y)
print("准确率:{:.2%}".format(acc))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/188098.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PyCharm+Miniconda3安装配置教程

PyCharm是Python著名的Python集成开发环境(IDE) conda有Miniconda和Anaconda,前者应该是类似最小化版本,后者可能是功能更为强大的版本,我们这里安装Miniconda 按官方文档的说法conda相当于pip与virtualenv的结合&am…

R系组播调优方案

修改/etc/sysctl.conf添加如下内容: Vim /etc/sysctl.con net.ipv4.ip_forward1 net.ipv4.ip_nonlocal_bind1 net.ipv4.conf.all.rp_filter0 net.ipv4.conf.default.rp_filter0 net.bridge.bridge-nf-call-arptables 0 net.bridge.bridge-nf-call-ip6tables 0 …

【数据结构】树与二叉树(十):二叉树的先序遍历(非递归算法NPO)

文章目录 5.2.1 二叉树二叉树性质引理5.1:二叉树中层数为i的结点至多有 2 i 2^i 2i个,其中 i ≥ 0 i \geq 0 i≥0。引理5.2:高度为k的二叉树中至多有 2 k 1 − 1 2^{k1}-1 2k1−1个结点,其中 k ≥ 0 k \geq 0 k≥0。引理5.3&…

Python实战:绘制直方图的示例代码,数据可视化获取样本分布特征

文章目录 一、初步二、参数三、绘图类型四、多组数据直方图对比Python技术资源分享1、Python所有方向的学习路线2、学习软件3、精品书籍4、入门学习视频5、实战案例6、清华编程大佬出品《漫画看学Python》7、Python副业兼职与全职路线 一、初步 对于大量样本来说,如…

2023年【危险化学品经营单位主要负责人】免费试题及危险化学品经营单位主要负责人证考试

题库来源:安全生产模拟考试一点通公众号小程序 2023年危险化学品经营单位主要负责人免费试题为正在备考危险化学品经营单位主要负责人操作证的学员准备的理论考试专题,每个月更新的危险化学品经营单位主要负责人证考试祝您顺利通过危险化学品经营单位主…

前端开发学习指南

前端是一个看似入门门槛不高,但要学好很难的领域。前端的知识体系庞杂又松散,技术演进快,如果摸不清脉络的话很容易陷入盲人摸象的困境甚至跑偏。 其实只要掌握了正确的方法,学习前端和学好前端就只是个时间问题,希望下…

OpenCV图像坐标系

绘制代码: X轴 # 选取两个点 point1 = (20, 0) point2 = (200, 0)# 在图像上绘制连接线 cv2.line(img, point1, point2, (

解决找不到x3daudio1_7.dll的方法,快速解决x3daudio1_7.dll丢失问题

在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是“找不到x3daudio1_7.dll”。这个问题可能是由于多种原因引起的,例如文件丢失、损坏或被病毒感染等。下面将详细介绍如何解决这个问题。 首先,我们需要了解x3daudio1_…

Kotlin HashMap entries.filter过滤forEach

Kotlin HashMap entries.filter过滤forEach fun main(args: Array<String>) {val hashMap HashMap<String, Int>()hashMap["a"] 1hashMap["b"] 2hashMap["c"] 3println(hashMap)hashMap.entries.filter {println("filter $…

2023年【北京市安全员-C3证】考试题库及北京市安全员-C3证在线考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 北京市安全员-C3证考试题库是安全生产模拟考试一点通总题库中生成的一套北京市安全员-C3证在线考试&#xff0c;安全生产模拟考试一点通上北京市安全员-C3证作业手机同步练习。2023年【北京市安全员-C3证】考试题库及…

Nignx及负载均衡动静分离

目录 一.Nginx负载均衡 1.1.下载 1.2.安装 1.3.负载均衡 二.前端部署 2.1. 准备工作 2.2.部署 好啦今天就到这里了哦&#xff01;&#xff01;&#xff01;希望能帮到你哦&#xff01;&#xff01;&#xff01; 一.Nginx负载均衡 1.1.下载 输入命令 : cd javaCloudJun/…

键盘win键无法使用,win+r不生效、win键没反应、Windows键失灵解决方案(亲测可以解决)

最近几天发现自己笔记本的win键无法使用&#xff0c;win失灵了&#xff0c;但是外接键盘后则正常:。 这个问题困扰了我一周&#xff0c;我都以为自己的枪神坏了。 寻找了几个解决方法&#xff0c;网上看了好多好多稀里糊涂的办法&#xff0c;都是不管用的&#xff0c;这里给大…

超简单的Linux FTP服务搭建教程

目录 前言1、检查vsftp是否已安装2、安装vsftpd3、启动ftp服务4、测试ftp服务5、上传文件配置总结 前言 本文记录了在Kylin Linux Desktop V10(SP1)系统上搭建FTP服务的过程。FTP是File Transfer Protocol的缩写&#xff0c;译为文件传输协议&#xff0c;是用于在网络上进行文…

向量的点积和外积

参考&#xff1a;https://www.cnblogs.com/gxcdream/p/7597865.html 一、向量的内积&#xff08;点乘&#xff09; 定义&#xff1a; 两个向量a与b的内积为 ab |a||b|cos∠(a, b)&#xff0c;特别地&#xff0c;0a a0 0&#xff1b;若a&#xff0c;b是非零向量&#xff0c;…

【读点论文】结构化剪枝

结构化剪枝 在一个神经网络模型中&#xff0c;通常包含卷积层、汇合层、全连接层、非线形层等基本结构&#xff0c;通过这些基本结构的堆叠&#xff0c;最终形成我们所常用的深度神经网络。 早在 1998 年&#xff0c;LeCun 等人使用少数几个基本结构组成 5 层的 LeNet-5 网络&…

GitHub Copilot Chat将于12月全面推出;DeepLearning.AI免费新课

&#x1f989; AI新闻 &#x1f680; GitHub Copilot Chat将于12月全面推出&#xff0c;提升开发者的生产力 摘要&#xff1a;GitHub宣布将于12月全面推出GitHub Copilot Chat&#xff0c;这是GitHub Copilot的一个新功能&#xff0c;旨在帮助开发者编写代码。它能够集成到开…

解决Docker启动之npm版本不兼容问题

报错内容&#xff1a; npm WARN read-shrinkwrap This version of npm is compatible with lockfileVersion1, but package-lock.json was generated for lockfileVersion2. Ill try to do my best with it! npm WARN tar ENOENT: no such file or directory, open /home/wvp-…

一个轻量级 Java 权限认证框架——Sa-Token

一、框架介绍 Sa-Token 是一个轻量级 Java 权限认证框架&#xff0c;主要解决&#xff1a;登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权 等一系列权限相关问题。 官网文档: https://sa-token.cc/doc.html 二、Spring Boot 集成Sa-Token 2.1、…

【机器学习】七、降维与度量学习

1. 维数灾难 样本的特征数称为维数&#xff08;dimensionality&#xff09;&#xff0c;当维数非常大时&#xff0c;也就是现在所说的维数灾难。 维数灾难具体表现在&#xff1a;在高维情形下&#xff0c;数据样本将变得十分稀疏&#xff0c;因为此时要满足训练样本为“密采样…

函数的连续性

函数在某一点极限存在&#xff0c;不一定连续 函数的左极限 函数的右极限 函数在某点连续需要满足三个条件 1、左右极限存在 2、左右极限相等 3、函数在该点的极限值等于在该点的函数值 满足1、2两个条件函数在该点极限存在。