张量的基本运算
add() 加 +sub(),减 -
mul(),乘 *
div(),除 /
neg() 取负 -
add_(), sub_(), mul_(), div_(), neg_() # 功能同上,但会修改原有数据, 功能类似pandas中的inplace=True按元素相乘运算
元素级乘法, 对应位置的元素进行相乘两个张量形状相同
mul()/*
矩阵乘法运算
行*列, 行每个数据和列每个数据相乘求和规则: (n, m) * (m, p) =(n, p)
@/torch.matmul()
张量运算函数
min/max/mean/sum(dim=)不设置dim参数, 对所有元素进行计算
设置dim参数, 对应维度元素进行计算
sqrt()/**0.5
平方根, 开根号
log()/log2()/log10()/log1p()
对数
pow()/**
幂次方 x^n
exp()
指数 e^x
张量索引操作
作用
根据索引获取对应位置的数据
tensor[0轴下标, 1轴下标, ...]从左到右从0开始, 0->第一个数据
从右到左从-1开始, -1->最后一个数据
下标取值
tensor[0]->0轴第一个数据tensor[:, 0] ->1轴第一个数据
列表取值
tensor[[0,1], [2,4]]->0轴第1个1轴第3个值, 0轴第2个1轴第5个值范围取值(切片)
tensor[起始索引:结束索引:步长,...]布尔取值
tensor[:, 0]>10判断1轴第1组数据大于10->返回T/F
tensor[tensor[:, 0]>10]
获取True对应的0轴数据
多维索引
指定每个维度/轴的索引, tensor[1,2,3]
张量形状操作
tensor.reshape(shape=)
在保证数据不变的前提下, 修改连续和非连续张量形状修改前后的张量元素个数一致
-1:自动计算
tensor.squeeze(dim=)
删除长度为1的维度/轴, 可以通过dim指定删除维度tensor.unsqueeze(dim=)
在指定维度上增加维度值1tensor.view(shape=)
修改连续张量的形状, 操作等同于reshapetensor.contiguous()
转换成连续张量tensor.is_contiguous()
判断张量是否连续tensor.transpose(dim0=, dim1=)
交换指定两个维度的数据参数值是维度下标值
tensor.permute(dims=())
交换任意维度的数据参数值是维度下标值
张量拼接操作
torch.cat([t1, t2, ...], dim=)
在指定维度上对张量进行拼接其他维度值相同, 不改变新张量的维度
指定维度的维度值相加
torch.stack([t1, t2, ...], dim=)
在指定维度上对张量进行堆叠其他维度值相同, 新张量在指定维度新增维度
指定维度的维度值就是张量个数
所拼接的两个张量的shape必须相同
循环自动微分模块
步骤
1. 定义变量w = torch.tensor(10,requires_grad=True,dtype=torch.float)
- 定义loss变量,表示损失变量
- 利用梯度下降法,循坏迭代指定次数,求最优解
3.1 正向传播
3.2 梯度清零(因为系统会将梯度自动叠加)
3.3 反向传播
3.4 梯度更新
自动微分模块入门
反向传播:基于预测和真实可以得出误差,从而得到损失函数的结果,针对损失函数的结果进行求导,就可以得到本次的梯度值为多少,有了梯度值之后就可以反向更新w和b,会让第二轮的结果更加精准,从而一步步使得值达到最优。
自动微分模块=对损失函数求导,结合反向传播,更新权重参数w,b
多元线性公式: y=wx+b
权重更新公式:w新=w旧-学习率*梯度
偏置更新公式:b新=b旧-学习率*梯度
实际开发中,大多是情况下,不考虑偏置会将偏置矩阵直接设置为:全0矩阵
只有标量才能对向量求导
pytorch框架_模拟线性回归
detch()函数功能
一个张量 一旦开启了梯度计算/自动微分,就无法转为 numpy对象,需要通过detach()函数来解决
''' 案例: 演示 detach()函数功能,解决自动微分的弊端 回顾 自动微分=求导 基于损失函数 计算梯度 结合权重更新公式:w新=w旧-学习率*梯度,来更新权重的 问题: 一个张量 一旦开启了梯度计算/自动微分, 就无法转为 numpy对象,需要通过detach()函数来解决 需要掌握: n1 = t1.detach().numpy() 使得自动微分的张量能够转化为numpy类型 '''importtorchimportnumpyasnpimportmatplotlib.pyplotaspltimportmatplotlib matplotlib.use('TKAgg')plt.rcParams['font.sans-serif']=['SimHei']# 用来正常显示中文标签plt.rcParams['axes.unicode_minus']=False# 用来正常显示负号#设置设备device=torch.device('cuda'iftorch.cuda.is_available()else'cpu')# 1.定义张量# 参数1:数据;参数2:是否自动微分/求导/梯度计算;参数3:数据类型t1=torch.tensor([1,2,3],requires_grad=True,dtype=torch.float32)print(f"t1:{t1}, type:{type(t1)}, requires_grad:{t1.requires_grad}")# 2. 张量 转 numpy对象# n1 = t1.numpy()# print(f"n1: {n1}, type: {type(n1)}")# 3.使用 detach() 函数, 拷贝一份张量t2=t1.detach()print(f"t2:{t2}, type:{type(t2)}, requires_grad:{t2.requires_grad}")# 4.测试 t1, t2 是否共享内存t1.data[0]=100print(f"t1:{t1}, type:{type(t1)}, requires_grad:{t1.requires_grad}")print(f"t2:{t2}, type:{type(t2)}, requires_grad:{t2.requires_grad}")## # 5. t2 -> numpy对象# n1 = t2.numpy()# print(f"n1: {n1}, type: {type(n1)}")n1=t1.detach().numpy()print(f"n1:{n1}, type:{type(n1)}")自动微分真实应用场景
演示 自动微分的真实应用场景工作流:
1.前向传播,计算 预测值z 2.基于loss_fn损失函数,结合 预测值z 和 真实值y, 来计算损失值loss 3.自动微分,反向传播loss.backward(),过程中,自动计算loss对模型参数w, b的梯度/导数 4.更新权重,梯度下降法,w新 = w旧 - 学习率 * 梯度importtorch#定义 x 表示:特征(输入数据),假设:2行5列,全1矩阵x=torch.ones(2,5)print(f"x:{x}, shape:{x.shape}")# 2.定义yy=torch.zeros(2,3)print(f"y:{y}, shape:{y.shape}")# 3.初始化模型参数 权重w, 偏置b, x @ w + bw=torch.randn(5,3,requires_grad=True,dtype=torch.float32)b=torch.randn(3,requires_grad=True,dtype=torch.float32)print(f"w:{w}, shape:{w.shape}")print(f"b:{b}, shape:{b.shape}")# 4.前向传播,计算 预测值zz=torch.matmul(x,w)+bprint(f"z:{z}, shape:{z.shape}")#5.计算损失criterion=torch.nn.MSELoss()loss=criterion(z,y)print(f"loss:{loss}")# 6.反向传播,演示自动微分,计算梯度:loss对w, b的梯度# #如果loss不是一个值的话需要改为# loss.sum().backward()loss.backward()print(f"梯度w.grad:{w.grad}")print(f"梯度b.grad:{b.grad}")# 后续就是:梯度下降法来更新模型参数,w, bpytorch框架_模拟线性回归
工作流:
1.准备训练集数据构建数据加载器:张量 -> 数据集对象TensorDataset -> 数据加载器DataLoader 2.构建要使用的模型 3.设置损失函数和优化器 4.模型训练 6.可视化,损失函数曲线,拟合曲线# 导入相关模块importtorch# numpy对象 -> 张量Tensor -> 数据集对象Dataset -> 数据加载器DataLoader ->分批次获取流程fromtorch.utils.dataimportTensorDataset# 构造数据集对象fromtorch.utils.dataimportDataLoader# 数据加载器,分批次加载数据,方便模型按批次训练fromtorchimportnn# nn模块中有平方损失函数和假设函数,线性网络层fromtorchimportoptim# optim模块中有优化器函数fromsklearn.datasetsimportmake_regression# 创建线性回归模型数据集importmatplotlib.pyplotasplt# 绘图importmatplotlib matplotlib.use('TKAgg')plt.rcParams['font.sans-serif']=['SimHei']# 用来正常显示中文标签plt.rcParams['axes.unicode_minus']=False# 用来正常显示负号# 1.定义函数,构造数据集defcreate_dataset():# 创建数据集对象x,y,coef=make_regression(n_samples=100,# 样本数量,100n_features=1,# 特征数量,1noise=10,# 噪声coef=True,# 是否返回系数bias=14.5,# 偏置random_state=24,)# 转化为张量x=torch.tensor(x,dtype=torch.float32)y=torch.tensor(y,dtype=torch.float32)# 返回结果returnx,y,coef#2.定义函数,表示模型训练deftrain(x,y,coef):#创建数据集对象 把tensor->数据集 ->数据加载器dataset=TensorDataset(x,y)#2.创建数据加载器对象#参1:数据集对象 参2:批次大小 参3 是否打乱数据(训练集打乱,测试集不打乱)dataloader=DataLoader(dataset,batch_size=16,shuffle=True)#3.创建初始的 线性回归模型#参1:输入特征未付,参2 输出特征维度model=nn.Linear(1,1)#4.创建损失函数对象criterion=nn.MSELoss()#5.创建优化器对象#参1 模型参数 参2 学习率optimizer=optim.SGD(model.parameters(),lr=0.01)#6.具体的训练过程#6.1定义变量 分别表示 训练轮数 每轮的(平均)损失值 训练总损失 训练的样本epochs,loss_list,total_loss,total_sample=100,[],0.0,0#6.2开始训练,按轮训练forepochinrange(epochs):#epochs 的值0,1,2,....99#6.3 每轮是分批次 训练的,所以从 数据记载器中 获取 批次数据fortrain_x,train_yindataloader:#7批(16,16,16,16,16,16,4)#6.4 模型预测y_pred=model(train_x)#6.5计算(每批的平均值)loss=criterion(y_pred,train_y.reshape(-1,1))#-1 自动计算#6.6计算总损失 和样本(批次)数total_loss+=loss.item()total_sample+=1#6.7梯度清零 + 反向传播 + 梯度更新optimizer.zero_grad()#梯度清零loss.backward()#反向传播,计算梯度optimizer.step()#梯度更新#6.8把本轮的(平均) 损失值,添加到列表中loss_list.append(total_loss/total_sample)print(f"第{epoch+1}轮,平均损失值:{total_loss/total_sample}")#7.打印(最终的)训练结果print(f'{epochs}轮的平均损失分别为:{loss_list}')print(f'模型参数,权重:{model.weight},偏置:{model.bias}')#8.绘制损失曲线# 100轮 每轮的平均损失值plt.plot(range(epochs),loss_list)plt.title('损失值曲线变化图')plt.grid()#绘制网格线plt.show()#9.绘制预测值和真实值的关系#9.1绘制样本点分布情况plt.scatter(x,y)#9.2绘制训练模型的预测值#x:100个样本点的特征y_pred=torch.tensor(data=[v*model.weight+model.biasforvinx])#9.3 计算真实值y_true=torch.tensor(data=[v*coef+14.5forvinx])#9.4绘制预测值 和真实值的 折线图plt.plot(x,y_pred,color='red',label='预测值')plt.plot(x,y_true,color='green',label='真实值')#9.5图例 网格plt.legend()plt.grid()#9.6显示图像plt.show()if__name__=='__main__':x,y,coef=create_dataset()train(x,y,coef)