0


【人工智能-神经网络】Numpy 实现单层感知机对情感文本多分类

Numpy 实现单层感知机对情感文本多分类

一、 实验题目

在给定文本数据集完成文本情感分类训练,在测试集完成测试,计算准确率

文本的特征可以使用TF或TF-IDF (可以使用sklearn库提取特征)设计合适的网络结构,选择合适的损失函数利用训练集完成网络训练,并在测试集上计算准确率。

训练集:train.txt
在这里插入图片描述

测试集: test.txt
在这里插入图片描述

二、 实验内容

1. 假定网络为单层感知机,且没有激活层,没有偏置,此时,网络输出为y=XW

2.设置损失函数为L_MSE,并随机初始化网络参数W

3.当满足终止条件时,终止优化,否则继续

4.计算网络输出y=XW,以及损失

  1. L
  2. M
  3. S
  4. E
  5. =
  6. 1
  7. /
  8. N
  9. (
  10. X
  11. W
  12. Y
  13. )
  14. T
  15. (
  16. X
  17. W
  18. Y
  19. )
  20. L_{MSE}=1/N(XWY)^T (XWY)
  21. LMSE​=1/N(XWY)T(XWY)

**5.求导可得

  1. L
  2. M
  3. S
  4. E
  5. /
  6. W
  7. =
  8. 1
  9. /
  10. N
  11. X
  12. T
  13. (
  14. X
  15. W
  16. Y
  17. )
  18. L_{MSE}/∂W=1/N X^T(XWY)
  19. LMSE​/∂W=1/NXT(XWY)**

**6.根据

  1. W
  2. =
  3. W
  4. η
  5. L
  6. M
  7. S
  8. E
  9. /
  10. W
  11. W=W−η∂L_{MSE}/∂W
  12. W=W−η∂LMSE​/∂W更新参数W**

7.跳转到3

三、关键代码

  1. from sklearn.feature_extraction.text import TfidfVectorizer
  2. import numpy as np
  3. from sklearn.preprocessing import LabelBinarizer
  4. import matplotlib.pyplot as plt
  5. train_set_path ='train.txt'
  6. test_set_path ='test.txt''''
  7. ---------------Basic Concept---------------
  8. 1. 单层感知机 (输入层+输出层), 输入层为每个文本的特征值、输出层经过sigmoid函数, 为各类的预测值
  9. 2. 输入、输出、权重三者的关系为: Y = XW, 其中,X是(train_size, feature_size)的矩阵, W是(feature_size, class_num)的矩阵
  10. 2.1. 需要注意的是, 由于输出经过了sigmoid函数, 因此值被限制在0~1之间, 而我们使用的标签是1~6的数, 所以要将它化成二进制码
  11. 3. 损失为L_MSE=1/N(XW−Y)^T(XW−Y) 对权重进行更新, 通过W = W - lr * ∂L_MSE/∂W, 其中∂L_MSE/∂W = 1/N X^T(XW−Y): [(feature_size, train_size) * (train_size, 6)]
  12. 3.1. 这里的Y是标签, 因为已经化成二进制值,所以每一个Yi是(1,6)的矩阵,如[0,0,0,1,0,0]表示标签4,
  13. ---------------END---------------
  14. '''# hyper parameters
  15. learning_rate =0.6
  16. num_epochs =4000
  17. num_classes =6
  18. batch_size =100
  19. epochs =[]
  20. accur_train =[]
  21. accur_test =[]# 激活函数defsigmoid(x):return1/(1+ np.exp(-x))defdsigmoid(x):return x *(1- x)defdata_process(path):'''
  22. :param path: 数据集路径
  23. :return: 文本、情感标签
  24. '''
  25. words =[]
  26. data_set =[]
  27. emotion =[]withopen(path,'r')as F:
  28. line = F.readlines()for i inrange(1,len(line)):
  29. emo =(int)(line[i].split()[1])# 情感标签
  30. temp = line[i].split()[3:]
  31. out =' '.join(temp)
  32. words.append(out)
  33. emotion.append(emo)return words, emotion
  34. deftf_idf_cal(text):'''
  35. :param text: 待计算文本
  36. :return: 特征名称和特征值矩阵
  37. '''
  38. tf_idf_vec = TfidfVectorizer()
  39. tf_idf_matrix = tf_idf_vec.fit_transform(text)return tf_idf_vec.get_feature_names(), tf_idf_matrix.toarray()
  40. words_train, emotion_train = data_process(train_set_path)
  41. words_test, emotion_test = data_process(test_set_path)
  42. train_feature_name, train_tf_idf = tf_idf_cal(words_train)
  43. test_feature_name, test_tf_idf = tf_idf_cal(words_test)# 处理训练集,将测试集特征在训练集中未出现过的特征值赋值为0
  44. aligned_train_set =[]
  45. aligned_test_set = test_tf_idf
  46. for k inrange(len(train_tf_idf)):
  47. temp =[]for i inrange(len(test_feature_name)):
  48. feature = test_feature_name[i]if feature in train_feature_name:
  49. idx = train_feature_name.index(feature)
  50. temp.append(train_tf_idf[k][idx])else:
  51. temp.append(0)
  52. aligned_train_set.append(temp)'''
  53. 方便查看:
  54. ---------------Basic Concept---------------
  55. 1. 单层感知机 (输入层+输出层), 输入层为每个文本的特征值、输出层经过sigmoid函数, 为各类的预测值
  56. 2. 输入、输出、权重三者的关系为: Y = XW, 其中,X是(train_size, feature_size)的矩阵, W是(feature_size, class_num)的矩阵
  57. 2.1. 需要注意的是, 由于输出经过了sigmoid函数, 因此值被限制在0~1之间, 而我们使用的标签是1~6的数, 所以要将它化成二进制码
  58. 3. 损失为L_MSE=1/N(XW−Y)^T (XW−Y): [(6,train_size) * (train_size, 6)] 对权重进行更新, 通过W = W - lr * ∂L_MSE/∂W, 其中∂L_MSE/∂W = 1/N X^T(XW−Y): [(feature_size, train_size) * (train_size, 6)]
  59. 3.1. 这里的Y是标签, 因为已经化成二进制值,所以每一个Yi是(1,6)的矩阵,如[0,0,0,1,0,0]表示标签4,
  60. 我们需要对Y进行扩展, 以便计算损失, 即将Y扩展成(train_size, 6)的矩阵,
  61. ---------------END---------------
  62. '''defMSE(inputs, outputs, labels):# 这里的labels为(train_size, 6)的矩阵'''
  63. :param inputs: 特征矩阵 (train_size, feature_size)
  64. :param outputs: 网络输出 (train_size, num_class)
  65. :param labels: 标签 (train_size, num_class)
  66. :return: MES loss和它对W的偏导数
  67. '''
  68. n = outputs.shape[0]# train_size
  69. mse_loss =0# 所有样本的mse loss之和
  70. loss_mat =(outputs - labels)**2/ n # 矩阵(train_size, train_size)for loss in loss_mat:
  71. mse_loss += loss.sum()
  72. loss_partial_mat = np.dot(inputs.T,(outputs - labels))/ n # 矩阵(feature_size, num_class)return mse_loss, loss_partial_mat
  73. '''
  74. 单层感知机
  75. '''classPerceptron:def__init__(self, in_size, out_size):
  76. self.in_size = in_size
  77. self.out_size = out_size
  78. self.weights = np.random.randn(in_size, out_size)# 随机化权重矩阵defforward(self, X):
  79. out = np.dot(X, self.weights)
  80. out = sigmoid(out)# sigmoid函数,输出值被限制到01之间return out
  81. # 转换成numpy数组
  82. aligned_train_set = np.array(aligned_train_set)
  83. aligned_test_set = np.array(aligned_test_set)
  84. emotion_train = np.array(emotion_train)
  85. emotion_test = np.array(emotion_test)# 数值为1~6的情感标签转化成二进制
  86. emotion_train_b = LabelBinarizer().fit_transform(emotion_train)
  87. emotion_test_b = LabelBinarizer().fit_transform(emotion_test)# 数据集参数
  88. total_step = train_size =len(aligned_train_set)
  89. test_size =len(aligned_test_set)
  90. feature_size =len(aligned_train_set[0])'''
  91. Train the perceptron and Predict the label each batch
  92. '''
  93. perceptron = Perceptron(feature_size, num_classes)for epoch inrange(num_epochs):
  94. out = perceptron.forward(aligned_train_set)
  95. out_test = perceptron.forward(aligned_test_set)
  96. mse_loss, loss_partial_mat = MSE(aligned_train_set, out, emotion_train_b)
  97. perceptron.weights = perceptron.weights - learning_rate * loss_partial_mat
  98. if epoch % batch_size ==0:
  99. pre_label =[]for i inrange(out.shape[0]):
  100. pre_label.append(np.argmax(out[i])+1)
  101. accuracy = np.mean(np.equal(pre_label, emotion_train))print('Train_Set: Epoch [{}/{}], Loss: {:.4f}, Accuracy: {}'.format(epoch +1, num_epochs, mse_loss,100* accuracy))
  102. accur_train.append(100* accuracy)
  103. pre_label =[]for i inrange(out_test.shape[0]):
  104. pre_label.append(np.argmax(out_test[i])+1)
  105. accuracy = np.mean(np.equal(pre_label, emotion_test))print('Test_Set: Epoch [{}/{}], Loss: {:.4f}, Accuracy: {}'.format(epoch +1, num_epochs, mse_loss,100* accuracy))
  106. epochs.append(epoch)
  107. accur_test.append(100* accuracy)
  108. plt.ylim((0,100))
  109. plt.xlabel("Epoch")
  110. plt.ylabel("Accuracy")
  111. plt.plot(epochs, accur_train, marker='o')
  112. plt.plot(epochs, accur_test, marker='*')
  113. plt.legend(['Train','test'])
  114. plt.show()

四、实验结果:

通过numpy矩阵进行运算速度还是很快的,基本在几秒内就能够算出结果。

(1) Epoch 500

image-20220526195922854

image-20220526195938638

(2) Epoch 2000

在这里插入图片描述

image-20220526195819467

(3) Epoch 4000

image-20220526200114387

image-20220526195642081


本文转载自: https://blog.csdn.net/m0_52387305/article/details/124991519
版权归原作者 Maxwell-Wong 所有, 如有侵权,请联系我们删除。

“【人工智能-神经网络】Numpy 实现单层感知机对情感文本多分类”的评论:

还没有评论