当前位置:   article > 正文

感知器_感知器学习算法中的权重如何初始化

感知器学习算法中的权重如何初始化

传统机器学习适合结构化数据

深度学习适合处理非结构化数据(图像,音频,视频,文本)

感知器

目录

感知器

1.1算法公式:可以实现二分类任务

1.2权重更新

1.3更新原则

1.4实现步骤

1.5程序示例


1.1算法公式:可以实现二分类任务

z为净输入,是连续的值,通过激励函数转成离散的值

1.2权重更新

感知器是一个自学习算法,即可以根据输入的数据(样本),不断调整权重的更新,最终完成分类。权重的更新公式如下:


其中,j表示某一列,i表示某一个样本。学习率 y(hat)代表y预测值

1.3更新原则

感知器的权重更新依据是:如果预测准确,则权重不进行更新,否则,增加权重,使其更趋向于正确的类别。

1.4实现步骤

  1. 对权重进行初始化。(初始化为0或者很小的数值。)
  2. 对训练集中每一个样本进行迭代,计算输出值y。
  3. 根据输出值y与真实值,更新权重。
  4. 循环步骤2。直到达到指定的次数(或者完全收敛)。

说明:

  • 如果两个类别线性可分,则感知器一定会收敛。
  • 如果两个类别线性不可分,则感知器一定不会收敛。

1.5程序示例

参考之前感知器的实现步骤,使用感知器实现与门与或门的计算。

  1. import numpy as np
  2. # 定义数据集
  3. X = np.array([[1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]])
  4. # 定义标签(每个样本所属的分类)。
  5. y = np.array([0, 0, 0, 1])
  6. # 定义权重。对于单层感知器,权重通常初始化为0或者很小的数值。
  7. # w = np.zeros(3)
  8. w = np.random.random(3)
  9. # 定义学习率。
  10. eta = 0.1
  11. for epoch in range(7):
  12. for x, target in zip(X, y):
  13. # 计算净输入
  14. z = np.dot(w, x)
  15. # 根据净输入,计算分类值。
  16. y_hat = 1 if z >= 0 else 0
  17. # 根据预测值与真实值,进行权重调整。
  18. w = w + eta * (target - y_hat) * x
  19. # 注意数组的矢量化计算,相当于执行了以下的操作。
  20. # w[0] = w[0] + eta * (y - y_hat) * x[0]
  21. # w[1] = w[1] + eta * (y - y_hat) * x[1]
  22. # w[2] = w[2] + eta * (y - y_hat) * x[2]
  23. print(target, y_hat)
  24. print(w)

算法的Python实现

现在,我们使用Python语言来实现感知器算法,进行鸢尾花的分类

  1. class Perceptron:
  2. """通过Python语言实现感知器类。用来进行二分类任务。"""
  3. def __init__(self, eta, epoch):
  4. """初始化方法。
  5. Parameter:
  6. -------
  7. eta: float
  8. 学习率。
  9. epoch: int
  10. 对训练集训练的轮数。
  11. """
  12. self.eta = eta
  13. self.epoch = epoch
  14. def step(self, z):
  15. """阶跃函数。对净输入进行转换。
  16. Parameter:
  17. -----
  18. z: 标量或数组类型
  19. 净输入。
  20. Return:
  21. ------
  22. t: 变量或数组类型。
  23. 分类的结果。0或者1。当z >= 0时,返回1,否则返回0。
  24. """
  25. # return 1 if z >= 0 else 0
  26. return np.where(z >= 0, 1, 0)
  27. def fit(self, X, y):
  28. """训练方法。
  29. Parameter:
  30. X: 类数组类型。形状为 (样本数量, 特征数量)
  31. 提供的训练集。
  32. y: 类数组类型。形状为(样本数量,)
  33. 样本对应的标签(分类)
  34. """
  35. # 对类型进行转换,不管是什么二维类型,统一转换成二维的ndarray数组类型。
  36. X = np.asarray(X)
  37. y = np.asarray(y)
  38. # 注意:权重的数量要比特征的数量多1。多出来的一个就是偏置。
  39. self.w_ = np.zeros(X.shape[1] + 1)
  40. # 定义损失列表。用来存放每个epoch迭代之后,分类错误的数量。
  41. self.loss_ = []
  42. # 迭代epoch指定的轮数。
  43. for i in range(self.epoch):
  44. # 用来记录单次epoch的损失值(分类错误的数量)
  45. loss = 0
  46. for x, target in zip(X, y):
  47. # 计算净输入
  48. z = np.dot(x, self.w_[1:]) + self.w_[0]
  49. # 根据净输入,计算分类。
  50. y_hat = self.step(z)
  51. # if target != y_hat:
  52. # loss += 1
  53. loss += target != y_hat
  54. # 调整权重
  55. self.w_[1:] += self.eta * (target - y_hat) * x
  56. # 调整偏置
  57. self.w_[0] += self.eta * (target - y_hat)
  58. # 将损失值加入到损失列表当中。
  59. self.loss_.append(loss)
  60. def predict(self, X):
  61. """预测方法。根据提供的数据集X,返回每一个样本对应的标签(分类)。
  62. Parameter:
  63. -----
  64. X: 类数组类型。形状为 (样本数量, 特征数量)
  65. 提供预测集。
  66. Return:
  67. -----
  68. label: 类数组类型。形状为:(样本数量,)
  69. 预测的每一个便签分类。
  70. """
  71. X = np.asarray(X)
  72. # 计算净输入。(矢量化计算,没有使用循环分别对每一个样本求净输出)
  73. z = np.dot(X, self.w_[1:]) + self.w_[0]
  74. # 获取最终的分类结果。(一维数组类型。)
  75. result = self.step(z)
  76. return result
  77. # 感知器类进行测试。
  78. X = np.array([[1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]])
  79. y = np.array([0, 0, 0, 1])
  80. p = Perceptron(0.1, 7)
  81. p.fit(X, y)
  82. print(p.w_)
  83. print(p.loss_)

练习

  • 使用感知器对鸢尾花两个类别进行分类。
  1. class Perceptron:
  2. """通过Python语言实现感知器类。用来进行二分类任务。"""
  3. def __init__(self, eta, epoch):
  4. """初始化方法。
  5. Parameter:
  6. -------
  7. eta: float
  8. 学习率。
  9. epoch: int
  10. 对训练集训练的轮数。
  11. """
  12. self.eta = eta
  13. self.epoch = epoch
  14. def step(self, z):
  15. """阶跃函数。对净输入进行转换。
  16. Parameter:
  17. -----
  18. z: 标量或数组类型
  19. 净输入。
  20. Return:
  21. ------
  22. t: 变量或数组类型。
  23. 分类的结果。0或者1。当z >= 0时,返回1,否则返回0。
  24. """
  25. # return 1 if z >= 0 else 0
  26. return np.where(z >= 0, 1, 0)
  27. def fit(self, X, y):
  28. """训练方法。
  29. Parameter:
  30. X: 类数组类型。形状为 (样本数量, 特征数量)
  31. 提供的训练集。
  32. y: 类数组类型。形状为(样本数量,)
  33. 样本对应的标签(分类)
  34. """
  35. # 对类型进行转换,不管是什么二维类型,统一转换成二维的ndarray数组类型。
  36. X = np.asarray(X)
  37. y = np.asarray(y)
  38. # 注意:权重的数量要比特征的数量多1。多出来的一个就是偏置。
  39. self.w_ = np.zeros(X.shape[1] + 1)
  40. # 定义损失列表。用来存放每个epoch迭代之后,分类错误的数量。
  41. self.loss_ = []
  42. # 迭代epoch指定的轮数。
  43. for i in range(self.epoch):
  44. # 用来记录单次epoch的损失值(分类错误的数量)
  45. loss = 0
  46. for x, target in zip(X, y):
  47. # 计算净输入
  48. z = np.dot(x, self.w_[1:]) + self.w_[0]
  49. # 根据净输入,计算分类。
  50. y_hat = self.step(z)
  51. # if target != y_hat:
  52. # loss += 1
  53. loss += target != y_hat
  54. # 调整权重
  55. self.w_[1:] += self.eta * (target - y_hat) * x
  56. # 调整偏置
  57. self.w_[0] += self.eta * (target - y_hat)
  58. # 将损失值加入到损失列表当中。
  59. self.loss_.append(loss)
  60. def predict(self, X):
  61. """预测方法。根据提供的数据集X,返回每一个样本对应的标签(分类)。
  62. Parameter:
  63. -----
  64. X: 类数组类型。形状为 (样本数量, 特征数量)
  65. 提供预测集。
  66. Return:
  67. -----
  68. label: 类数组类型。形状为:(样本数量,)
  69. 预测的每一个便签分类。
  70. """
  71. X = np.asarray(X)
  72. # 计算净输入。(矢量化计算,没有使用循环分别对每一个样本求净输出)
  73. z = np.dot(X, self.w_[1:]) + self.w_[0]
  74. # 获取最终的分类结果。(一维数组类型。)
  75. result = self.step(z)
  76. return result
  77. # 感知器类进行测试。
  78. X = np.array([[1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]])
  79. y = np.array([0, 0, 0, 1])
  80. p = Perceptron(0.1, 7)
  81. p.fit(X, y)
  82. print(p.w_)
  83. print(p.loss_)
  84. # 使用感知器实现鸢尾花的分类。
  85. from sklearn.datasets import load_iris
  86. from sklearn.model_selection import train_test_split
  87. import pandas as pd
  88. # return_X_y设置为True,只返回Data与target。
  89. X, y = load_iris(return_X_y=True)
  90. # X.shape, y.shape
  91. # np.concatenate 合并的数组,要求具有相同的维度,因此,需要将y变成
  92. # 2维的形式。
  93. data = pd.DataFrame(np.concatenate((X, y.reshape((-1, 1))), axis=1))
  94. # np.sum(data.duplicated())
  95. # display(data.shape)
  96. data.drop_duplicates(inplace=True)
  97. # display(data.shape)
  98. # data[4].map({0:1, 1:-1, 2:2})
  99. # data = data[data[4] != 2]
  100. data[4] = data[4].map({0:10, 1:0, 2:1})
  101. data = data[data[4] != 10]
  102. data[4].value_counts()
  103. # data[4].value_counts()
  104. X, y = data.iloc[:, :4], data.iloc[:, 4]
  105. train_X, test_X, train_y, test_y = train_test_split(X, y, test_size=0.2, random_state=0)
  106. # train_X.shape, test_X.shape
  107. p = Perceptron(0.1, 20)
  108. p.fit(train_X, train_y)
  109. # 查看训练后的权重与损失情况。
  110. # display(p.w_)
  111. # display(p.loss_)
  112. result = p.predict(test_X)
  113. np.sum(test_y == result) / len(result)
  114. import matplotlib as mpl
  115. import matplotlib.pyplot as plt
  116. mpl.rcParams["font.family"] = "SimHei"
  117. mpl.rcParams["axes.unicode_minus"] = False
  118. plt.plot(test_y.values, "go", ms=15, label="真实值")
  119. plt.plot(result, "rx", ms=15, label="预测值")
  120. plt.title("感知器二分类预测")
  121. plt.xlabel("样本序号")
  122. plt.ylabel("样本类别")
  123. plt.legend()
  124. plt.show()
  125. # 绘制损失曲线。(每个epoch预测样本错误的数量)
  126. plt.plot(range(1, len(p.loss_) + 1), p.loss_, "o-")

使用Python实现train_test_split方法的功能

  1. split_index = test_size * len()
  2. data[:split_index]
  3. data[split_index:]

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/286847
推荐阅读
相关标签
  

闽ICP备14008679号