LizierData Optimal
电脑之心校对
参予:distinguished萌、路
责任编辑以fluctuation为例,如是说了从零同时实现电脑自学方式的要点和必要性。
Cubzac写电脑自学演算法能赢得许多实战经验。当你最后顺利完成时,你会基克县,所以你明白这另一面到底出现了甚么。
很多演算法非常复杂,他们不从单纯的演算法已经开始,而要要从非常单纯的演算法已经开始,比如说双层fluctuation。
责任编辑以fluctuation为例,透过下列 6 个关键步骤鼓励你Cubzac写演算法:
对演算法有基本上的介绍
找出相同的学习天然资源
将演算法还原成块
从单纯的范例已经开始
用可靠的同时实现展开校正
写出你的操作过程
基本上介绍
不介绍基础知识,就无法Cubzac处理演算法。至少,你要能回答下列问题:
它是甚么?
它一般用在甚么地方?
甚么时候不能用它?
就fluctuation而言,这些问题的答案如下:
双层fluctuation是最基础的神经网络,一般用于二分类问题(1 或 0,「是」或「否」)。
它可以应用在一些单纯的地方,比如说情感分析(积极反应或消极反应)、贷款违约预测(「会违约」,「不会违约」)。在这两种情况中,决策边界都是线性的。
当决策边界是非线性的时候不能使用fluctuation,要用相同的方式。
借助相同的自学天然资源
在对模型有了基本上介绍之后,就可以已经开始研究了。有人用教科书学得更好,而有人用视频学得更好。就我而言,我喜欢到处转转,用各种各样的天然资源自学。
如果是学数学细节的话,书的效果很好(参见:https://www.dataoptimal.com/data-science-books-2018/),但对于更实际的范例,我更推荐博客和 YouTube 视频。
下列列举了一些关于fluctuation不错的天然资源:
书
《统计自学基础》(The Elements of Statistical Learning),第 4.5.1 节(https://web.stanford.edu/~hastie/Papers/ESLII.pdf)
《深入理解电脑自学:从原理到演算法》,第 21.4 节(https://www.cs.huji.ac.il/~shais/UnderstandingMachineLearning/understanding-machine-learning-theory-algorithms.pdf)
博客
Jason Brownlee 写的《如何用 Python 从零已经开始同时实现fluctuation演算法》(https://machinelearningmastery.com/implement-perceptron-algorithm-scratch-python/)
Sebastian Raschka 写的《双层神经网络和梯度下降》(https://sebastianraschka.com/Articles/2015_singlelayer_neurons.html)
视频
fluctuation训练(https://www.youtube.com/watch?v=5g0TPrxKK6o)
fluctuation演算法的工作原理(https://www.youtube.com/watch?v=1XkjVl-j8MM)
将演算法还原成块
现在他们已经收集好了资料,是时候已经开始自学了。与其从头读一个章节或者一篇博客,不如先浏览章节标题和其他重要信息。写出要点,并试着概述演算法。
在看过这些资料之后,我将fluctuation分成下列 5 个模块:
初始化权重
将输入和权重相乘之后再求和
比较上述结果和阈值,计算输出(1 或 0)
更新权重
重复
接下来他们详细叙述每一个模块的内容。
1. 初始化权重
首先,他们要初始化权重向量。
权重数量要和特征数量相同。假设他们有三个特征,权重向量如下图所示。权重向量一般会初始化为 0,此例中将一直采用该初始化值。
2. 输入和权重相乘再求和
接下来,我们就要将输入和权重相乘,再对其求和。为了更易于理解,我给第一行中的权重及其对应特征涂上了颜色。
在他们将特征和权重相乘之后,对乘积求和。一般将其称为点积。
最后结果是 0,此时用「f」表示这个暂时的结果。
3. 和阈值比较
计算出点积后,他们要将它和阈值展开比较。我将阈值定为 0,你可以用这个阈值,也可以试一下其他值。
由于之前计算出的点积「f」为 0,不比阈值 0 大,因此估计值也等于 0。
将估计值标记为「y hat」,y hat 的下标 0 对应的是第一行。当然你也可以用 1 表示第一行,这无关紧要,我选择从 0 已经开始。
如果将这个结果和真值比较的话,可以看出他们当前的权重没有正确地预测出真实的输出。
由于他们的预测错了,因此要更新权重,这就要展开下一步了。
4. 更新权重
他们要用到下面的等式:
基本上思想是在迭代「n」时调整当前权重,这样他们将在下一次迭代「n+1」时得到新权重。
为了调整权重,他们需要设定「自学率」,用希腊字母「eta(η)」标记。我将自学率设为 0.1,当然就像阈值一样,你也可以用相同的数值。
目前本讲义主要如是说了:
现在他们要继续计算迭代 n=2 时的新权重了。
他们成功顺利完成了fluctuation算法的第一次迭代。
5. 重复
由于他们的演算法没能计算出正确的输出,因此还要继续。
一般需要展开大量的迭代。遍历数据集中的每一行,每一次迭代都要更新权重。一般将完整遍历一次数据集称为一个「epoch」。
他们的数据集有 3 行,因此如果要顺利完成 1 个 epoch 需要经历 3 次迭代。他们也可以设置迭代总数或 epoch 数来执行演算法,比如说指定 30 次迭代(或 10 个 epoch)。与阈值和自学率一样,epoch 也是可以随意使用的参数。
在下一次迭代中,他们将使用第二行特征。
此处不再重复计算操作过程,下图给出了下一个点积的计算:
接着就可以比较该点积和阈值来计算新的估计值、更新权重,然后再继续。如果他们的数据是线性可分的,那么fluctuation最后将会收敛。
从单纯的范例已经开始
他们已经将演算法还原成块了,接下来就可以已经开始用代码同时实现它了。
单纯起见,我一般会以非常小的「玩具数据集」已经开始。对这类问题而言,有一个很好的小型线性可分数据集,它就是与非门(NAND gate)。这是数字电路中一种常见的逻辑门。
由于这个数据集很小,他们可以手动将其输入到 Python 中。我添加了一列值为 1 的虚拟特征(dummy feature)「x0」,这样模型就可以计算偏置项了。你可以将偏置项视为可以促使模型正确分类的截距项。
下列是输入数据的代码:
# Importing libraries
# NAND Gate
# Note: x0 is a dummy variableforthe bias term
# x0 x1 x2
x = [[1., 0., 0.],
[1., 0., 1.],
[1., 1., 0.],
[1., 1., 1.]]
y =[1.,
1.,
1.,
0.]与前面的章节一样,我将逐步顺利完成演算法、编写代码并对其展开测试。
1. 初始化权重
第一步是初始化权重。
# Initialize the weights
import numpy asnp
w = np.zeros(len(x[0]))
Out:
[ 0. 0. 0.]注意权重向量的长度要和特征长度相匹配。以 NAND 门为例,它的长度是 3。
2. 将权重和输入相乘并对其求和
他们可以用 Numpy 轻松执行该运算,要用的方式是 .dot()。
从权重向量和第一行特征的点积已经开始。
# Dot Product
f = np.dot(w, x[0])
print f
Out:
0.0如他们所料,结果是 0。为了与前面的笔记保持连贯性,设点积为变量「f」。
3. 与阈值相比较
为了与前文保持连贯,将阈值「z」设为 0。若点积「f」大于 0,则预测值为 1,否则,预测值为 0。将预测值设为变量 yhat。
# ActivationFunctionz = 0.0iff > z:
yhat = 1.else:
yhat = 0.print yhat
Out:
0.0正如他们所料,预测值是 0。
你可能注意到了在上文代码的注释中,这一步被称为「激活函数」。这是对这部分内容的更正式的描述。
从 NAND 输出的第一行可以看到实际值是 1。由于预测值是错的,因此需要继续更新权重。
4. 更新权重
现在已经做出了预测,他们准备更新权重。
# Update the weights
eta = 0.1w[0] = w[0] + eta*(y[0] – yhat)*x[0][0]
w[1] = w[1] + eta*(y[0] – yhat)*x[0][1]
w[2] = w[2] + eta*(y[0] – yhat)*x[0][2]
print w
Out:
[ 0.1 0. 0.]
要像前文那样设置自学率。为与前文保持一致,将自学率 η 的值设为 0.1。为了便于阅读,我将对每次权重的更新展开硬编码。
权重更新顺利完成。
5. 重复
现在他们顺利完成了每一个关键步骤,接下来就可以把它们组合在一起了。
他们尚未讨论的最后一步是损失函数,他们需要将其最小化,它在本例中是误差项平方和。
他们要用它来计算误差,然后看模型的性能。
把它们都放在一起,就是完整的函数:
import numpy asnp
# Perceptron functiondef perceptron(x, y, z, eta, t):Input Parameters:
x: data set of input features
y: actual outputs
z: activation function threshold
eta: learning rate
t: number of iterations
# initializing the weights w = np.zeros(len(x[0]))
n = 0 # initializing additional parameters to compute sum-of-squared errors yhat_vec = np.ones(len(y)) # vector for predictions errors = np.ones(len(y)) # vector for errors (actual – predictions) J = [] # vector for the SSE cost function while n < t: for i in xrange(0, len(x)): # dot product f = np.dot(x[i], w) # activation function if f >= z: yhat = 1. else:
yhat = 0.yhat_vec[i] = yhat
# updating the weights for j in xrange(0, len(w)):
w[j] = w[j] + eta*(y[i]-yhat)*x[i][j]
n += 1 # computing the sum-of-squared errors for i inxrange(0,len(y)):
errors[i] = (y[i]-yhat_vec[i])**2 J.append(0.5*np.sum(errors))
returnw, J
现在已经编写了完整的fluctuation代码,接着是运行代码:
# x0 x1 x2x = [[1., 0., 0.],
[1., 0., 1.],
[1., 1., 0.],
[1., 1., 1.]]
y =[1.,
1.,
1.,
0.]
z = 0.0eta = 0.1t = 50print “The weights are:”print perceptron(x, y, z, eta, t)[0]
print “The errors are:”printperceptron(x, y, z, eta, t)[0]
Out:
The weights are:
[ 0.2 -0.2 -0.1]
The errors are:
[0.5, 1.5, 1.5, 1.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
他们可以看到,第 6 次迭代时误差趋近于 0,且在剩余迭代中误差一直是 0。当误差趋近于 0 并保持为 0 时,模型就收敛了。这告诉他们模型已经正确「自学」了适当的权重。
下一部分,他们将用计算好的权重在更大的数据集上展开预测。
用可靠的同时实现展开校正
到目前为止,我们已经找出了相同的自学天然资源、手动顺利完成了演算法,并用单纯的范例测试了演算法。
现在要用可靠的同时实现和他们的模型展开比较了。他们使用的是 scikit-learn 中的fluctuation(http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Perceptron.html)。
他们将按照下列几步展开比较:
导入数据
将数据分割为训练集和测试集
训练fluctuation
测试fluctuation
和 scikit-learn fluctuation展开比较
1. 导入数据
首先导入数据。你可以在这里(https://github.com/dataoptimal/posts/blob/master/algorithms from scratch/dataset.csv)得到数据集的副本。这是我创建的线性可分数据集,确保fluctuation可以起作用。为了确认,他们还将数据绘制成图。
从图中很容易看出来,他们可以用一条直线将数据分开。
import pandas aspd
import numpy asnp
import matplotlib.pyplot asplt
df = pd.read_csv(“dataset.csv”)
plt.scatter(df.values[:,1], df.values[:,2], c = df[3], alpha=0.8)
text
在继续之前,我先解释一下绘图的代码。我用 Pandas 导入 csv,它可以自动将数据放入 DataFrame 中。为了绘制数据,我要将值从 DataFrame 中取出来,因此我用了 .values 方式。特征在第一列和第二列,因此我在散点图函数中用了这些特征。第 0 列是值为 1 的虚拟特征,这样就能计算截距。这与上一节中的 NAND 门操作相似。最后,在散点图函数中令 c = df[3], alpha = 0.8 为两个类着色。输出是第三列数据(0 或 1),所以我告诉函数用列「3」给这两个类着色。
你可以在此处(https://matplotlib.org/api/_as_gen/matplotlib.pyplot.scatter.html)找到更多关于 Matplotlib 散点图函数的信息。
2. 将数据分割成训练集/测试集
现在他们已经确定数据可线性分割,那么是时候分割数据了。
在与测试集相同的数据集上训练模型是很好的做法,这有助于避免过拟合。还有相同的方式,但是单纯起见,我要用一个训练集和一个测试集。首先打乱数据。
df = df.values
np.random.seed(5)
np.random.shuffle(df)先将数据从 DataFrame 变为 numpy 数组。这样就可以更容易地使用 numpy 函数了,比如说 .shuffle。为了结果的可重复性,我设置了随机种子 (5)。顺利完成后,我试着改变随机种子,并观察结果会产生怎样的变化。接下来,我将 70% 的数据分为训练集,将 30% 的数据作为测试集。
train = df[0:int(0.7*len(df))]
test = df[int(0.7*len(df)):int(len(df))]
最后一步是分离训练集和测试集的特征和输出。
x_train = train[:, 0:3]
y_train = train[:, 3]
x_test = test[:, 0:3]
y_test = test[:,3]
我在这个范例中将 70% 的数据作为训练集,将 30% 的数据作为测试集,你们可以研究 k 折交叉校正等其他方式。
3. 训练fluctuation
他们可以重复使用之前的章节中构建的代码。
def perceptron_train(x, y, z, eta, t):Input Parameters:
x: data set of input features
y: actual outputs
z: activation function threshold
eta: learning rate
t: number of iterations
# initializing the weightsw = np.zeros(len(x[0]))
n = 0 # initializing additional parameters to compute sum-of-squared errorsyhat_vec = np.ones(len(y))# vector for predictions errors = np.ones(len(y)) # vector for errors (actual – predictions) J = [] # vector for the SSE cost function while n < t: for i in xrange(0, len(x)): # dot product f = np.dot(x[i], w) # activation function if f >= z: yhat = 1. else:
yhat = 0.yhat_vec[i] = yhat
# updating the weights for j in xrange(0, len(w)):
w[j] = w[j] + eta*(y[i]-yhat)*x[i][j]
n += 1 # computing the sum-of-squared errors for i in xrange(0,len(y)):
errors[i] = (y[i]-yhat_vec[i])**2 J.append(0.5*np.sum(errors))
returnw, J
z = 0.0eta = 0.1t = 50perceptron_train(x_train, y_train, z, eta, t)
接下来看权重和误差项平方和。
w = perceptron_train(x_train, y_train, z, eta, t)[0]
J = perceptron_train(x_train, y_train, z, eta, t)[1]
printw
printJ
Out:
[-0.5 -0.29850122 0.35054929]
[4.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
现在权重对他们来说意义不大了,但是他们在测试fluctuation时还要再使用这些数值,和用这些权重比较他们的模型和 scikit-learn 的模型。
根据误差项平方和可以看出,fluctuation已经收敛了,这是他们预料中的结果,因为数据是线性可分的。
4. 测试fluctuation
现在是时候测试fluctuation了。他们要建立一个小的 perceptron_test 函数来测试模型。与前文类似,这个函数取他们之前用 perceptron_train 函数和特征计算出的权重的点积和激活函数展开预测。之前唯一没见过的只有 accuracy_score,这是 scikit-learn 中的评估指标函数。
将所有的这些放在一起,代码如下:
fromsklearn.metricsimportaccuracy_score
w = perceptron_train(x_train, y_train, z, eta, t)[0]
def perceptron_test(x, w, z, eta, t):y_pred = []
for i in xrange(0, len(x-1)):
f = np.dot(x[i], w)
# activation function iff > z:
yhat =1 else:
yhat = 0y_pred.append(yhat)
returny_pred
y_pred = perceptron_test(x_test, w, z, eta, t)
print “The accuracy score is:”print accuracy_score(y_test, y_pred)得分为 1.0 表示他们的模型在所有的测试数据上都做出了正确的预测。因为数据集明显是可分的,所以结果正如他们所料。
5. 和 scikit-learn fluctuation展开比较
最后一步是将他们的fluctuation和 scikit-learn 的fluctuation展开比较。下面的代码是 scikit-learn fluctuation的代码:
from sklearn.linear_model importPerceptron
# training the sklearn Perceptronclf = Perceptron(random_state=None, eta0=0.1, shuffle=False, fit_intercept=False)
clf.fit(x_train, y_train)
y_predict = clf.predict(x_test)
现在他们已经训练了模型,接下来要比较这个模型的权重和他们的模型计算出来的权重。
Out:
sklearn weights:
[-0.5 -0.29850122 0.35054929]
my perceptron weights:
[-0.5 -0.29850122 0.35054929]
scikit-learn 模型中的权重和他们模型的权重完全相同。这意味着他们的模型可以正确地工作,这是个好消息。
在结束之前还有一些小问题。在 scikit-learn 模型中,他们将随机状态设置为「None」所以没有打乱数据。这是因为他们已经设置了随机种子,所以已经打乱过数据,不用再做一次。还需要将自学率 eta0 设置为 0.1,和他们的模型相同。最后一点是截距。因为他们已经设置了值为 1 的虚拟特征列,因此模型可以自动拟合截距,所以不必在 scikit-learn fluctuation中打开它。
这些看似都是小细节,但是如果不设置它们的话,他们的模型就无法重复得到相同的结果。这是重点。在使用模型之前,阅读文档并介绍相同的设置有甚么作用非常重要。
写出你的操作过程
这是该操作过程的最后一步,可能也是最重要的一步。
你刚刚经历了自学、做笔记、Cubzac写演算法和用可靠同时实现展开比较的流程。不要浪费这些努力!
写出操作过程原因有二:
你要更深刻地理解这个操作过程,因为你还要将你学到的东西教给别人。
你要向潜在雇主展示这个操作过程。
从电脑自学库中同时实现演算法是一回事,Cubzac同时实现演算法是另一回事,它会给人留下深刻印象。
GitHub 个人资料是展示你所做工作的一种很好的方式。
总结
责任编辑如是说了如何从零已经开始同时实现fluctuation。这是一种在更深层次上自学演算法的好方式,而你还可以自己同时实现它。你在大多数情况下用的都是可靠的同时实现,但是如果你真的想要更深入地介绍另一面出现了甚么,从头同时实现演算法是很好的练习。
原文链接:https://www.dataoptimal.com/machine-learning-from-scratch/
责任编辑为电脑之心校对,。
✄————————————————
加入机器之心(全职记者 / 实习生):[email protected]
投稿或寻求报道:content@jiqizhixin.com
广告 & 商务合作:[email protected]