在我正在上的机器学习课程中,我有100条数据条目,并将其用于感知机算法。我想要展示这样的一个图表。
如上图所示,我们用红点和蓝点表示数据,以及不同计算出的线条,这些线条最小化了误差。这就是我想要的输出。以下是我的数据和代码。
data.csv
0.78051,-0.063669,10.28774,0.29139,10.40714,0.17878,10.2923,0.4217,10.50922,0.35256,10.27785,0.10802,10.27527,0.33223,10.43999,0.31245,10.33557,0.42984,10.23448,0.24986,10.0084492,0.13658,10.12419,0.33595,10.25644,0.42624,10.4591,0.40426,10.44547,0.45117,10.42218,0.20118,10.49563,0.21445,10.30848,0.24306,10.39707,0.44438,10.32945,0.39217,10.40739,0.40271,10.3106,0.50702,10.49638,0.45384,10.10073,0.32053,10.69907,0.37307,10.29767,0.69648,10.15099,0.57341,10.16427,0.27759,10.33259,0.055964,10.53741,0.28637,10.19503,0.36879,10.40278,0.035148,10.21296,0.55169,10.48447,0.56991,10.25476,0.34596,10.21726,0.28641,10.67078,0.46538,10.3815,0.4622,10.53838,0.32774,10.4849,0.26071,10.37095,0.38809,10.54527,0.63911,10.32149,0.12007,10.42216,0.61666,10.10194,0.060408,10.15254,0.2168,10.45558,0.43769,10.28488,0.52142,10.27633,0.21264,10.39748,0.31902,10.5533,1,00.44274,0.59205,00.85176,0.6612,00.60436,0.86605,00.68243,0.48301,01,0.76815,00.72989,0.8107,00.67377,0.77975,00.78761,0.58177,00.71442,0.7668,00.49379,0.54226,00.78974,0.74233,00.67905,0.60921,00.6642,0.72519,00.79396,0.56789,00.70758,0.76022,00.59421,0.61857,00.49364,0.56224,00.77707,0.35025,00.79785,0.76921,00.70876,0.96764,00.69176,0.60865,00.66408,0.92075,00.65973,0.66666,00.64574,0.56845,00.89639,0.7085,00.85476,0.63167,00.62091,0.80424,00.79057,0.56108,00.58935,0.71582,00.56846,0.7406,00.65912,0.71548,00.70938,0.74041,00.59154,0.62927,00.45829,0.4641,00.79982,0.74847,00.60974,0.54757,00.68127,0.86985,00.76694,0.64736,00.69048,0.83058,00.68122,0.96541,00.73229,0.64245,00.76145,0.60138,00.58985,0.86955,00.73145,0.74516,00.77029,0.7014,00.73156,0.71782,00.44556,0.57991,00.85275,0.85987,00.51912,0.62359,0
现在这是我的代码。第一部分
import numpy as npimport pandas as pd# 设置随机种子,可以随意更改以查看不同的解决方案。np.random.seed(42)import matplotlib.pyplot as pltdef stepFunction(t): return 1 if t >= 0 else 0def prediction(X, W, b): return stepFunction((np.matmul(X, W) + b)[0])# TODO: 填写下面的代码以实现感知机技巧。# 输入# 数据X,标签y,# 权重W(作为数组)和偏置b,# 根据感知机算法调整权重和偏置W, b,# 并返回W和b。def perceptronStep(X, y, W, b, learn_rate=0.01): for i in range(len(X)): y_hat = prediction(X[i], W, b) if y[i] - y_hat == 1: W[0] += X[i][0] * learn_rate W[1] += X[i][1] * learn_rate b += learn_rate elif y[i] - y_hat == -1: W[0] -= X[i][0] * learn_rate W[1] -= X[i][1] * learn_rate b -= learn_rate return W, b# 此函数在数据集上重复运行感知机算法,# 并返回迭代中获得的一些边界线,# 用于绘图目的。# 可以随意调整学习率和迭代次数,# 并在下方查看结果图表。def trainPerceptronAlgorithm(X, y, learn_rate=0.01, num_epochs=25): x_min, x_max = min(X.T[0]), max(X.T[0]) y_min, y_max = min(X.T[1]), max(X.T[1]) W = np.array(np.random.rand(2, 1)) b = np.random.rand(1)[0] + x_max # 这些是下方绘制的解决方案线。 boundary_lines = [] for i in range(num_epochs): # 在每个迭代中,我们应用感知机步骤。 W, b = perceptronStep(X, y, W, b, learn_rate) # 这里我有一个疑问。为什么如果y = W0*x1 + W1*x2 + b # 那么我们可以得到 x2 = y/W1 - (W0*x1)/W1 - b/W1 + y/W1) # 如果我们去掉y/W1,我们只得到截距和斜率 # 但为什么我们不使用最后一个项y/W1 boundary_lines.append((-W[0] / W[1], -b / W[1])) return boundary_lines# 获取数据并绘制点data = pd.read_csv('data.csv', header = None)X = data.iloc[:, :2].valuesy = data.iloc[:, -1].valuesx1 = X[:, 0]x2 = X[:, 1]color = ['red' if value == 1 else 'blue' for value in y]plt.scatter(x1, x2, marker='o', color=color)plt.xlabel('X1输入特征')plt.ylabel('X2输入特征')plt.title('X1, X2的感知机回归')plt.show()
当你运行这段代码时,你会正确地得到
所以现在我想在同一个图表中绘制代表每次迭代最佳函数的线条。为此,我注释了上面的最后一行plt.show(),并做了以下操作
# 现在让我们绘制代表每次迭代最佳函数的线条boundary_lines = trainPerceptronAlgorithm(X, y)x_lin = np.linspace(0, 1, 100)for line in boundary_lines: Θo, Θ1 = line Θ1 = Θ1[0] Θo = Θo[0] # TODO: 误差函数的方程是 # y = W0*x1 + W1*x2 + b # 所以我们可以得到 x2 = y/W1 - (W0*x1)/W1 - b/W1 + y/W1) # 如果我们去掉y/W1,我们只得到截距和斜率 # boundary_lines.append((-W[0] / W[1], -b / W[1]) # plt.axes([-0.5, -0.5, 1.5, 1.5]) plt.plot(x_lin, (Θ1 * x_lin / Θo)) plt.draw() plt.pause(5) input("按回车键继续") plt.close()
但这并没有得到我期望的结果。为什么没有得到期望的结果?
回答:
错误在于plt.plot(x_lin, (Θ1 * x_lin / Θo))
,这里应该使用Θo * x_lin + Θ1
而不是Θ1 * x_lin / Θo
。
fig, ax = plt.subplots(1, 1, figsize=(8,5))ax.set_xlim(0, 1)ax.set_ylim(0, 1)ax.scatter(x1, x2, marker='o', color=color)for i, line in enumerate(boundary_lines): Θo, Θ1 = line if i == len(boundary_lines) - 1: c, ls, lw = 'k', '-', 2 else: c, ls, lw = 'g', '--', 1.5 ax.plot(x_lin, Θo * x_lin + Θ1, c=c, ls=ls, lw=lw)plt.show()
结果: