当前位置: 首页 > news >正文

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))

相关文章:

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

文章目录 1.线性回归1)介绍2)加载自由泳冠军数据集3)从0开始实现线性回归模型4)使用自动求导训练线性回归模型5)使用优化器训练线性回归模型 2.使用torch.nn模块构建线性回归模型1)使用torch.nn.Linear训练…...

360导航恶意修改浏览器启动页!我的chrome和IE均中招,如何解决?

0,关闭360等“安全”软件 1,按下组合键winR 2,输入regedit,回车 3,按下组合键ctrlF 4,输入http://hao.360.cn,查找下一个 5,查到一个注册表键值就删一个,一个不放过…...

RabbitMQ的高级特性

目录 数据导入 MQ的常见问题 消息可靠性问题 生产者确认机制 SpringAMQP实现生产者确认 消息持久化 消费者消息确认 失败重试机制 消费者失败消息处理策略 死信交换机 TTL 延时队列 安装插件 SpringAMQP使用插件 消息堆积问题 惰性队列 MQ的高可用 普通集群 …...

Java自学第10课:JavaBean和servlet基础

目录 目录 1 JavaBean (1)概念 (2)分类 (3)使用 2 servlet (1)代码结构 (2)常用接口 (3)如何开发 1 新建servlet 2 配置 1…...

AR打卡小程序:构建智能办公的新可能

【内容摘要】 随着技术的飞速发展,智能办公已不再是遥不可及的梦想。在这其中,AR打卡小程序以其独特的技术优势,正逐步成为新型办公生态的重要组成部分。本文将探讨AR打卡小程序的设计理念、技术实现以及未来的应用前景,并尝试深…...

Python环境安装、Pycharm开发工具安装(IDE)

Python下载 Python官网 Python安装 Python安装成功 Pycharm集成开发工具下载(IDE) PC集成开发工具 Pycharm集成开发工具安装(IDE) 安装完成 添加环境变量(前面勾选了Path不用配置) (1&…...

报时机器人的rasa shell执行流程分析

本文以报时机器人为载体,介绍了报时机器人的对话能力范围、配置文件功能和训练和运行命令,重点介绍了rasa shell命令启动后的程序执行过程。 一.报时机器人项目结构 1.对话能力范围 (1)能够识别欢迎语意图(greet)和拜拜意图(goodbye) (2)能够识别时间意…...

C#开发的OpenRA游戏之世界存在的属性UpdatesPlayerStatistics(2)

C#开发的OpenRA游戏之世界存在的属性UpdatesPlayerStatistics(2) 在文件OpenRA\mods\cnc\rules\ defaults.yaml里,可以看到这个配置,它的作用就是让这个单元可以被观察者查看到相关的信息。 UpdatesPlayerStatistics属性同样也是有两个类组成,一个叫做信息类UpdatesPlay…...

Ocelot:.NET开源API网关提供路由管理、服务发现、鉴权限流等功能

随着微服务的兴起,API网关越来越常见。API网关是连接应用程序和用户之间的桥梁,就像一个交通指挥员,负责处理所有进出应用的数据和请求,确保安全、高效、有序地流通。 今天给大家推荐一个.NET开源API网关。 01 项目简介 Ocelot…...

wsl [Ubuntu20.04.6] 安装 Hadoop

文章目录 1.安装WSL2.安装Java安装Hadoop3.3配置文件1.修改hadoop-env.sh2.修改core-site.xml3.修改hdfs-site.xml ssh启动 1.安装WSL 重启电脑 管理员打开powershell PS C:\windows\system32> wsl --list --online PS C:\windows\system32> wsl --install -d Ubuntu-2…...

2023华为ict网络赛道初赛(部分)试题

2023华为ict网络赛道初赛(部分)试题 10.在网络运维中,Telnet是用于连接远程设备的协议之一,那么以下哪一个设备不支持通过Telnet协议远程连接? PCACAPAR 12.openFlow交换机基于流表转发报文,每个流表项由…...

rabbitMq虚拟主机概念

虚拟主机是RabbitMQ中的一种逻辑隔离机制,用于将消息队列、交换机以及其他相关资源进行隔离。 在RabbitMQ中,交换机(Exchange)用于接收生产者发送的消息,并根据特定的路由规则将消息分发到相应的队列中。而虚拟主机则…...

2-CentOS7.9下安装docker

默认情况下,CentOS7.9下有两种方法可以安装docker,分别是在线安装docker和离线安装docker(伪离线,最后还是需要网络支持) 1.环境信息 HostNameIPAddressOS VersionDocker VersionNotecentos79172.20.10.12CentOS Linux release 7.9.2009 (Core)Docker version 23.0.6, buil…...

【已验证-直接用】微信小程序wx.request请求服务器json数据并渲染到页面

微信小程序的数据总不能写死吧,肯定是要结合数据库来做数据更新,而小程序数据主要是json数据格式,所以我们可以利用php操作数据库,把数据以json格式数据输出即可。 现在给大家讲一下微信小程序的wx.request请求服务器获取数据的用…...

如何提高小红书笔记的互动率

相信有很多新手在运营小红书的时候,可能都会遇到过以下这样的情况: 笔记点赞、收藏数据明明还可以,但评论区却没有人留言?为何大家只给点赞、收藏,却不关注账号? 其实,这背后有很多运营技巧&a…...

RabbitMQ 系列教程

一、RabbitMQ 部署及配置详解(集群部署) 二、RabbitMQ 部署及配置详解 (单机) 三、RabbitMQ 详解及实例(含错误信息处理) 四、RabbitMq死信队列及其处理方案 五、RabbitMQ Java开发教程—官方原版 六、RabbitMQ Java开发教程(二&#x…...

无感刷新token

无感刷新 无感刷新Token技术是一种用于实现持久登录体验的关键技术,它通过在用户登录后自动刷新Token,以延长用户的登录状态,避免频繁要求用户重新登录。 实现 使用access_token(短效token)和refresh_token&#xf…...

【Python大数据笔记_day06_Hive】

hive内外表操作 建表语法 create [external] table [if not exists] 表名(字段名 字段类型 , 字段名 字段类型 , ... ) [partitioned by (分区字段名 分区字段类型)] # 分区表固定格式 [clustered by (分桶字段名) into 桶个数 buckets] # 分桶表固定格式 注意: 可以排序[so…...

Netty--文件编程

3. 文件编程 3.1 FileChannel ⚠️ FileChannel 工作模式 FileChannel 只能工作在阻塞模式下 获取 不能直接打开 FileChannel,必须通过 FileInputStream、FileOutputStream 或者 RandomAccessFile 来获取 FileChannel,它们都有 getChannel 方法 通过…...

SVN 服务器建立

1.建立SVN库 svnadmin create cat svndir/conf/passwd 修改SVN用户密码 chenht 123456 2.建立目录权限 [aliases] # joe /CXZ/STDessert/LSnake City/OSnake Oil, Ltd./OUResearch Institute/CNJoe Average [groups] # harry_and_sally harry,sally # harry_sally_…...

云计算——弹性云计算器(ECS)

弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

免费数学几何作图web平台

光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

基于Springboot+Vue的办公管理系统

角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

OD 算法题 B卷【正整数到Excel编号之间的转换】

文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...