学习笔记-李沐动手学深度学习(二)(08-09、线性回归、优化算法、Softmax回归、损失函数、图片分类)

总结

以_结尾的方法,好像是原位替换(即 原地修改,就地修改变量)如 fill_()

感恩的心:(沐神的直播环境)
在这里插入图片描述

08-线性回归+基础优化算法

引言(如何在美国买房)

根据现在行情预测房价
在这里插入图片描述
在这里插入图片描述

线性回归(简化模型)、线性模型、神经网络

b为偏差
在这里插入图片描述
扩展到一般化
在这里插入图片描述

线性模型
每个箭头代表一个权重
当层单层神经网络原因:不看输出层,将权重层和input放一起 带权重的层只有一层
在这里插入图片描述

【书中】
在这里插入图片描述

衡量预估质量

1/2是为了求导时把2消去
在这里插入图片描述

线性回归(求最优解)

一般的模型都没有显示解,因为有显示解的模型都过于简单(显示解:个人感觉就是 能直接用数学方法手动解出来的解)
在这里插入图片描述

训练数据

当每个xi是一个列向量样本时, X即一个大矩阵,该矩阵每一行对应一个样本
y是一个列向量,每个yi是一个实数数值,对应预测的房价
在这里插入图片描述

参数学习、显示解

损失函数l:模型在每一个数据上的损失 求均值就得到损失函数
目标是求 最小的损失函数

这里X是一个矩阵,x_{i}的意思是第i条数据,每一条数据都包含了(房间个数,居住面积)等决策信息
argmin是指让后面公式取得最小值的参数大小, min是指公式本身的最小值.
在这里插入图片描述

因为线性模型,因此有显示解。下面求:

为了写起来方便,将偏差b也写进来,
在这里插入图片描述
此时为了能进行矩阵计算X·W,为 矩阵X加入一列全一的特征(增广矩阵?)

最优解是 导数为0的,即
在这里插入图片描述
此处是唯一一个有最优解的模型,以后学的都不会有了
具体计算过程:
在这里插入图片描述

优化算法(初步体验)

后面有专门的章节将优化方法

在这里插入图片描述
在这里插入图片描述

梯度下降法(含超参数:学习率)

【实际场景】很少直接使用梯度下降,一般都用小批量随机梯度下降
当一个模型没有显示解时,我们会:

下图画的是等高线
梯度是使其增加最快的方向,负梯度就是下降最快的方向

学习率:此处的yita,是超参数,是需要人为指定的(超参数不需要数据来驱动,而是在训练前或者训练中人为的进行调整的参数)
在这里插入图片描述
以w0到w1为例:yita相当于每一步走多远(即w0到w1),偏导数(即梯度)相当于 确定向哪个方向走(沿负梯度方向就是沿下降最快的方向)
上图中橙框乘红框就相当于 w0到w1、w1到w2的每段向量, 则上述等式相当于 起点+ yita乘梯度(即 要运动的向量)=最终的向量
在这里插入图片描述
选太小:每次走的步长有限,需要计算很多次梯度,那么 时间和空间成本都太大
后续有教程教选学习率

【常用】小批量随机梯度下降法(Stochastic Gradient Descent)(含超参数:批量大小batch)

每次走一步都计算所有的梯度成本太大。

在这里插入图片描述
在这里插入图片描述

代码实现

线性回归(从0实现,不用框架)

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

生成数据集

标准差:standard deviation
torch.normal() 返回一个张量,包含从给定参数means,std的离散正态分布中抽取随机数。 均值means是一个张量,包含每个输出元素相关的正态分布的均值
torch.matmul:两个张量矩阵相乘
reshape中-1表示自动计算,1表示固定,即列向量为1

弹幕说:
这个函数返回的特征与标签,相当于分别把真实的房屋‘关键因素’和对应的‘房价’列出来。这一页的信息,相当于去市场调研收集真实的房屋数据。
features中每一行都包含一个二维数据样本,labels中的每一行都包含一维标签值(一个标签)。
在这里插入图片描述

绘制数据集

此处打印看一下 第0个样本的样子 以及 可视化一下所有样本

使用.detach()方法可以将一个张量从当前的计算图中分离出来,使其变成一个不再需要梯度追踪的普通张量,即使它是由需要梯度的操作创建的

从图中也看出 横纵轴变量是有线性相关性的
在这里插入图片描述

读取小批量

定义一个data_iter函数,接收批量大小、特征矩阵、标签向量作为输入,生成大小为batch_size的小批量

yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后开始。

%matplotlib inline
import random
import torch
from d2l import torch as d2ldef synthetic_data(w,b,num_exaples):"""生成 y = Xw + b + 噪声"""X = torch.normal(0,1,(num_exaples,len(w)))y = torch.matmul(X,w) + by += torch.normal(0,0.01,y.shape)return X, y.reshape((-1,1))true_w = torch.tensor([2,-3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)
print('features:',features[0],'\nlabel:',labels[0])d2l.set_figsize()
d2l.plt.scatter(features[:,(1)].detach().numpy(),labels.detach().numpy(),1)   # data_iter:把所有样本分成很多个batch,每个batch中的样本数量为batch_size(函数接收批量大小、特征矩阵和标签向量作为输入,生成大小为batch_size的小批量)
def data_iter(batch_size,features,labels):num_examples = len(features)  # 样本个数indices = list(range(num_examples)) # 样本索引(从0- num_examples-1)# 这些样本是随即读取的,没有特定的顺序random.shuffle(indices) # 把索引随机打乱for i in range(0, num_examples, batch_size): # 遍历所有样本,每次步长为batch_size# 每batch_size个样本为一组,拿到该组样本的索引。注:当i+batch_size超出时,取num_examples         # batch_indices = torch.tensor(indices[i:min(i+batch_size,num_examples)]) batch_indices = indices[i:min(i+batch_size,num_examples)] # 这么写也行,只是为了拿到索引嘛, 索引用不用tensor感觉均可yield features[batch_indices], labels[batch_indices] # 基于样本索引获得对应的特征,及对应的标签batch_size = 10
for X,y in data_iter(batch_size, features, labels):print(X, '\n', y) # 取一个批次后,就break跳出了break

在这里插入图片描述

定义模型、损失函数、优化算法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

说明:
1.关于 l.sum().backward():
在这里插入图片描述

%matplotlib inline
import random
import torch
from d2l import torch as d2ldef synthetic_data(w,b,num_exaples):"""生成 y = Xw + b + 噪声"""X = torch.normal(0,1,(num_exaples,len(w)))y = torch.matmul(X,w) + by += torch.normal(0,0.01,y.shape)return X, y.reshape((-1,1))true_w = torch.tensor([2,-3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)
print('features:',features[0],'\nlabel:',labels[0])d2l.set_figsize()
d2l.plt.scatter(features[:,(1)].detach().numpy(),labels.detach().numpy(),1)   def data_iter(batch_size,features,labels):num_examples = len(features)  # 样本个数indices = list(range(num_examples)) # 样本索引# 这些样本是随即读取的,没有特定的顺序random.shuffle(indices) # 把索引随即打乱for i in range(0, num_examples, batch_size):batch_indices = torch.tensor(indices[i:min(i+batch_size,num_examples)]) # 当i+batch_size超出时,取num_examples         yield features[batch_indices], labels[batch_indices] # 获得随即顺序的特征,及对应的标签batch_size = 10
for X,y in data_iter(batch_size, features, labels):print(X, '\n', y) # 取一个批次后,就break跳出了break# 定义初始化模型参数
w = torch.normal(0,0.01,size=(2,1),requires_grad=True)  # 初始化w:w是长为2的向量,均值为0,标准差为0.01
b = torch.zeros(1,requires_grad=True)# 定义模型
def linreg(X,w,b):"""线性回归模型"""return torch.matmul(X,w)+b# 定义损失函数
def squared_loss(y_hat,y):"""均方损失"""return (y_hat - y.reshape(y_hat.shape))**2/2 # 将y统一成与y_hat一样的尺寸   # 定义优化算法
def sgd(params,lr,batch_size):   # params:参数list,如[w、b]"""小批量随即梯度下降"""with torch.no_grad(): # 设置不更新梯度for param in params: # 每个参数进行遍历# 每个参数进行更新:因为之前的损失函数没有求均值,所以这里除以 batch_size 求了均值。由于乘法的线性关系,这里除以放在loss的除以是等价的。 param -= lr * param.grad / batch_size                param.grad.zero_() # 每个参数的梯度清零(以避免影响下次梯度计算)# 训练过程
lr = 0.03
num_epochs = 3
net = linreg # 这里用线性模型,这样写是很方便net赋予其他模型,只需要改一处,不需要下面所有网络模型名称都改
loss = squared_loss# 训练过程(都是套路,大同小异,两次for loop)
for epoch in range(num_epochs):  # 第一层for:对数据扫一遍for X,y in data_iter(batch_size,features,labels): # 第二层for:每次拿出batch_size大小的一个batchl = loss(net(X,w,b),y) # x和y的小批量损失: 输入参数给模型net得到预测值;用预测值和真实值y做损失。此时损失l就是长度为batch_size的向量# 因为l是形状是(batch_size,1),而不是一个标量。l中所有元素被加到一起,并以此计算关于[w,b]的梯度l.sum().backward() # 求和算梯度不懂什么意思的可以回看上一节自动求导,求和后算梯度是求每一个y对每一个x的梯度,不求和直接算梯度结果是一个矩阵!不是我们要的结果sgd([w,b],lr,batch_size) #使用参数的梯度更新参数(此处可能存在细节问题,但只是为了说明整体上的训练过程,因为 最后一个batch可能样本数量不足batch_size个)# 扫完一个epoch后,评价一下(这部分无需更新梯度)with torch.no_grad():train_l = loss(net(features,w,b),labels)print(f'epoch{epoch+1},loss{float(train_l.mean()):f}')   # 比较真实参数和通过训练学到的参数来评估训练的成功程度
print(f'w的估计误差:{true_w-w.reshape(true_w.shape)}')
print(f'b的估计误差:{true_b-b}')

打印结果:
在这里插入图片描述

体验lr太大或太小时的效果:(注意 改变lr时要 重新初始化一下w和b)
当lr很小时
在这里插入图片描述
此时可以考虑增加epoch,但loss还不是特别小
在这里插入图片描述
lr太大时,loss为nan,因为可能 求导时会除以0,超出傅里叶的计算范围了
在这里插入图片描述

线性回归(使用框架)

python中的* (拆包、解包):在Python中,号表示解包操作,它可以将一个包含多个元素的元组、列表、集合等数据结构解压为多个独立的元素。 表示接受任意多个参数并将其放在一个元组中
在这里插入图片描述
在这里插入图片描述
下图中 左侧为本节图片,等价于右图(即上节手动实现的方式)
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import numpy as np
import torch
from torch.utils import data
from d2l import torch as d2l
from torch import nn    
# 0.基本数据准备    
true_w = torch.tensor([2,-3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w,true_b,1000) # 库函数生成人工数据集    # 1.【与不用框架实现的区别之一】调用框架现有的API来读取数据(把已有的训练数据(features,labels)传入TensorDataset)
def load_array(data_arrays,batch_size,is_train=True):"""构造一个Pytorch数据迭代器"""dataset = data.TensorDataset(*data_arrays) # dataset相当于Pytorch的Dataset。一个星号*,表示对list解开入参(是python中的拆包符号)。      return data.DataLoader(dataset,batch_size,shuffle=is_train) # 返回的是从dataset中随机挑选出batch_size个样本出来     batch_size = 10
data_iter = load_array((features,labels),batch_size) # 返回的数据的迭代器
print(next(iter(data_iter))) # iter(data_iter) 是一个迭代器对象,next是取迭代器里面的元素  # 2.使用框架的预定义好的层
# nn是神经网络的缩写
net = nn.Sequential(nn.Linear(2,1))# 3.初始化模型参数
# 以单下划线_结尾的方法都是原位替换
net[0].weight.data.normal_(0,0.01) # 使用正态分布替换掉weight变量里面的数据值。 其中net[0]就是 神经网络net的第一层(即 nn.Linear(2,1))。
net[0].bias.data.fill_(0)  # 偏差bias变量里面的值设置为0。normal_ :以单下划线_结尾的方法都是原位替换
print(net[0])# 4.计算均方误差使用的是MSELoss类,也称为平方L2范数
loss = nn.MSELoss()  #L1是算术差,L2是平方差# 4.实例化SGD实例
trainer = torch.optim.SGD(net.parameters(),lr=0.03)  # 传入网络中所有的参数(此处指w和b)# 5.训练过程代码与从零开始时所做的非常相似
num_epochs = 3
for epoch in range(num_epochs):for X, y in data_iter:  # 从DataLoader里面一次一次把所有数据拿出来
#         print("X:",X)
#         print("y:",y)l = loss(net(X),y) # net(X) 为计算出来的线性回归的预测值trainer.zero_grad() # 梯度清零(避免影响其他次计算)l.backward()  # pytorch已经帮我们做了 向量.sum()  (即转成了标量),无需手动写了(如上节的l.sum().backward())trainer.step()  # SGD优化器优化模型:调用step()进行模型更新l = loss(net(features),labels)  # 当前epoch的lossprint(f'epoch{epoch+1},loss{l:f}')   # 这行都是l 而不是1

打印结果:
在这里插入图片描述

QA

在这里插入图片描述

1.可以,直接 上面pip就行

2.后面会讲一下二者区别,但是区别不大。
绝对差值在0点时可能不能求导。

3.也可以不求。求不求本质上没区别,不求平均 梯度数值会比较大。如果损失不除以n,那么学习率 除以n也行, 但是 只不过除了之后 更好调(除n主要就是用来忽略样本规模的)

  1. 是的

在这里插入图片描述

6.除以谁都没关系,不影响 本质, 最后求的都是min Loss

7.经验。后续也会讲

8.其实batch_size越小越好,对收敛越好但是大了不行。
采样样本越小,噪音越大,但是噪音对于神经网络是好事情, 更利用训练出 泛化性强的网络

在这里插入图片描述

9.batch_size只要不是特别特别大都行

10.是的。 梯度是线性的, 和的均值等于均值的和

在这里插入图片描述

11.不是。批量大小是一样的即batch_size,随机只每次在样本中 随机采集batch_size大小个元素

12.需要。 但是一般损失函数和正则会分开, 而且正则有很多方法。

13.首先二阶导数不一定能计算,很难算。 有时一阶导是向量,二阶导就变成了矩阵
为什么不用牛顿法:
【二阶导不一定能计算,或者方便计算】此处有两个问题,一个是统计模型(损失函数长什么样),一个是优化模型(用什么算法求解),但其实这俩都是错的, 因为 统计模型是错的,优化模型肯定也求不对, 应该是指我们很难找到 完全正确、十分精准的损失函数,一般机器学习都求不到最优解(面对实际的问题我们不可能拿到精确的模型,真实的损失函数是非常复杂的)。
因此求出一个统计模型的最优解的意义并不大, 因为它是一个错误的模型,因此收敛快不快并不care,我们关心损失函数收敛到那个地方,用牛顿法虽然快,但 求的结果可能并不平坦。 不一定 很快得到的结果就是好的结果(可能泛化性差)
【牛顿法求出的结果不一定比随机梯度求得的结果好,收敛不一定快, 即便收敛快、结果也不一定好】
弹幕说:收敛更准确比更快更重要

在这里插入图片描述

14.如果损失函数L中没除以n,那么 学习率yita除以n
在这里插入图片描述

15.从计算图分离:要转换成numpy数据类型,就需要先将其从求梯度的计算图中分离出来(但是具体也看pytorch版本)
16.detach就是pytorch中的
17.是的,如果数据量特别大会爆掉。 但是整本书中dataset都不大, 如果真实情况下 GPU足够大,load全部也没问题。
实际场景下,数据都存储在硬盘上的

18.弹幕说也可以
在这里插入图片描述

19.相当于洗牌之后再把所有的牌抽起来看一遍
20.不用return时,每次需要数据时run一遍即可,现用现生成,节省内存;
用iter就是python的写法,python的习惯

21、22.三种做法:(代码中只是刚好整除了)
(1)【常用】代码中:每次取的范围是: [ i , min(i+batch_size,num_examples)]
(2)丢掉最后不足的样本
(3)从下一个epoch中补一些过来 使最后一个batch也满足 batch_size个样本数

在这里插入图片描述
24.lr不做衰减也问题不大,此处先不讲这个
24-2.
(1)可以判断相邻两次epoch的loss的变化范围不大(如1%时)
(2)用 交叉验证集,当其精度不增加时
(3)算力允许的情况下,epoch多点也没关系

25.是的。除了线性回归模型外,都没有显示解。能求出显示解的模型都太简单了

NPC(np-complete)问题即NP完全问题, 任何一个NP问题都可以在多项式时间内归约为某个NP问题,那么这个问题就成为NPC问题
【NP问题】
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

26.初始时也可以用同样的值,偷懒就用了随机的
27.求导时会涉及除法,后面也会讲数据稳定性问题
28.不一定, 只是此处手动设了,后续就不会了
29.是的
30.就是为了print,同时我们只run了forward,没run backward,即没计算梯度,无需清0
31.因为pytorch不自动帮你清零,如果 不人为清零,则 后面梯度计算时会在前面的梯度计算的结果上 累加
在这里插入图片描述
32.后面会单独讲

09-softmax回归+损失函数+图片分类数据集

Softmax回归(具体细节也可看吴恩达)

【softmax算子(操作子)的作用】将所有的输入都 拉到[0,1]区间内,且令这些输入 经由softmax的输出 之和为1(刚好符合概率的感觉)
在这里插入图片描述

在这里插入图片描述

回归vs分类

在这里插入图片描述
下图补充:
回归:
输出的区间是 单个自然区间

分类:
多输出,输出的个数等于类别的个数
在这里插入图片描述

【分类问题举例】Kaggle上的分类问题

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

从回归到多类分类

如何从回归问题过渡到分类问题:

【编码和初步计算】均方损失

1.编码
如果有n个类别,则 构造一个 长度为n的向量y。(one-hot编码)
如果该东西真实类别是i,则yi=1,其他yi=0

下图中yhat 是 使得oi取最大值对应的那个类别标号i。
oi:中o为置信度,o是神经网络的输出
y是真实值,yhat是预测值
在这里插入图片描述

【分析】无校验比例

【我们关心的问题1】对于分类问题,我们不关心 物体实际的值,而是 关心 分类正确物体的置信度是不是特别大

下图中yhat 是 使得oi取最大值对应的那个类别标号i
在这里插入图片描述
我们目的是 要使得对正确类别y的置信度 oy能远远大于 其他类别的置信度oi, 即 二者的差大于等于一个阈值(如 derta)
这样能保证我们的模型能够将 物体真正的类别和其他类别拉开距离

【softmax定义】【基于指数运算进行映射】校验比例(看书效果更好)

【我们关心的问题2】
同时接问题1,我们还希望 分类的预测输出是一个概率,暂时现在我们的输出是一个向量( o1,…,on)
此时我们引入一个操作子 softmax,作用于o,得到yhat,它是一个长度为n的向量(y1hat,…,ynhat),该向量的每个元素yi都非负、且这些元素之和为1(每个元素就是 该物体被预测为当前索引类别的概率)
其中yhati
【个人总结softmax作用】【使用exp(即指数)、exp(oi)/xigema exp(ok) 的目的】
(1)通俗版本:将所有的输入都 拉到[0,1]区间内,且令这些输入 经由softmax的输出 之和为1(刚好符合概率的感觉)
(2)将 每个元素都映射到非负区间上(这才符合概率)且 最后的yhat i更符合概率的特点, 值属于[0,1]且 之和为1
(因为真实的向量y也是 所有元素之和为1,即只有一个1, 也可以将其视为概率)

【书上soffmax作用】softmax函数能够将未规范化的预测变换为⾮负数(范围在 0-1)并且总和为1,同时让模型保持可导的性质
【为什么不能直接将oi作为输出】
我们能否将未规范化的预测o直接视作我们感兴趣的输出呢?答案是否定的。因为将线性层的输出直接
视为概率时存在⼀些问题:⼀⽅⾯,我们没有限制这些输出数字的总和为1。另⼀⽅⾯,根据输⼊的不同,它
们可以为负值。
在这里插入图片描述
【o与y的关系(这也就是softmax的 主要计算原理)】
在这里插入图片描述

下图中的softmax的输入O是一个(行)向量
在这里插入图片描述
下图中softmax的输入是一个矩阵(可见softmax从0实现一节)
在这里插入图片描述

Softmax和交叉熵(Cross Entropy)损失

p和q是两个概率,H表示交叉熵,i为第i个元素,共n个元素
向量y(即加粗的黑体y)是真实值的向量(共n个元素, 只有一个元素为1,其余为0),向量yhat是预测得到的向量,
标量y是 物体真实类别,标量yhati是物体被预测为 i类别的概率

解释下图第一个公式的推导(如绿框):由于y是⼀个⻓度为n的独热编码向量,所以除了⼀个项以外的所有项j都消失了。
yhaty:对真实类别y的预测的概率 为yhat。 即 对于分类问题,我们只关心对正确类别的预测值有多大,而不关心对于非正确类别的预测情况
在这里插入图片描述

上图中第三个公式的推导
在这里插入图片描述

损失函数

【作用】用于衡量真实值和预测值之间的区别
在这里插入图片描述
下面:
y:真实值
y’:预测值
除以2:求导后 2和1/2抵消

L2 loss

横轴是y’
在这里插入图片描述

在这里插入图片描述
④ 【变化规律】当预测值y’跟真实值y隔的比较远的时候,(真实值y为0,预测值就是下面的曲线里的x轴),梯度比较大,所以参数更新比较多。

⑤ 随着预测值靠近真实值是,梯度越来越小,参数的更新越来越小。
在这里插入图片描述
下图中的更新指参数权重的更新
在这里插入图片描述

L1 loss

L2也不一定很好,因为 当y‘离原点很远时(此例中取真实值y=0),也不一定希望更新的很快,因此看下L1
在这里插入图片描述
① 相对L2 loss,L1 loss的梯度就是距离原点时,梯度也不是特别大,权重的更新也不是特别大。会带来很多稳定性的好处。

② 他的缺点是在零点处不可导,并在零点处左右有±1的变化,这个不平滑性导致预测值与真实值靠的比较近的时候,优化到末期的时候,可能会不那么稳定。
在这里插入图片描述

Huber’s Robust Loss(鲁棒损失)

Huber’s Robust Loss 结合了L1和L2 loss的优点:
当预测值和真实值的差距不同时,Loss计算方式不同:即 预测值和真实值差的比较大时,梯度通过比较均匀的力度调整参数;预测值和真实值差的比较小时(即优化末期),梯度绝对值越来越小,以保证 整个参数调整过程是比较平滑的
在这里插入图片描述

在这里插入图片描述

图像分类数据集(Fashion-MNIST)

0.概述和课件

此处是先初步介绍一下后面要常用到的一个数据集Fashion-MNIST

① MINIST数据集是图像分类中广泛使用的数据集之一,但作为基准数据集过于简单。
② 下面将使用类似但更复杂的Fashion-MNIST数据集。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

【代码】

1.导入包

在这里插入图片描述

2.准备数据

在这里插入图片描述

3.单进程读取batch并可视化的函数

在这里插入图片描述

在这里插入图片描述

4.多进程读取一个小batch,大小为batch_size

一般要保证读取数据的速度大于训练的速度

%matplotlib inline
import torch
import torchvision
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2ld2l.use_svg_display()# 通过ToTensor实例将图像数据从PIL类型变换成32位浮点数格式
# 并除以255使得所有像素的数值均在0到1之间
trans = transforms.ToTensor()
mnist_train = torchvision.datasets.FashionMNIST(root="01_data/01_DataSet_FashionMNIST",train=True,transform=trans,download=True)
mnist_test = torchvision.datasets.FashionMNIST(root="01_data/01_DataSet_FashionMNIST",train=False,transform=trans,download=True)            def get_fashion_mnist_labels(labels):"""返回Fashion-MNIST数据集的文本标签"""text_labels = ['t-shirt','trouser','pullover','dress','coat','sandal','shirt','sneaker','bag','ankle boot']return [text_labels[int(i)] for i in labels]def show_images(imgs, num_rows, num_cols, titles=None, scale=1.5):"""Plot a list of images."""figsize = (num_cols * scale, num_rows * scale) # 传进来的图像尺寸,scale 为放缩比例因子_, axes = d2l.plt.subplots(num_rows,num_cols,figsize=figsize)print(_)print(axes) # axes 为构建的两行九列的画布axes = axes.flatten()print(axes) # axes 变成一维数据for i,(ax,img) in enumerate(zip(axes,imgs)):if torch.is_tensor(img):# 图片张量ax.imshow(img.numpy())ax.set_title(titles[i])else:# PIL图片ax.imshow(img)X, y = next(iter(data.DataLoader(mnist_train,batch_size=18))) # X,y 为仅抽取一次的18个样本的图片、以及对应的标签值
show_images(X.reshape(18,28,28),2,9,titles=get_fashion_mnist_labels(y))batch_size = 256
def get_dataloader_workers(): # 一般数据都在硬盘上,不能一次读取完,此时使用4个进程来读"""使用4个进程来读取的数据"""return 4train_iter = data.DataLoader(mnist_train, batch_size, shuffle=True,num_workers=get_dataloader_workers())timer = d2l.Timer() # 计时器对象实例化,开始计时
for X,y in train_iter:  # 遍历一个batch_size数据的时间continue
f'{timer.stop():.2f}sec' # 计时器停止时,停止与开始的时间间隔事件

在这里插入图片描述

5.【完整代码】整合-上述内容到一个函数中(load_data_fashion_mnist)

本节整合代码并实现函数load_data_fashion_mnist 以供后面使用 Fashion-MNIST数据集
额外声明resize参数,以便后续 如果模型需要不同size的图片时可以 基于此调整
在这里插入图片描述

%matplotlib inline
import torch
import torchvision
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2ld2l.use_svg_display()# 通过ToTensor实例将图像数据从PIL类型变换成32位浮点数格式
# 并除以255使得所有像素的数值均在0到1之间
trans = transforms.ToTensor()
mnist_train = torchvision.datasets.FashionMNIST(root="01_data/01_DataSet_FashionMNIST",train=True,transform=trans,download=True)
mnist_test = torchvision.datasets.FashionMNIST(root="01_data/01_DataSet_FashionMNIST",train=False,transform=trans,download=True)            def get_fashion_mnist_labels(labels):"""返回Fashion-MNIST数据集的文本标签"""text_labels = ['t-shirt','trouser','pullover','dress','coat','sandal','shirt','sneaker','bag','ankle boot']return [text_labels[int(i)] for i in labels]def show_images(imgs, num_rows, num_cols, titles=None, scale=1.5):"""Plot a list of images."""figsize = (num_cols * scale, num_rows * scale) # 传进来的图像尺寸,scale 为放缩比例因子_, axes = d2l.plt.subplots(num_rows,num_cols,figsize=figsize)print(_)print(axes) # axes 为构建的两行九列的画布axes = axes.flatten()print(axes) # axes 变成一维数据for i,(ax,img) in enumerate(zip(axes,imgs)):if torch.is_tensor(img):# 图片张量ax.imshow(img.numpy())ax.set_title(titles[i])else:# PIL图片ax.imshow(img)X, y = next(iter(data.DataLoader(mnist_train,batch_size=18))) # X,y 为仅抽取一次的18个样本的图片、以及对应的标签值
show_images(X.reshape(18,28,28),2,9,titles=get_fashion_mnist_labels(y))batch_size = 256
def get_dataloader_workers():"""使用4个进程来读取的数据"""return 4train_iter = data.DataLoader(mnist_train, batch_size, shuffle=True,num_workers=get_dataloader_workers())timer = d2l.Timer()
for X,y in train_iter:continue
f'{timer.stop():.2f}sec'  # 扫一边数据集的事件def load_data_fashion_mnist(batch_size, resize=None): # 额外声明resize参数,以便后续 如果模型需要不同size的图片时可以 基于此调整"""下载Fashion-MNIST数据集,然后将其加载到内存中"""trans = [transforms.ToTensor()]if resize:trans.insert(0,transforms.Resize(resize)) # 如果有Resize参数传进来,就进行resize操作trans = transforms.Compose(trans)mnist_train = torchvision.datasets.FashionMNIST(root="01_data/01_DataSet_FashionMNIST",train=True,transform=trans,download=True)mnist_test = torchvision.datasets.FashionMNIST(root="01_data/01_DataSet_FashionMNIST",train=False,transform=trans,download=True)            return (data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_workers()),data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_workers()))               

Softmax-从零实现

1.训练集、测试集抽取

基于上节实现的函数读取数据集的数据
在这里插入图片描述

2.初始化参数w、b

因为对于softmax回归来说,input需要是一个向量,因此 784=28*28,将图片展平(但这样会丢失图片的空间信息,后续用卷积神经网络来实现)

在这里插入图片描述
size是关键:个人理解
X是的shape是(1,784),为了XW能计算,且输出为10类,则 W.shape为(784,10)
在这里插入图片描述

3.定义Softmax

回顾一下:矩阵可以多不同axis上求和
在这里插入图片描述
正文:
此处softmax的对象是一个矩阵,对矩阵做softmax就相当于对其每一行做softmax

分别计算公式中的分子和分母
在这里插入图片描述

验证一下上面写的是否正确:符合softmax的预期:每个元素都为非负且 在0,1之间,每一行所有元素之和也为1
在这里插入图片描述
W.shape为(784,10) (第一步就分析了)
在这里插入图片描述

在这里插入图片描述

4.交叉熵损失

先补充个细节:如何 从所有预测值中根据 标号(即类别label)拿到其对应的预测值(即 最终预测的概率)
(弹幕说)此处内容涉及python的高级索引
在这里插入图片描述
最终拿到的是yhat[0,0], [1,2]
在这里插入图片描述
正文:
上面说明的内容就是为了 实现 获取下图中的 yhaty:即 预测结果中 某东西的真实类别(即老师口中的标号)的预测值
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.计算预测正确的数量

因为是分类问题,将预测类别与真实y元素进行比较。

【过程总结】
1.找出yhat中每行(每行代表 对一个样本类别的 属于各个类别的概率预测值)中 预测值最大的元素对应的索引,即 预测该样本的类别;
2.将yhat与y中每个元素逐个比较并 将 每个元素的比较结果保存到cmp中;其中cmp中每个元素都是布尔类型
3.将 cmp转换为y中元素的数据类型(即 int)并求和,得到了 所有预测类别正确的样本的数量
4. 预测正确样本数/总样本数 =准确率
在这里插入图片描述
在这里插入图片描述

【补充】变量1.type(变量2):将 变量1的类型转换为变量2的类型
在这里插入图片描述
【补充2】QA中的问题:为什么不在accuracy中 直接除以len(y)

因为我们读取batch时 最后一个batch中样本数量可能不足 batch_size,
那么此时 accuracy/len(y) 是不对的
在这里插入图片描述

6.任意模型的准确率(或称精度)

evaluate_accuracy(net,data_iter)作用:基于给定模型net和数据迭代器data_iter,可以计算该模型在该数据迭代器上的精度
Accumulator类的作用:该类可生成一个累加迭代器
在这里插入图片描述
弹幕说:如报Runtime的错误,把自己的Batchsize和进程数改小就可以了,毕竟cpu太拉

%matplotlib inline
import torch
import torchvision
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2ldef get_dataloader_workers():"""使用4个进程来读取的数据"""return 4def load_data_fashion_mnist(batch_size, resize=None):"""下载Fashion-MNIST数据集,然后将其加载到内存中"""trans = [transforms.ToTensor()]if resize:trans.insert(0,transforms.Resize(resize)) # 如果有Resize参数传进来,就进行resize操作trans = transforms.Compose(trans)mnist_train = torchvision.datasets.FashionMNIST(root="01_data/01_DataSet_FashionMNIST",train=True,transform=trans,download=True)mnist_test = torchvision.datasets.FashionMNIST(root="01_data/01_DataSet_FashionMNIST",train=False,transform=trans,download=True)            return (data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_workers()),data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_workers()))               batch_size = 256
train_iter, test_iter = load_data_fashion_mnist(batch_size) # 返回训练集、测试集的迭代器     num_inputs = 784
num_outputs = 10
w = torch.normal(0,0.01,size=(num_inputs,num_outputs),requires_grad=True)
b = torch.zeros(num_outputs,requires_grad=True)def softmax(X):X_exp = torch.exp(X) # 每个都进行指数运算partition = X_exp.sum(1,keepdim=True) return X_exp / partition # 这里应用了广播机制# 实现softmax回归模型
def net(X):return softmax(torch.matmul(X.reshape((-1,w.shape[0])),w)+b) # -1为默认的批量大小,表示有多少个图片,每个图片用一维的784列个元素表示      def cross_entropy(y_hat, y):return -torch.log(y_hat[range(len(y_hat)),y]) # y_hat[range(len(y_hat)),y]为把y的标号列表对应的值拿出来。传入的y要是最大概率的标号      def accuracy(y_hat,y):"""计算预测正确的数量"""if len(y_hat.shape) > 1 and y_hat.shape[1] > 1: # y_hat.shape[1]>1表示不止一个类别,每个类别有各自的概率   y_hat = y_hat.argmax(axis=1) # y_hat.argmax(axis=1)为求行最大值的索引cmp = y_hat.type(y.dtype) == y # 先判断逻辑运算符==,再赋值给cmp,cmp为布尔类型的数据return float(cmp.type(y.dtype).sum()) # 获得y.dtype的类型作为传入参数,将cmp的类型转为y的类型(int型),然后再求和       # 【基于给定模型net和数据迭代器data_iter,可以计算该模型在该数据迭代器上的精度】可以评估在任意模型net的准确率
def evaluate_accuracy(net,data_iter):  # 当传入一个模型net和数据迭代器data_iter"""计算在指定数据集上模型的精度"""#如果net模型是torch.nn.Module实现的神经网络的话,将它变成评估模式(评估模式下不计算梯度,即只做forward不做backward)if isinstance(net,torch.nn.Module):      net.eval()  # 将模型设置为评估模式metric = Accumulator(2) # 正确预测数、预测总数,metric为累加器的实例化对象,里面存了两个数for X, y in data_iter:  # 对于迭代器中每次拿到的一个batch中的X和ymetric.add(accuracy(net(X),y),y.numel()) # net(X)将X输入模型,获得预测值。y.numel()为y中元素总个数return metric[0] / metric[1] # 分类正确的样本数 / 总样本数# 【该类可生成一个累加迭代器】Accumulator实例中创建了2个变量,用于分别存储正确预测的数量和预测的总数量
class Accumulator:"""在n个变量上累加"""def __init__(self,n):self.data = [0,0] * ndef add(self, *args):self.data = [a+float(b) for a,b in zip(self.data,args)] # zip函数把两个列表第一个位置元素打包、第二个位置元素打包....def reset(self):self.data = [0.0] * len(self.data)def __getitem__(self,idx):return self.data[idx]print(evaluate_accuracy(net, test_iter))   # 看一下随机出来的模型和测试迭代器 的效果(因为共10个类别,因此正确率应在10%左右)

在这里插入图片描述

【补充】pytorch中的tensor.numel()方法
在这里插入图片描述

7.训练函数

train_epoch_ch3:对整个数据集数据迭代一次(即一个epoch)的实现方式
在这里插入图片描述
在这里插入图片描述

8.动画绘制

自定义一个小动画,可视化训练过程
在这里插入图片描述

9.多epoch总训练函数

ch3指在第三章的训练函数,后面会不断完善这个训练函数
metrics:指标
在这里插入图片描述
在这里插入图片描述

我们一般关注测试的精度test acc

在这里插入图片描述
可视化效果:
在这里插入图片描述

10.预测数据

从测试集中拿出6个样本预测一下
在这里插入图片描述
在这里插入图片描述

【完整代码】

个别局部部分的解释可以看具体对应章节的注释

##### %matplotlib inline
import torch
import torchvision
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2l
from IPython import displaydef get_dataloader_workers():"""使用4个进程来读取的数据"""return 0def load_data_fashion_mnist(batch_size, resize=None):"""下载Fashion-MNIST数据集,然后将其加载到内存中"""trans = [transforms.ToTensor()]if resize:trans.insert(0,transforms.Resize(resize)) # 如果有Resize参数传进来,就进行resize操作trans = transforms.Compose(trans)mnist_train = torchvision.datasets.FashionMNIST(root="01_data/01_DataSet_FashionMNIST",train=True,transform=trans,download=True)mnist_test = torchvision.datasets.FashionMNIST(root="01_data/01_DataSet_FashionMNIST",train=False,transform=trans,download=True)            return (data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_workers()),data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_workers()))               batch_size = 256
train_iter, test_iter = load_data_fashion_mnist(batch_size) # 返回训练集、测试集的迭代器     
# 2.
num_inputs = 784
num_outputs = 10
w = torch.normal(0,0.01,size=(num_inputs,num_outputs),requires_grad=True)  # 重点是size
b = torch.zeros(num_outputs,requires_grad=True)def softmax(X): # 此处softmax的对象是一个矩阵。对矩阵做softmax就相当于对其每一行做softmaxX_exp = torch.exp(X) # 每个元素都进行指数运算(即softmax公式中的分子)partition = X_exp.sum(1,keepdim=True)  # 按axis=1进行求和,并仍保持原维度(即二维矩阵)(即softmax公式中的分母)return X_exp / partition # 这里应用了广播机制(即softmax公式中的分子/分母)# 实现softmax回归模型
def net(X):return softmax(torch.matmul(X.reshape((-1,w.shape[0])),w)+b) # -1表示自动计算一下(为默认的批量大小),表示有多少个图片,每个图片用一维的784列个元素表示      def cross_entropy(y_hat, y):return -torch.log(y_hat[range(len(y_hat)),y]) # y_hat[range(len(y_hat)),y]为把y的标号列表对应的值拿出来。传入的y要是最大概率的标号      def accuracy(y_hat,y):"""计算预测正确的数量"""if len(y_hat.shape) > 1 and y_hat.shape[1] > 1: # y_hat.shape[1]>1表示不止一个类别,每个类别有各自的概率   y_hat = y_hat.argmax(axis=1) # y_hat.argmax(axis=1)为求行最大值的索引cmp = y_hat.type(y.dtype) == y # 先判断逻辑运算符==,再赋值给cmp,cmp为布尔类型的数据return float(cmp.type(y.dtype).sum()) # 获得y.dtype的类型作为传入参数,将cmp的类型转为y的类型(int型),然后再求和       # 可以评估在任意模型net的准确率
def evaluate_accuracy(net,data_iter):"""计算在指定数据集上模型的精度"""if isinstance(net,torch.nn.Module): # 如果net模型是torch.nn.Module实现的神经网络的话,将它变成评估模式     net.eval()  # 将模型设置为评估模式metric = Accumulator(2) # 正确预测数、预测总数,metric为累加器的实例化对象,里面存了两个数for X, y in data_iter:metric.add(accuracy(net(X),y),y.numel()) # net(X)将X输入模型,获得预测值。y.numel()为样本总数return metric[0] / metric[1] # 分类正确的样本数 / 总样本数# Accumulator实例中创建了2个变量,用于分别存储正确预测的数量和预测的总数量
class Accumulator:"""在n个变量上累加"""def __init__(self,n):self.data = [0,0] * ndef add(self, *args):self.data = [a+float(b) for a,b in zip(self.data,args)] # zip函数把两个列表第一个位置元素打包、第二个位置元素打包....def reset(self):self.data = [0.0] * len(self.data)def __getitem__(self,idx):return self.data[idx]# 训练函数
def train_epoch_ch3(net, train_iter, loss, updater):if isinstance(net, torch.nn.Module):net.train() # 开启训练模式metric = Accumulator(3)for X, y in train_iter:y_hat = net(X)l = loss(y_hat,y) # 计算损失if isinstance(updater, torch.optim.Optimizer): # 如果updater是pytorch的优化器的话updater.zero_grad()l.mean().backward()  # 这里对loss取了平均值出来updater.step()metric.add(float(l)*len(y),accuracy(y_hat,y),y.size().numel()) # 总的训练损失、样本正确数、样本总数   else:l.sum().backward()updater(X.shape[0])metric.add(float(l.sum()),accuracy(y_hat,y),y.numel()) return metric[0] / metric[2], metric[1] / metric[2] # 所有loss累加除以样本总数,总的正确个数除以样本总数  class Animator:def __init__(self, xlabel=None, ylabel=None, legend=None, xlim=None,ylim=None, xscale='linear',yscale='linear',fmts=('-','m--','g-.','r:'),nrows=1,ncols=1,figsize=(3.5,2.5)): if legend is None:legend = []d2l.use_svg_display()self.fig, self.axes = d2l.plt.subplots(nrows,ncols,figsize=figsize)if nrows * ncols == 1:self.axes = [self.axes,]self.config_axes = lambda: d2l.set_axes(self.axes[0],xlabel,ylabel,xlim,ylim,xscale,yscale,legend)         self.X, self.Y, self.fmts = None, None, fmtsdef add(self, x, y):if not hasattr(y, "__len__"):y = [y]n = len(y)if not hasattr(x, "__len__"):x = [x] * nif not self.X:self.X = [[] for _ in range(n)] if not self.Y:self.Y = [[] for _ in range(n)]for i, (a,b) in enumerate(zip(x,y)):if a is not None and b is not None:self.X[i].append(a)self.Y[i].append(b)self.axes[0].cla()for x, y, fmt in zip(self.X, self.Y, self.fmts):self.axes[0].plot(x, y, fmt)self.config_axes()display.display(self.fig)display.clear_output(wait=True)# 总训练函数        
def train_ch3(net,train_iter,test_iter,loss,num_epochs,updater):animator = Animator(xlabel='epoch',xlim=[1,num_epochs],ylim=[0.3,0.9],       legend=['train loss','train acc','test acc'])  # 可视化函数(不细讲)for epoch in range(num_epochs):  # 变量num_epochs遍数据train_metrics = train_epoch_ch3(net,train_iter,loss,updater) # 训练过程相关指标:返回两个值,一个总损失、一个总正确率test_acc = evaluate_accuracy(net, test_iter) # 测试数据集上评估精度,仅返回一个值,总正确率  animator.add(epoch+1,train_metrics+(test_acc,)) # 可视化:train_metrics+(test_acc,) 仅将两个值的正确率相加,train_loss, train_acc = train_metrics# 【实现SGD】小批量随即梯度下降来优化模型的损失函数
lr = 0.1
def updater(batch_size):return d2l.sgd([w,b],lr,batch_size)num_epochs = 10
train_ch3(net,train_iter,test_iter,cross_entropy,num_epochs,updater)

预测数据:

def predict_ch3(net,test_iter,n=6):for X, y in test_iter: break # 仅拿出一批六个数据trues = d2l.get_fashion_mnist_labels(y)  # 真实labelpreds = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1))  # 预测labeltitles = [true + '\n' + pred for true, pred in zip(trues,preds)]d2l.show_images(X[0:n].reshape((n,28,28)),1,n,titles=titles[0:n])predict_ch3(net,test_iter)

Softmax-基于框架实现(nn.Module)

1.拿到数据和迭代器
在这里插入图片描述

2.构造softmax回归模型:

nn.Flatten():将任何维度的tensor转换为2Dtensor(即保留其第0维度,其他维度均展平为一个向量)

在这里插入图片描述
3.损失函数与优化算法
在这里插入图片描述

在这里插入图片描述

后面的课程会不断在该数据集上应用更深、更复杂的模型

import torch
from torch import nn
from d2l import torch as d2lbatch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)# Softmax回归的输出是一个全连接层
# PyTorch不会隐式地调整输入的形状
# 因此,我们定义了展平层(flatten)在线性层前调整网络输入的形状
net = nn.Sequential(nn.Flatten(),nn.Linear(784,10))def init_weights(m): # 该函数会对网络的每一层都 call一次,其中m就是当前的layerif type(m) == nn.Linear:nn.init.normal_(m.weight, std=0.01) # 如果当前层是线性层,就将其权重初始化为 均值为0、方差为0.01的随机值net.apply(init_weights)  # net网络权重初始化:应用init_weights函数到net网络的每一层
print(net.apply(init_weights)) # net网络的参数用的是init_weights初始化参数# 在交叉熵损失函数中传递未归一化的预测,并同时计算softmax及其对数
loss = nn.CrossEntropyLoss()
# 使用学习率为0.1的小批量随即梯度下降作为优化算法
trainer = torch.optim.SGD(net.parameters(),lr=0.1)num_epochs = 10
d2l.train_ch3(net,train_iter,test_iter,loss,num_epochs,trainer)

QA

在这里插入图片描述
1.softlabel是图像分类问题的实际场景中的一个常用技巧,大概意思就是 softmax理论上的效果在实际中可能不能完全实现?
刚刚讲的是 softmax+one-hot编码:将 n类 变成长度为n的向量,只有类别正确的那一类为1,其余均为0 ,然后用softmax去逼近这个 纯0、1的分布。
但其存在的问题是 (回想softmax公式)很难用 指数去逼近1, 即 要求输出几乎接近无穷大(分子)、分母的其他项都很小,这样 最后结果才是1,很难实现
在这里插入图片描述
因此提出了改进方案softlabel,将正确类记为0.9,错误类记为0.1(而不是像one-hot这样纯0、1),除以n? 这样就使得 用softmax去拟合 那些很小的数 是有可能实现的

2、3.逻辑回归就是 当类别n=2是的softmax回归

4.互信息不好算, 交叉熵就够用、好用了

5.也不是说我们不关注不正确的类,只是one-hot编码 将不正确的类的概率变为0了,所以计算时可以忽略掉不正确的类 。
如果是用softlabel,即类比one-hot用 0.9和0.1,那么计算时就不能忽略掉不正确的类了

在这里插入图片描述

6.会。但其实只要每个类都有足够多的样本时, 还是比较平衡的

7.每次走的步长取决于两点:梯度大小和lr,假设lr固定,那么步长只受梯度(如下图中橙色线)影响,因此对于下图,不管梯度是+1or-1,梯度的绝对值是一样的,因此每步移动的距离都是平均的
在这里插入图片描述
而下图则是,当 离原点较远时,梯度较大,因此每步步长就较大
在这里插入图片描述
8、9.似然函数属于统计学中的概念,因为深度学习后面的模型和统计没有太大关系,因此没有细讲这里
【最小化损失就等价于最大化似然函数】
似然函数简单理解:当给定一个模型(即 有了确定的权重)和数据,这个模型权重出现的概率有多大。因此我们要找到最大似然, 使得 这个权重更合理

在这里插入图片描述

10.前面讲过了(回想 权重更新公式即可 w1 = w0 - lr * 梯度)
11.可以用

在这里插入图片描述

13、14.是的。开多个python进程
课程中单独定义一个设置num_workers的原因是 老版本 中 windows不支持设置 多进程,因此需要在函数中判断一下是不是win系统,如果是就不用多进程
现在支持了,直接写死num也行,不用函数定义

15.有讲究,此处只是为了当前教学,后面会展开讲方差

在这里插入图片描述

17.不是。无论batch_size设为几,计算量不变。
只是说能不能想办法增加计算的并行度,以提高效率。
如果增大减小batch_size的没区别,可能说明 你在CPU上或模型很小

18.python

19.因为我们读取batch时 最后一个batch中样本数量可能不足 batch_size,
那么此时 accuracy/len(y) 是不对的,而是应该像evaluate_accuracy中这样将所有正、负例 累加起来再除
在这里插入图片描述
在这里插入图片描述

20.后面基于GPU会再讲

  1. 设一下是好习惯,即 设置后不用计算并更新梯度了,性能会好
  2. 就是传参穿进去的, 如手动实现时 手动放进去和 基于框架实现时用 net.parameters放进去

23.可能是。 后面会通过 微调学习率或加入正则项来解决过拟合

在这里插入图片描述

24.后面

25.后面
26.自己比一下。

在这里插入图片描述

27.可以看下pytorch文档,如将每个类别单独放一个文件夹

29.建议看下统计学习
弹幕说:softmax往前回溯的话应该是模式识别中的最大后验分类

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

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

相关文章

用ChatGPT教学、科研!亚利桑那州立大学与OpenAI合作

亚利桑那州立大学(简称“ASU”)在官网宣布与OpenAI达成技术合作。从2024年2月份开始,为所有学生提供ChatGPT企业版访问权限,主要用于学习、课程作业和学术研究等。 为了帮助学生更好地学习ChatGPT和大语言模型产品,AS…

unicloud 云对象 schema

目录 云对象 创建云对象 客户端调用 二、Schema(表结构) 什么是Schema? 如何编写DB Schema Schema的一级节点 客户端直连数据库 字段属性 字段类型bsonType 默认值defaultValue/forceDefaultValue 云对象 创建云对象 云对象&#…

HarmonyOS鸿蒙应用开发 (一、环境搭建及第一个Hello World)

万事开头难。难在迈出第一步。心无旁骛,万事可破。没有人一开始就能想清楚,只有做起来,目标才会越来越清晰。--马克.扎克伯格 前言 2024年1月16日,华为目前开启已HarmonyOS NEXT开发者预览版Beta招募,报名周期为1月15…

Conmi的正确答案——eclipse C/C++显示“未解析的包含:<xxx.h>”/“Unresolved inclusion: <xxx.h>”

eclipse IDE 版本&#xff1a;2023-12 部分采自&#xff1a;解决方法&#xff1a;关于问题 “C - Unresolved inclusion: <iostream>” 解释事项&#xff1a;方法一可能版本不同&#xff0c;部分界面修改了。这里使用的是方法二的解决方法。&#xff08;或者各位大神的描…

JavaEE中什么是Web容器?

Web容器&#xff08;也称为Servlet引擎&#xff09;是一个用于执行Java Servlet和JSP的服务器端环境。它负责管理和执行在其上运行的Web应用程序。 Tomcat是Web容器 Apache Tomcat 是一个流行的开源的Web容器&#xff0c;它实现了Java Servlet和JavaServer Pages&#xff08;…

【深度学习目标检测】十七、基于深度学习的洋葱检测系统-含GUI和源码(python,yolov8)

使用AI实现洋葱检测对农业具有以下意义&#xff1a; 提高效率&#xff1a;AI技术可以快速、准确地检测出洋葱中的缺陷和问题&#xff0c;从而提高了检测效率&#xff0c;减少了人工检测的时间和人力成本。提高准确性&#xff1a;AI技术通过大量的数据学习和分析&#xff0c;能够…

第五课:MindSpore自动并行

文章目录 第五课&#xff1a;MindSpore自动并行1、学习总结&#xff1a;数据并行模型并行MindSpore算子级并行算子级并行示例 流水线并行GPipe和Micro batch1F1B流水线并行示例 内存优化重计算优化器并行 MindSpore分布式并行模式课程ppt及代码地址 2、学习心得&#xff1a;3、…

如何使用pytorch的Dataset, 来定义自己的Dataset

Dataset与DataLoader的关系 Dataset: 构建一个数据集&#xff0c;其中含有所有的数据样本DataLoader&#xff1a;将构建好的Dataset&#xff0c;通过shuffle、划分batch、多线程num_workers运行的方式&#xff0c;加载到可训练的迭代容器。 import torch from torch.utils.dat…

Qt6入门教程 9:QWidget、QMainWindow和QDialog

目录 一.QWidget 1.窗口和控件 2.事件 二.QMainWindow 三.QDialog 1.模态对话框 1.1模态对话框 1.2.半模态对话框 2.非模态对话框 在用Qt Creator创建Qt Widgets项目时&#xff0c;会默认提供三种基类以供选择&#xff0c;它们分别是QWidget、QMainWIndow和QDialog&am…

SQL 注入总结(详细)

一、前言 这篇文章是最近学习 SQL 注入后的笔记&#xff0c;里面整理了 SQL 常见的注入方式&#xff0c;供大家学习了解 SQL 注入的原理及方法&#xff0c;也方便后续自己回顾&#xff0c;如有什么错误的地方欢迎指出&#xff01; 二、判断注入类型 按照注入点类型分类 数字型…

外贸自建站如何建立?海洋建站的操作指南?

外贸自建站的建站流程什么&#xff1f;做跨境怎么搭建外贸网站&#xff1f; 外贸自建站成为企业开拓国际市场、提升品牌形象的重要途径。然而&#xff0c;对于许多企业而言&#xff0c;如何高效地进行外贸自建站仍然是一个挑战。海洋建站将带您一步步探讨外贸自建站的关键步骤…

计算机网络——面试问题

1 从输⼊ URL 到⻚⾯展示到底发⽣了什么&#xff1f; 1. 先检查浏览器缓存⾥是否有缓存该资源&#xff0c;如果有直接返回&#xff1b;如果没有进⼊下⼀ 步⽹络请求。 2. ⽹络请求前&#xff0c;进⾏ DNS 解析 &#xff0c;以获取请求域名的 IP地址 。 3. 浏览器与服务器…

《WebKit 技术内幕》之七(3): 渲染基础

3 渲染方式 3.1 绘图上下文&#xff08;GraphicsContext&#xff09; 上面介绍了WebKit的内部表示结构&#xff0c;RenderObject对象知道如何绘制自己&#xff0c;但是&#xff0c;问题是RenderObject对象用什么来绘制内容呢&#xff1f;在WebKit中&#xff0c;绘图操作被定…

xcode 设置 ios苹果图标,为Flutter应用程序配置iOS图标

图标设置 1,根据图片构建各类尺寸的图标2.xcode打开ios文件3.xcode设置图标4.打包提交审核,即可(打包教程可通过我的主页查找) 1,根据图片构建各类尺寸的图标 工具网址:https://icon.wuruihong.com/ 下载之后文件目录如下 拷贝到项目的ios\Runner\Assets.xcassets\AppIcon.ap…

java简单的抽奖工具类(含测试方法)

文章目录 结果代码 结果 代码 import lombok.AllArgsConstructor; import lombok.Data; import lombok.ToString;import java.util.ArrayList; import java.util.List;/****/ public class LotteryUtils {public static void main(String[] args) throws InterruptedException…

PythonNet,Csharp如何白嫖Python生态和使用Matplotlib

文章目录 前言PythonNet环境配置Python环境配置Csharp Nuget配置运行代码测试运行结果 总结 前言 我既然用Csharp去尝试学习机器视觉&#xff0c;我就想试试用Csharp去使用Python的库。 这个世界上有没有编程语言既有Python的开发效率&#xff0c;又有C/C/ PythonNet Pythonne…

Android:JNI实战,加载三方库、编译C/C++

一.概述 Android Jni机制让开发者可以在Java端调用到C/C&#xff0c;也是Android应用开发需要掌握的一项重要的基础技能。 计划分两篇博文讲述Jni实战开发。 本篇主要从项目架构上剖析一个Android App如何通过Jni机制加载三方库和C/C文件。 二.Native C Android Studio可…

精准核酸检测 - 华为OD统一考试

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 题目描述 为了达到新冠疫情精准防控的需要&#xff0c;为了避免全员核酸检测带来的浪费&#xff0c;需要精准圈定可能被感染的人群。 现在根据传染病流调以及大数据分析&a…

【代码实战】从0到1实现transformer

获取数据 import pathlibimport tensorflow as tf# download dataset provided by Anki: https://www.manythings.org/anki/ text_file tf.keras.utils.get_file(fname"fra-eng.zip",origin"http://storage.googleapis.com/download.tensorflow.org/data/fra-…

transdata笔记:手机数据处理

1 mobile_stay_duration 每个停留点白天和夜间的持续时间 transbigdata.mobile_stay_duration(staydata, col[stime, etime], start_hour8, end_hour20) 1.1 主要参数 staydata停留数据&#xff08;每一行是一条数据&#xff09;col 列名&#xff0c;顺序为[‘starttime’,…