• python 使用Softmax回归处理IrIs数据集


    本文章包含以下内容:

            数据: lris数据集;

            模型: Softmax回归模型;

            损失函数:交叉嫡损失;

            优化器:梯度下降法;

            评价指标:准确率。

    1.实验数据集

            Iris(1).csv无法上传,这里就不提供下载了,它长这样

             lris数据集,也称为鸢尾花数据集,包含了3种鸢尾花类别(Setosa · Versicolour - Virginica),每种类别有50个样本,共计150个样本。其中每个样本中包含了4个属性:花尊长度﹑花芎宽度﹑花瓣长度以及花瓣宽度,本实验通过鸢尾花这4个属性来判断该样本的类别。

    2.读取数据集

            实验中将数据集划分为三个部分:训练集:用于确定模型参数;

            验证集:与训练集独立的样本集合,用于使用提前停止策略选择最优模型;

            测试集:用于估计应用效果。

            在本实验中,将80%的数据用于模型训练, 10%的数据用于模型验证,10%的数据用于模型测试。

    3.模型构建

            使用Softmax回归模型进行鸢尾花分类实验,将模型的输入维度定义为4,输出维度定义为3。

    4.模型训练

            使用训练集和验证集进行模型训练,共训练80个epoch,其中每隔10个epoch打印训练集上的指标,并且保存准确率最高的模型作为最佳模型。

    5.模型评价

            使用测试数据对在训练过程中保存的最佳模型进行评价,观察模型在测试集上的准确率情况。

    6.模型预测 

            使用保存好的模型,对测试集中的数据进行模型预测,并取出1条数据观察模型效果。

    代码如下:

    1. import numpy as np
    2. import pandas as pd
    3. import torch
    4. from torch import nn
    5. # 读取数据
    6. def read_data(file):
    7. # 读取csv文件,并存入data,带标签 dataframe
    8. data = pd.read_csv(file)
    9. data = data.sample(frac=1).reset_index(drop=True) # 打乱数据集
    10. y = list(data['Species']) # 标签
    11. len_data = len(y) # 数据个数
    12. # labels 删除的列标签,axis=1 删除列,inplace=True 改变原数据
    13. data.drop(labels=['Id', 'Species'], axis=1, inplace=True) # 删除Id,Species列
    14. # Species 转独热向量
    15. for i in range(len(y)):
    16. if y[i] == 'Iris-setosa':
    17. y[i] = [1, 0, 0]
    18. elif y[i] == 'Iris-versicolor':
    19. y[i] = [0, 1, 0]
    20. elif y[i] == 'Iris-virginica':
    21. y[i] = [0, 0, 1]
    22. y = torch.Tensor(y) # 转张量
    23. data = torch.Tensor(data.values) # 转张量
    24. # train 训练
    25. # verification 验证
    26. # test 测试
    27. return [[data[0:int(len_data * 0.8)], y[0:int(len_data * 0.8)]],
    28. [data[int(len_data * 0.8):int(len_data * 0.9)], y[int(len_data * 0.8):int(len_data * 0.9)]],
    29. [data[int(len_data * 0.9):len_data], y[int(len_data * 0.9):len_data]]]
    30. # 初始化参数 通过从均值为0﹑标准差为0.01的正态分布中采样随机数来初始化权重
    31. # 并将偏置初始化为0
    32. def chushi():
    33. # 返回从正态分布中提取的随机数的张量,该正态分布的均值是mean,标准差是std。
    34. # requires_grad=True 表示需要计算梯度,注意size=(4,3)列向量
    35. w = torch.normal(mean=0.1, std=0.01, size=(4, 3), requires_grad=True)
    36. return w
    37. # 测试函数,比较准确率
    38. def ceshi(w, f, l):
    39. c = 0
    40. # 模型计算出所有的结果
    41. l1 = softmax(f, w)
    42. for i in range(len(l)):
    43. # 如果最大值对应的l值是1,说明验证正确。
    44. s = -1
    45. t = float('-inf')
    46. for j in range(len(l[0])):
    47. if l1[i][j] > t:
    48. t = l1[i][j]
    49. s = j
    50. if l[i][s]:
    51. c = c + 1
    52. return c / len(l)
    53. # 该函数接收批量大小﹑特征矩阵和标签向量作为输入,生成大小为batch_size的小批量,每个小批量包含一组特征和标签。
    54. def data_iter(batch_size, features, labels): # 批量 特征 标签
    55. for i in range(len(labels) - batch_size):
    56. test_index = np.random.choice(len(features), batch_size, replace=False)
    57. yield features[test_index], labels[test_index]
    58. def softexp(A):
    59. A = A.exp()
    60. A_sum = A.sum(axis=1, keepdims=True)
    61. A = A / A_sum
    62. return A
    63. # 模型 输入特征为x﹑权重为w
    64. def softmax(X, w):
    65. S = torch.matmul(X, w)
    66. return softexp(S)
    67. # 交叉熵损失函数,返回损失值,其中y_hat为预测值, y为真实值。
    68. def cross_entropy_loss(y_hat, y):
    69. lo = 0
    70. for i in range(len(y)):
    71. lo -= (torch.log(y_hat) * y).sum()
    72. return lo / len(y)
    73. # 从数据集中随机抽取小批量样本,根据参数计算损失的梯度;然后朝着减少损失的方向更新参数。
    74. # 实现小批量随机梯度下降更新,该函数接受模型参数集合﹑学习速率和批量大小作为输入。
    75. def sgd(params, lr, batch_size, X, y, y_hat):
    76. # dw = (1.0 / batch_size) * torch.matmul((y - y_hat).T,X)
    77. # params.data = params + lr * dw.T
    78. params.data -= lr * params.grad / batch_size
    79. params.grad.zero_()
    80. def xunlian(batch_size, features, labels, f_verify, l_verify, w):
    81. lr = 0.03 # 学习率
    82. num_epochs = 81 # 循环次数
    83. net = softmax # 模型
    84. loss = cross_entropy_loss # 损失函数
    85. stop = 0 # 上一回的验证集准确率早停用
    86. for epoch in range(num_epochs):
    87. for X, y in data_iter(batch_size, features, labels):
    88. y_hat = net(X, w) # 计算y_hat
    89. l = loss(y_hat, y) # X和y 的小批量损失
    90. # 因为l形状是(batch_size,1),而不是一个标量。l中的所有元素被加到一起,
    91. # 并以此计算关于[w,b]的梯度
    92. l.sum().backward()
    93. sgd(w, lr, batch_size, X, y, y_hat) # 使用参数的梯度更新参数
    94. if epoch % 10 == 0: # 每循环10次执行
    95. with torch.no_grad(): # 输出当前误差,循环次数
    96. train_l = loss(net(features, w), labels)
    97. print(f'epoch {epoch}, loss {float(train_l.mean()):f}')
    98. c = ceshi(w[:], features, labels, ) # 看一看在训练集上的准确率
    99. print('训练集准确率:', c * 100, "%")
    100. c = ceshi(w[:], f_verify, l_verify) # 看一看在验证集上的准确率
    101. if stop > c: # 准确率下降,早停
    102. print('验证集准确率:', c * 100, "%-》早停")
    103. break
    104. else:
    105. print('验证集准确率:', c * 100, "%")
    106. stop = c
    107. W = w # 拿验证集准确率最高的
    108. return W, stop
    109. file = 'Iris(1).csv' # 数据文件
    110. [[X_train, y_train],
    111. [X_verification, y_verification],
    112. [X_test, y_test, ]] = read_data(file) # 读取数据集
    113. w = chushi() # 初始化 w
    114. batch_size = 1 # 批量大小为 8
    115. # 训练函数
    116. [w, c] = xunlian(batch_size, X_train, y_train, X_verification, y_verification, w)
    117. print('训练完成====================================')
    118. c = ceshi(w[:], X_test, y_test) # 测试集准确率
    119. print('测试集准确率:', c * 100, "%")
    120. print('所得w如下:\n', w)
    121. print('例子:\n X值:', X_test[0:1])
    122. print('实际y', y_test[0:1])
    123. print('预测y', softmax(X_test[0:1], w))
    124. # print(w)

    结果示例:

    1. epoch 0, loss 68.055267
    2. 训练集准确率: 63.33333333333333 %
    3. 验证集准确率: 66.66666666666666 %
    4. epoch 10, loss 27.553486
    5. 训练集准确率: 90.83333333333333 %
    6. 验证集准确率: 100.0 %
    7. epoch 20, loss 18.791990
    8. 训练集准确率: 95.83333333333334 %
    9. 验证集准确率: 100.0 %
    10. epoch 30, loss 17.222626
    11. 训练集准确率: 95.0 %
    12. 验证集准确率: 100.0 %
    13. epoch 40, loss 18.608782
    14. 训练集准确率: 92.5 %
    15. 验证集准确率: 100.0 %
    16. epoch 50, loss 14.631225
    17. 训练集准确率: 95.83333333333334 %
    18. 验证集准确率: 100.0 %
    19. epoch 60, loss 15.789186
    20. 训练集准确率: 95.0 %
    21. 验证集准确率: 100.0 %
    22. epoch 70, loss 16.089447
    23. 训练集准确率: 95.0 %
    24. 验证集准确率: 100.0 %
    25. epoch 80, loss 12.320921
    26. 训练集准确率: 96.66666666666667 %
    27. 验证集准确率: 100.0 %
    28. 训练完成====================================
    29. 测试集准确率: 100.0 %
    30. 所得w如下:
    31. tensor([[ 1.6637, 1.3427, -2.6891],
    32. [ 3.2052, 0.6697, -3.5951],
    33. [-4.0419, -0.4740, 4.8318],
    34. [-1.8177, -2.4302, 4.5498]], requires_grad=True)
    35. 例子:
    36. X值: tensor([[5.4000, 3.4000, 1.5000, 0.4000]])
    37. 实际y tensor([[1., 0., 0.]])
    38. 预测y tensor([[9.9477e-01, 5.2329e-03, 4.3153e-14]], grad_fn=<DivBackward0>)
    39. 进程已结束,退出代码为 0
    1. epoch 0, loss 108.753929
    2. 训练集准确率: 70.0 %
    3. 验证集准确率: 40.0 %
    4. epoch 10, loss 34.283939
    5. 训练集准确率: 85.83333333333333 %
    6. 验证集准确率: 73.33333333333333 %
    7. epoch 20, loss 28.772650
    8. 训练集准确率: 88.33333333333333 %
    9. 验证集准确率: 80.0 %
    10. epoch 30, loss 15.300897
    11. 训练集准确率: 96.66666666666667 %
    12. 验证集准确率: 93.33333333333333 %
    13. epoch 40, loss 17.209322
    14. 训练集准确率: 95.0 %
    15. 验证集准确率: 93.33333333333333 %
    16. epoch 50, loss 13.655725
    17. 训练集准确率: 95.83333333333334 %
    18. 验证集准确率: 86.66666666666667 %-》早停
    19. 训练完成====================================
    20. 测试集准确率: 100.0 %
    21. 所得w如下:
    22. tensor([[ 1.4083, 1.2524, -2.3524],
    23. [ 2.7663, 0.2030, -2.6643],
    24. [-3.4667, -0.2554, 4.0330],
    25. [-1.5833, -1.7317, 3.6147]], requires_grad=True)
    26. 例子:
    27. X值: tensor([[5.2000, 4.1000, 1.5000, 0.1000]])
    28. 实际y tensor([[1., 0., 0.]])
    29. 预测y tensor([[9.9853e-01, 1.4738e-03, 8.8739e-14]], grad_fn=<DivBackward0>)
    30. 进程已结束,退出代码为 0

    你们可以改一下批量大小,建议改为2的幂次,最好不要大于64,能加快训练速度(虽然本来也不慢)。

  • 相关阅读:
    Intel汇编语言程序设计(第7版)第八章编程练习题答案
    健康防猝指南2:饮食健康
    从零到一手写迷你版Vue
    【Iterator模式】C++设计模式——迭代器
    淘宝/天猫获得淘宝商品详情 API 返回值说明
    Java Math.sqrt()具有什么功能呢?
    Mysql通过binlog恢复误删数据
    38. rem适配布局
    【gl-transitions配置】原项目dockerfile修改,为视频添加转场效果
    【ONNX】导出,载入PyTorch的ONNX模型并进行预测新手教程(Windows+Python+Pycharm+PyTorch+ONNX)
  • 原文地址:https://blog.csdn.net/weixin_58196051/article/details/127424050