机器学习中的损失函数(附python代码) Posted 2021-04-06 深度学习与计算机视觉
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机器学习中的损失函数(附python代码)相关的知识,希望对你有一定的参考价值。
本文将深入研究hinge损失、logistic损失和二分类损失背后的概念和原理,并在MATLAB上实现感知器算法,并看看如何根据损失函数来选择最佳分类器。
在本文的最后,你将知道如何使用感知器进行分类,以及每个损失函数的优缺点。
数据集
我们将使用一个包含N=200个样本点的三维数据集,该数据集最初是由Ruth Urner博士在她的一个机器学习课程作业中提出的。在下面的存储库中,你将找到两个TXT文件:fg_inputs.txt和fg_outputs.txt.
https://github.com/jaimedantas/perceptron-classification
这些文件包含输入和输出向量。使用MATLAB,我们可以在Home>import Data中导入它们。现在,让我们绘制这个数据集。
x = input_fg; % Graph % +1 plot3 (x(1 :100 ,1 ),x(1 :100 ,2 ),x(1 :100 ,3 ),'o' )hold on% -1 plot3 (x(100 :200 ,1 ),x(100 :200 ,2 ),x(100 :200 ,3 ),'o' ) xlabel('x' ) ylabel('y' ) zlabel('z' ) grid on title('FG dataset' );legend ('+1' ,'-1' ) print -depsc 3 ddataset
感知器
感知器算法是至今仍被广泛使用的最古老的机器学习算法之一,它用于不同类型数据集的线性分类,且原理非常容易理解。
你可以阅读这篇文章来详细了解它的工作原理:
https://en.wikipedia.org/wiki/Perceptron。
如果你真的想学它背后的数学原理,以下课程可能会对你有所帮助:
https://www.cs.cornell.edu/courses/cs4780/2018fa/lectures/lecturenote03.html 。
长话短说,感知器的工作方式是分析x和w的点积与其标签t的乘积的正负性。
每当h(x)小于或等于0时,我们用一个新值更新w。
现在让我们在MATLAB上实现它吧!我在MATLAB上创建了一个函数来实现感知器算法,它接收输入矩阵x和标签向量t。首先在x中添加一列1;
然后,我将x和t连接起来,原因是这样可以更容易地对数据进行无序处理。我使用MATLAB的函数randperm()来随机化数据集,然后用0初始化向量w,最后添加偏置项b,即w0,同样用b=0进行初始化。
我还跟踪算法在变量更新中对数据集运行的传递次数,在算法的最后,我对向量w进行了欧几里德归一化。算法如下所示。
function [w_normalized, updates] = perceptron (x, t) [D,n] = size (x); one = ones (D,1 ); % 加one 和 t x = [one x t]; % 随机化 random_x = x(randperm(D), :); % X 和 t 随机化 x_shuffled = random_x(:,1 :end -1 ); t_shuffled = random_x(:,end ); % 初始化 w 和 b w = [0 zeros (1 ,n)]; index = 1 ; updates = 0 ; while updates < 100 && index <= D if t_shuffled(index) * dot (x_shuffled(index,:), w) <= 0 % 更新 w w = w + t_shuffled(index) * x_shuffled(index,:); updates = updates + 1 ; % 它将用新的w再次检查所有索引 index = 1 ; else % 增加索引以检查下一个索引 index = index + 1 ; end end % 归一化 (Euclidean 范数) w_normalized = w/norm(w);end
为了运行我们的函数,我们必须在MATLAB的命令窗口中执行命令**[w, updates] = perceptron(input, output)**。
损失函数比较分析
为了计算损失,执行了感知器函数20次,每次都存储向量wi。我还在矩阵x中添加了一列1。
% -- 损失 % 执行20次 for i = 1 :20 [w_normalized, u(i )] = perceptron(input_fg, output_fg); wi{i ,1 } = w_normalized;end [D,n] = size (input_fg); one = ones (D,1 );% 加一列1 x = [one input_fg]; t = output_fg;
让我们首先计算预测值的二分类损失,并将其平均。该损失函数由下面的等式给出
% 二元损失 binary = [zeros (20 ,1 )];for j = 1 :20 for i = 1 :D k(i ) = t(i ) * dot (wi{j ,1 }, x(i ,:)); if t(i ) * dot (wi{j ,1 }, x(i ,:)) <= 0 binary_i(i ) = 1 ; else binary_i(i ) = 0 ; end binary(j ) = binary(j ) + binary_i(i ); end if j ==1 b = scatter (k, binary_i, '*' ); hold on end % 平均 binary(j ) = binary(j )/D;end
对hinge损失也做同样的处理,这一次的损失是由下式给出:
% 铰链损失 hinge = [zeros (20 ,1 )];for j = 1 :20 for i = 1 :D k(i ) = t(i ) * dot (wi{j ,1 }, x(i ,:)); hinge_i(i ) = max (0 ,1 - t(i ) * dot (wi{j ,1 }, x(i ,:))); hinge(j ) = hinge(j ) + hinge_i(i ); end if j ==1 h = scatter (k, hinge_i, '.' ); end % 平均 hinge(j ) = hinge(j )/D;end
% 逻辑损失 logistic = [zeros (20 ,1 )];for j = 1 :20 for i = 1 :D k(i ) = t(i ) * dot (wi{j ,1 }, x(i ,:)); logistic_i(i ) = log (1 + exp (-t(i ) * dot (wi{j ,1 }, x(i ,:)))); logistic(j ) = logistic(j ) + logistic_i(i ); end if j ==1 figure l = scatter (k, logistic_i); hold on end % 平均 logistic(j ) = logistic(j )/D;end
为了分析这个数据集的训练损失,我创建了compare_losses.m脚本来绘制损失。
下图的图表显示了20次运行的损失,从那里,我们可以注意到二分类损失是三者中最小的,另外,其他的损失可以显示了我们分类器更“好”。因为当我们看i=17和i=18的执行情况时,我们可以看到,虽然它们的二分类损失大致相同,但后者的hinge和logistic损失比前者小得多,这是因为其他的损失计算出错程度很大的数据点会产生非常大的hinge和logistic损失。
当我们看i=4和i=5时,可以和i=17、i=18进行比较,前者的二分类损失较小,后者的hinge和logistic损失较小。因此,从这个分析来看,i=5的分类器可能比i=4的分类器更好。这使我们得出结论,hinge和logistic损失损失与二分类损失无关,也可以说是相互独立的。
继续看上图的右图,我们可以看到,当我们对一个数据点进行错误分类时,logistic损失和hinge损失都会给我们带来巨大的损失。而当我们正确分类时,logistic损失和hinge损失都接近于零(当t⟨w,x⟩≥1时),另外,我们可以得出结论,当t⟨w,x⟩在0和1之间时,hinge损失不是零,这是因为数据点太接近对两个类进行分类的直线。
另外,当数据点分类正确但离直线太近时,hinge损失给出的值较小。同样,当数据点被错误地分类,并且数据点离直线太远时,logistic损失和hinge损失会给我们带来很大的损失值。事实上,对于t⟨w,x⟩的较大负值,两个损失都变成了平行线。
对于分类错误的数据点,logistic损失遵循hinge损失的趋势,然而,如上图右图所示,正确分类的数据点永远不会为零;类似地,对于过于接近直线的数据点,logistic损失会指定一个接近1的误差。
最后,hinge损失是二分类损失的一个上界,它比二分类损失更能证明实际的损失值。下面我们可以看到每种损失的最小损失值。
结果表明,二分类损失确实是最小的损失(i=1),然而,logistic损失和hinge损失最小的是执行18次,这突出了使用其他损失函数进行二分类的重要性。因此,给我们最小的二元损失的分类器并不总是理想的分类器。
使用MATLAB
出于好奇,我决定将我们的结果与MATLAB上的一个现成的实现进行比较,我在MATLAB上运行这个数据集
正如我们看到的,MATLAB拟合了一个误差为0.135的分类器,这与运行我们的感知器算法是一致的。重要的是要记住,在MATLAB上的比较中使用的学习算法不是感知器。我只想说明我们的感知器可以为这个数据集估计一个非常好的分类器。
结论
结论发现,与logistic损失和hinge损失不同,当我们对所有数据点进行正确分类时,二分类损失总是为0。logistic损失和hinge损失表明了预测因子的“正确程度”或“错误程度”。
因此,在选择最佳分类器时,尤其是当二分类损失不为0时,分析其他损失函数是至关重要的。
最后,我们介绍了如何在MATLAB上实现D+1维空间的感知器算法。
参考阅读
[1] Yossi Keshet. Multiclass Classification. 2014. URL: https://u.cs.biu.ac.il/~jkeshet/teaching/aml2016/multiclass.pdf
[2] Dorian Lazar. Perceptron: Explanation, Implementation and a Visual Example. 2020. URL: https: //towardsdatascience.com/perceptron-explanation-implementation-and-a-visual-example- 3c8e76b4e2d1
[3] Marina Santini. Machine Learning for Language Technology Lecture 9: Perceptron. 2014. URL: http://santini.se/teaching/ml/2014/Lecture09_Perceptron.pdf
[4] Shai Shalev-Shwartz and Ben-David. Understanding Machine Learning: From Theory to Algorithms. Cambridge University Press, 2014. DOI: 10.1017/CBO9781107298019. URL: https://www.cs.huji.ac.il /~shais/UnderstandingMachineLearning/understanding — machine — learning — theory — algorithms.pdf
[5] Kilian Weinberger. Empirical Risk Minimization — Cornell University. 2020. URL: https://www.cs.cornell.edu/courses/cs4780/2018fa/lectures/lecturenote10.html
参考链接:https://towardsdatascience.com/reasons-why-surrogate-loss-functions-are-pivotal-for-classification-in-machine-learninxxxxxxxx9
如果看到这里,说明你喜欢这篇文章,请
转发、点赞
。微信搜索「uncle_pn」,欢迎添加小编微信「 mthler」,每日朋友圈更新一篇
高质量博文
。
以上是关于机器学习中的损失函数(附python代码)的主要内容,如果未能解决你的问题,请参考以下文章
建模分析之机器学习算法(附python&R代码)
机器学习实战4:基于马尔科夫随机场的图像分割(附Python代码)
9 个鲜为人知的机器学习 Python 工具库 | 附代码示例
机器学习实战3:基于朴素贝叶斯实现单词拼写修正器(附Python代码)
机器学习:基于朴素贝叶斯实现单词拼写修正器(附Python代码)
机器学习领域必知必会的12种概率分布(附Python代码实现)