鱼C论坛

 找回密码
 立即注册
查看: 1566|回复: 0

tensorflow实现自编码器(Autoencoder)用softmax分类时无准确率

[复制链接]
发表于 2022-3-12 00:30:42 | 显示全部楼层 |阅读模式
20鱼币
环境为python3.7,tensorflow-gpu 2.1

数据集为iris数据集,训练过程采用无监督学习,测试过程采用有监督学习
神经网络为最基本的自编码器:包含输入层,编码隐藏层,解码隐藏层,softmax层用于分类

训练过程的loss一直是在下降,但是测试过程中的预测准确率却从100%降到0,这是什么原因呢?

跪谢解答的大神!!!

  1. import tensorflow as tf
  2. from sklearn import datasets
  3. from matplotlib import pyplot as plt
  4. import numpy as np

  5. # 导入iris数据集
  6. x_data = datasets.load_iris().data
  7. y_data = datasets.load_iris().target

  8. # 打乱数据集
  9. np.random.seed(116)
  10. np.random.shuffle(x_data)
  11. np.random.seed(116)
  12. np.random.shuffle(y_data)
  13. tf.random.set_seed(116)

  14. # 将打乱的数据集构造成训练集和测试集
  15. x_train = x_data[:-30]
  16. y_train = y_data[:-30]
  17. x_test = x_data[-30:]
  18. y_test = y_data[-30:]

  19. # 转换数据类型
  20. x_train = tf.cast(x_train, tf.float32)
  21. x_test = tf.cast(x_test, tf.float32)

  22. # 定义分批输入的训练集
  23. train_db = tf.data.Dataset.from_tensor_slices(x_train, ).batch(32)
  24. test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)

  25. # 定义超参数
  26. input_size = 4
  27. encoder_hidden = 3
  28. decoder_hidden = 3
  29. output_size = input_size

  30. # 生成神经网络的参数,4个输入特征故,输入层为4个输入节点;因为3分类,故输出层为3个神经元
  31. # 用tf.Variable()标记参数可训练
  32. # 用tf.random.truncated_normal,如果x的取值在区间(μ-2σ,μ+2σ)之外则重新进行选择。这样保证了生成的值都在均值附近。
  33. # tf.truncated_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)
  34. # shape: 一维的张量,也是输出的张量。 mean: 正态分布的均值。 stddev: 正态分布的标准差。 dtype: 输出的类型。
  35. # seed: 一个整数,当设置之后,每次生成的随机数都一样。
  36. # name: 操作的名字。
  37. # 使用seed使每次生成的随机数相同(方便教学,使大家结果都一致,在现实使用时不写seed)
  38. encoder_w1 = tf.Variable(tf.random.truncated_normal([input_size, encoder_hidden], stddev=0.1))
  39. encoder_b1 = tf.Variable(tf.random.truncated_normal([encoder_hidden], stddev=0.1))

  40. decoder_w1 = tf.Variable(tf.random.truncated_normal([encoder_hidden, output_size], stddev=0.1))
  41. decoder_b1 = tf.Variable(tf.random.truncated_normal([output_size], stddev=0.1))

  42. #dense_w1 = tf.Variable(tf.random.truncated_normal([output_size, output_size], stddev=0.1))
  43. #dense_b1 = tf.Variable(tf.random.truncated_normal([output_size]), stddev=0.1)

  44. lr = 0.09  # 学习率为0.1
  45. train_loss_results = []  # 将每轮的loss记录在此列表中,为后续画loss曲线提供数据
  46. test_loss_results = []
  47. test_acc = []  # 将每轮的acc记录在此列表中,为后续画acc曲线提供数据
  48. epoch = 101  # 循环500轮
  49. loss_train_all = 0  # 每轮分4个step,loss_all记录四个step生成的4个loss的和
  50. loss_test_all = 0

  51. # 训练部分
  52. for epoch in range(epoch):  # 数据集级别的循环,每个epoch循环一次数据集
  53.     for step, (x_train) in enumerate(train_db):  # batch级别的循环,每个step循环一次batch
  54.         with tf.GradientTape() as tape:  # wtih结构记录梯度信息
  55.             encoder_hidden_train_output = tf.nn.sigmoid(tf.matmul(x_train, encoder_w1) + encoder_b1)
  56.             decoder_hidden_train_output = tf.nn.sigmoid(tf.matmul(encoder_hidden_train_output, decoder_w1) + decoder_b1)

  57.             # 使输出softmax_hidden_output符合概率分布(此操作后与独热码同量级,可相减求loss)
  58.             #softmax_hidden_train_output = tf.nn.softmax(encoder_hidden_train_output)
  59.             #y_train_prediction = softmax_hidden_train_output
  60.             # 将标签转换成独热码格式,方便计算loss和accuracy
  61.             #y_real = tf.one_hot(y_train, dtype=3)

  62.             loss_train = tf.reduce_mean(tf.square(x_train - decoder_hidden_train_output))
  63.             # 用loss.numpy()取出loss中的值
  64.             # 将每个step计算出的loss累加,为后续求loss平均值提供数据,这样计算的loss更准确
  65.             loss_train_all += loss_train.numpy()
  66.         # 计算loss对各个参数的梯度
  67.             grads = tape.gradient(loss_train, [encoder_w1, encoder_b1, decoder_w1, decoder_b1])

  68.         # 梯度下降法
  69.         # 实现梯度更新 w1 = w1 - lr * w1_grad    b = b - lr * b_grad
  70.         # tf.assign_sub(ref, value, use_locking=None, name=None)
  71.         # 变量 ref 减去 value值,即 ref = ref - value
  72.         # ref:变量;value:值;use_locking,默认 False, 若为 True,则受锁保护;name,名称
  73.         encoder_w1.assign_sub(lr * grads[0])  # 参数encoder_w1自更新
  74.         encoder_b1.assign_sub(lr * grads[1])  # 参数encoder_b1自更新
  75.         decoder_w1.assign_sub(lr * grads[2])  # 参数decoder_w1自更新
  76.         decoder_b1.assign_sub(lr * grads[3])  # 参数decoder_b1自更新

  77.     # 每个epoch打印loss信息
  78.     print('Epoch:{}, loss_train:{}'.format(epoch, loss_train_all / 4))
  79.     train_loss_results.append(loss_train_all / 4)  # 将8个step的loss求平均记录在train_loss_results中
  80.     loss_train_all = 0  # loss_all归零,为记录下一个epoch的loss做准备

  81.     # 测试部分
  82.     # total_correct为预测对的样本数,total_number为测试的总样本数,将这两个变量初始化为0
  83.     correct = 0
  84.     total_correct, total_number = 0, 0
  85.     for x_test, y_test in test_db:
  86.         # 使用更新后的参数进行预测
  87.         encoder_hidden_test_output = tf.nn.sigmoid(tf.matmul(x_test, encoder_w1) + encoder_b1)
  88.         #decoder_hidden_test_output = tf.nn.sigmoid(tf.matmul(encoder_hidden_test_output, decoder_w1) + decoder_b1)
  89.         softmax_hidden_test_output = tf.nn.softmax(encoder_hidden_test_output)

  90.         # tf.argmax(array, axis)按行或列返回array中最大元素的索引值
  91.         # axis=0表示跨行(经度,搜寻每一列的最大值的索引);axis=1表示跨列(纬度,搜寻每一行的最大值的索引)
  92.         # axis不指定的话,所有元素参与运算
  93.         y_test_prediction = tf.argmax(softmax_hidden_test_output, axis=1)  # 返回decoder_hidden_test_output最大值的索引,即预测的分类

  94.         # 将y_test_prediction转换成y_test的数据类型
  95.         y_test_prediction = tf.cast(y_test_prediction, dtype=y_test.dtype)

  96.         # 若分类正确,则correct=1,否则为0,将bool型的结果转换成int型
  97.         correct = tf.cast(tf.equal(y_test, y_test_prediction), dtype=tf.int32)

  98.         # 将每个batch的correct数加起来
  99.         correct = tf.reduce_sum(correct)
  100.         # 将所有batch中的correct数加起来
  101.         total_correct += int(correct)
  102.         # total_number为测试的总样本数,即x_test的行数,shape[0]返回变量的行数
  103.         total_number += x_test.shape[0]
  104.     # 总的准确率等于total_correct/total_number
  105.     acc = total_correct / total_number
  106.     test_acc.append(acc)

  107.     print("Test_acc:{0}, correct:{1}, total_correct:{2}, total_number:{3}".format(acc, correct, total_correct, total_number))
  108.     print('--------------------------')

  109. # 绘制loss_train曲线
  110. plt.title("Loss_Train Function Curve")  # 图标题
  111. plt.xlabel("Epoch")  # x轴名称
  112. plt.ylabel("Loss_Train")  # y轴名称
  113. plt.plot(train_loss_results, label='$Loss_train$')  # 逐点画出train_loss_results值并连线,连线图标是Loss_train
  114. plt.legend()  # 画出曲线图标
  115. plt.show()  # 画出图像

  116. # 绘制Accuracy曲线
  117. plt.title("Accuracy Curve")
  118. plt.xlabel("Epoch")
  119. plt.ylabel("Accuracy")
  120. plt.plot(test_acc, label='$Accuracy$')
  121. plt.legend()
  122. plt.show()
复制代码

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-29 23:42

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表