网站没有icp备案,vs网站开发教程,自助建站免费搭建个人网站,网站编辑转行做文案目录 五维向量交叉熵多分类 规律#xff1a; 实现#xff1a; 1.设计模型 2.生成数据集 3.模型测试 4.模型训练 5.对训练的模型进行验证 调用模型 你的平静#xff0c;是你最强的力量 —— 24.12.6 五维向量交叉熵多分类
规律#xff1a;
x是一个五维(索引)向量#xff… 目录 五维向量交叉熵多分类 规律 实现 1.设计模型 2.生成数据集 3.模型测试 4.模型训练 5.对训练的模型进行验证 调用模型 你的平静是你最强的力量 —— 24.12.6 五维向量交叉熵多分类
规律
x是一个五维(索引)向量对x做五分类任务
改用交叉熵实现一个多分类任务五维随机向量中最大的数字在哪维就属于哪一类 实现
1.设计模型
Linear()模型函数中定义线性层
activation nn.Softmax(dim1)定义激活层为softmax激活函数
nn.CrossEntropyLoss() / nn.functional.cross_entropy定义交叉熵损失函数
pyTorch中定义的交叉熵损失函数内部封装了softMax函数 而使用交叉熵必须使用softMax函数对数据进行归一化
经过 Softmax 归一化后输出向量的每个元素可以被解释为样本属于相应类别的概率。这使得我们能够直接比较不同类别上的概率大小并且与真实的类别概率分布(如one-hot编码)进行合理的对比。
例如在一个三分类问题中经过 Softmax 后的输出可能是[0.2,0.3,0.5]我们可以直观地说样本属于第三类的概率是 0.5这是一个符合概率意义的解释
forward函数前向计算定义网络的使用方式声明模型计算过程
# 1.设计模型
class TorchModel(nn.Module):def __init__(self, input_size):super(TorchModel, self).__init__()# 预测出一个五维的向量五维向量代表五个类别上的概率分布self.linear nn.Linear(input_size, 5) # 线性层# 类交叉熵写法CrossEntropyLoss() 函数交叉熵写法cross_entropy# nn.CrossEntropyLoss() pycharm交叉的熵损失函数内部封装了softMax函数 而使用交叉熵必须使用softMax函数self.loss nn.functional.cross_entropy # loss函数采用交叉熵损失self.activation nn.Softmax(dim1)# 当输入真实标签返回loss值无真实标签返回预测值def forward(self, x, yNone):# 输入过第一个网络层y_pred self.linear(x) # (batch_size, input_size) - (batch_size, 1)if y is not None:return self.loss(y_pred, y) # 预测值和真实值计算损失else:return self.activation(y_pred) # 输出预测结果# return y_pred 2.生成数据集
由于题目要求要在一个五维随机向量中查找标量最大的数所在维度所以用np.random函数随机生成一个五维向量然后通过np.argmax函数找出生成向量中最大标量所对应的维度并将其作为数据 x 的标注 y 返回
当我们输出一串数字要告诉模型输出的是一串单独的数而不是一串样本时需要用到 [ ]换句话说当y是单独的一个数标量时才需要加“[ ]”
而该模型输出的预测结果是一个向量而不是一个数标量的概率时不需要拼在一起
# 2.生成数据集标签label 数据构建
# 生成一个样本, 样本的生成方法代表了我们要学习的规律随机生成一个5维向量如果第一个值大于第五个值认为是正样本反之为负样本
def build_sample():x np.random.random(5)# 获取最大值对应的索引max_index np.argmax(x)return x, max_index# 随机生成一批样本
# 正负样本均匀生成
def build_dataset(total_sample_num):X []Y []# 随机生成样本,total_sample_num 生成的随机样本数for i in range(total_sample_num):x, y build_sample()X.append(x)# 当我们输出一串数字要告诉模型输出的是一串单独的数而不是一串样本时需要用到[]换句话说当y是单独得一个数标量时才需要加“[]”# 而该模型输出的预测结果是一个向量而不是一个数标量的概率时不需要拼在一起Y.append(y)X_array np.array(X)Y_array np.array(Y)# 一般torch中的Long整形类型用来判定类型return torch.FloatTensor(X_array), torch.LongTensor(Y_array) 3.模型测试
用来测试每轮模型预测的精确度
model.eval()声明模型框架在这个函数中不做训练
with torch.no_grad()在模型测试的部分中声明是测试函数不计算梯度增加模型训练效率
zip()zip 函数是一个内置函数用于将多个可迭代对象(如列表、元组、字符串等)中对应的元素打包成一个个元组然后返回由这些元组组成的可迭代对象(通常是一个 zip 对象)。如果各个可迭代对象的长度不一致那么 zip 操作会以最短的可迭代对象长度为准。
# 3.模型测试
# 用来测试每轮模型的准确率
def evaluate(model):model.eval()test_sample_num 100x, y build_dataset(test_sample_num)print(本次预测集中共有%d个正样本%d个负样本 % (sum(y), test_sample_num - sum(y)))correct, wrong 0, 0with torch.no_grad():y_pred model(x) # 模型预测 model.forward(x)for y_p, y_t in zip(y_pred, y): # 与真实标签进行对比# np.argmax是求最大数所在维max求最大数torch.argmax是求最大数所在维if torch.argmax(y_p) int(y_t):correct 1 # 正确预测加一else:wrong 1 # 错误预测加一print(正确预测个数%d, 正确率%f % (correct, correct / (correct wrong)))return correct / (correct wrong) 4.模型训练
① 配置参数
② 建立模型
③ 选择优化器Adam
④ 读取训练集
⑤ 训练过程 Ⅰ、model.train()设置训练模式 Ⅱ、对训练集样本开始循环训练循环取出训练数据 Ⅲ、根据模型函数和损失函数的定义计算模型损失 Ⅳ、计算梯度 Ⅴ、通过梯度用优化器更新权重 Ⅵ、计算完一轮训练数据后梯度进行归零下一轮重新计算
torch.save(model.state_dict(), model.pt)将模型保存为model.pt文件
一般任务不同只需更改数据读取步骤③和模型构建步骤①内容训练过程一般无需更改evaluate测试代码可能也需更改因为不同模型测试正确率的方式不同
# 4.模型训练
def main():# 配置参数epoch_num 20 # 训练轮数batch_size 20 # 每次训练样本个数train_sample 5000 # 每轮训练总共训练的样本总数input_size 5 # 输入向量维度learning_rate 0.001 # 学习率# ① 建立模型model TorchModel(input_size)# ② 选择优化器optim torch.optim.Adam(model.parameters(), lrlearning_rate)log []# ③ 创建训练集正常任务是读取训练集train_x, train_y build_dataset(train_sample)# 训练过程# 轮数进行自定义for epoch in range(epoch_num):model.train()watch_loss []# ④ 读取数据集for batch_index in range(train_sample // batch_size):x train_x[batch_index * batch_size : (batch_index 1) * batch_size]y train_y[batch_index * batch_size : (batch_index 1) * batch_size]# ⑤ 计算lossloss model(x, y) # 计算loss model.forward(x,y)# ⑥ 计算梯度loss.backward() # 计算梯度# ⑦ 权重更新optim.step() # 更新权重# ⑧ 梯度归零optim.zero_grad() # 梯度归零watch_loss.append(loss.item())# 一般任务不同只需更改数据读取步骤③和模型构建步骤①内容训练过程一般无需更改evaluate测试代码可能也需更改因为不同模型测试正确率的方式不同print(\n第%d轮平均loss:%f % (epoch 1, np.mean(watch_loss)))acc evaluate(model) # 测试本轮模型结果log.append([acc, float(np.mean(watch_loss))])# 保存模型torch.save(model.state_dict(), model.pt)# 画图print(log)plt.plot(range(len(log)), [l[0] for l in log], labelacc) # 画acc曲线plt.plot(range(len(log)), [l[1] for l in log], labelloss) # 画loss曲线plt.legend()plt.show()return 5.对训练的模型进行验证
调用main函数
if __name__ __main__:main() 调用模型
model.eval()声明模型框架在这个函数中不做训练
predict(model.pt, test_vec)调用模型存储的文件model.pt通过调用模型对数据进行预测
# 使用训练好的模型做预测
def predict(model_path, input_vec):input_size 5model TorchModel(input_size)# 加载训练好的权重model.load_state_dict(torch.load(model_path, weights_onlyTrue))# print(model.state_dict())model.eval() # 测试模式不计算梯度with torch.no_grad():# 输入一个真实向量转成Tensor让模型forward一下result model.forward(torch.FloatTensor(input_vec)) # 模型预测for vec, res in zip(input_vec, result):# python中round函数是对浮点数进行四舍五入print(输入%s, 预测类别%s, 概率值%s % (vec, torch.argmax(res), res)) # 打印结果if __name__ __main__:test_vec [[0.97889086,0.15229675,0.31082123,0.03504317,0.88920843],[0.74963533,0.5524256,0.95758807,0.95520434,0.84890681],[0.00797868,0.67482528,0.13625847,0.34675372,0.19871392],[0.09349776,0.59416669,0.92579291,0.41567412,0.1358894]]predict(model.pt, test_vec)