提起笔来写这篇博客,忽然有点愧疚和尴尬。愧疚的是,工做琐事多,加之懒癌严重,致使这个系列一直没有更新,向关注该系列的同窗们道个歉。尴尬的是,按理说,机器学习介绍与算法一览应该放在最前面写,详细的应用建议应该在讲完机器学习经常使用算法以后写,忽然莫名奇妙在中间插播这么一篇,好像有点打乱主线。
老话说『亡羊补牢,为时未晚』,前面开头忘讲的东西,咱在这块儿补上。咱们先带着你们过一遍传统机器学习算法,基本思想和用途。把问题解决思路和方法应用建议提早到这里的想法也很简单,但愿能提早给你们一些小建议,对于某些容易出错的地方也先给你们打个预防针,这样在理解后续相应机器学习算法以后,使用起来也有必定的章法。html
按照不一样的分类标准,能够把机器学习的算法作不一样的分类。python
咱们先从机器学习问题自己分类的角度来看,咱们能够分红下列类型的算法:git
机器学习中有一大部分的问题属于『监督学习』
的范畴,简单口语化地说明,这类问题中,给定的训练样本中,每一个样本的输入xx都对应一个肯定的结果yy,咱们须要训练出一个模型(数学上看是一个x→yx→y的映射关系ff),在未知的样本x′x′给定后,咱们能对结果y′y′作出预测。算法
这里的预测结果若是是离散值(不少时候是类别类型,好比邮件分类问题中的垃圾邮件/普通邮件,好比用户会/不会购买某商品),那么咱们把它叫作分类问题(classification problem);若是预测结果是连续值(好比房价,股票价格等等),那么咱们把它叫作回归问题(regression problem)。markdown
有一系列的机器学习算法是用以解决监督学习问题的,好比最经典的用于分类问题的朴素贝叶斯、逻辑回归、支持向量机等等;好比说用于回归问题的线性回归等等。网络
有另一类问题,给咱们的样本并无给出『标签/标准答案』,就是一系列的样本。而咱们须要作的事情是,在一些样本中抽取出通用的规则。这叫作『无监督学习』
。包括关联规则和聚类算法在内的一系列机器学习算法都属于这个范畴。数据结构
这类问题给出的训练数据,有一部分有标签,有一部分没有标签。咱们想学习出数据组织结构的同时,也能作相应的预测。此类问题相对应的机器学习算法有自训练(Self-Training)、直推学习(Transductive Learning)、生成式模型(Generative Model)等。app
整体说来,最多见是前两类问题,而对应前两类问题的一些机器学习算法以下:dom
咱们也能够从算法的共性(好比功能,运做方式)角度对机器学习算法分类。下面咱们根据算法的共性去对它们归个类。不过须要注意的是,咱们下面的归类方法可能对分类和回归有比较强的倾向性,而这两类问题也是最常遇到的。机器学习
scikit-learn做为一个丰富的python机器学习库,实现了绝大多数机器学习的算法,有至关多的人在使用,因而我这里很无耻地把machine learning cheat sheet for sklearn搬过来了,原文能够看这里。哈哈,既然讲机器学习,咱们就用机器学习的语言来解释一下,这是针对实际应用场景的各类条件限制,对scikit-learn里完成的算法构建的一颗决策树,每一组条件都是对应一条路径,能找到相对较为合适的一些解决方法,具体以下:
首先样本量若是很是少的话,其实全部的机器学习算法都没有办法从里面『学到』通用的规则和模式,so多弄点数据是王道。而后根据问题是有/无监督学习和连续值/离散值预测,分红了分类
、聚类
、回归
和维度约减
四个方法类,每一个类里根据具体状况的不一样,又有不一样的处理方法。
上面带着代价蜻蜓点水过了一遍机器学习的若干算法,下面咱们试着总结总结在拿到一个实际问题的时候,若是着手使用机器学习算法去解决问题,其中的一些注意点以及核心思路。主要包括如下内容:
多说一句,这里写的这个小教程,主要是做为一个通用的建议和指导方案,你不必定要严格按照这个流程解决机器学习问题。
咱们先使用scikit-learn的make_classification函数来生产一份分类数据,而后模拟一下拿到实际数据后咱们须要作的事情。
#numpy科学计算工具箱 import numpy as np #使用make_classification构造1000个样本,每一个样本有20个feature from sklearn.datasets import make_classification X, y = make_classification(1000, n_features=20, n_informative=2, n_redundant=2, n_classes=2, random_state=0) #存为dataframe格式 from pandas import DataFrame df = DataFrame(np.hstack((X, y[:, None])),columns = range(20) + ["class"])
咱们生成了一份包含1000个分类数据样本的数据集,每一个样本有20个数值特征。同时咱们把数据存储至pandas中的DataFrame
数据结构中。咱们取前几行的数据看一眼:
不幸的是,肉眼看数据,尤为是维度稍微高点的时候,颇有可能看花了也看不出看不出任何线索。幸运的是,咱们对于图像的理解力,比数字好太多,而又有至关多的工具能够帮助咱们『可视化』数据分布。
咱们在处理任何数据相关的问题时,了解数据都是颇有必要的,而可视化能够帮助咱们更好地直观理解数据的分布和特性
数据的可视化有不少工具包能够用,好比下面咱们用来作数据可视化的工具包Seaborn。最简单的可视化就是数据散列分布图和柱状图,这个能够用Seanborn的pairplot
来完成。如下图中2种颜色表示2种不一样的类,由于20维的可视化没有办法在平面表示,咱们取出了一部分维度,两两组成pair看数据在这2个维度平面上的分布情况,代码和结果以下:
import matplotlib.pyplot as plt import seaborn as sns #使用pairplot去看不一样特征维度pair下数据的空间分布情况 _ = sns.pairplot(df[:50], vars=[8, 11, 12, 14, 19], hue="class", size=1.5) plt.show()
咱们从散列图和柱状图上能够看出,确实有些维度的特征相对其余维度,有更好的区分度,好比第11维和14维看起来颇有区分度。这两个维度上看,数据点是近似线性可分的。而12维和19维彷佛呈现出了很高的负相关性。接下来咱们用Seanborn中的corrplot
来计算计算各维度特征之间(以及最后的类别)的相关性。代码和结果图以下:
import matplotlib.pyplot as plt plt.figure(figsize=(12, 10)) _ = sns.corrplot(df, annot=False) plt.show()
相关性图很好地印证了咱们以前的想法,能够看到第11维特征和第14维特征和类别有极强的相关性,同时它们俩之间也有极高的相关性。而第12维特征和第19维特征却呈现出极强的负相关性。强相关的特征其实包含了一些冗余的特征,而除掉上图中颜色较深的特征,其他特征包含的信息量就没有这么大了,它们和最后的类别相关度不高,甚至各自之间也没什么先惯性。
插一句,这里的维度只有20,因此这个相关度计算并不费太大力气,然而实际情形中,你彻底有可能有远高于这个数字的特征维度,同时样本量也可能多不少,那种情形下咱们可能要先作一些处理,再来实现可视化了。别着急,一下子咱们会讲到。
数据的状况咱们大体看了一眼,肯定一些特征维度以后,咱们能够考虑先选用机器学习算法作一个baseline的系统出来了。这里咱们继续参照上面提到过的机器学习算法使用图谱。
咱们只有1000个数据样本,是分类问题,同时是一个有监督学习,所以咱们根据图谱里教的方法,使用LinearSVC
(support vector classification with linear kernel)试试。注意,LinearSVC
须要选择正则化方法以缓解过拟合问题;咱们这里选择使用最多的L2正则化,并把惩罚系数C设为10。咱们改写一下sklearn中的学习曲线绘制函数,画出训练集和交叉验证集上的得分:
from sklearn.svm import LinearSVC from sklearn.learning_curve import learning_curve #绘制学习曲线,以肯定模型的情况 def plot_learning_curve(estimator, title, X, y, ylim=None, cv=None, train_sizes=np.linspace(.1, 1.0, 5)): """ 画出data在某模型上的learning curve. 参数解释 ---------- estimator : 你用的分类器。 title : 表格的标题。 X : 输入的feature,numpy类型 y : 输入的target vector ylim : tuple格式的(ymin, ymax), 设定图像中纵坐标的最低点和最高点 cv : 作cross-validation的时候,数据分红的份数,其中一份做为cv集,其他n-1份做为training(默认为3份) """ plt.figure() train_sizes, train_scores, test_scores = learning_curve( estimator, X, y, cv=5, n_jobs=1, train_sizes=train_sizes) train_scores_mean = np.mean(train_scores, axis=1) train_scores_std = np.std(train_scores, axis=1) test_scores_mean = np.mean(test_scores, axis=1) test_scores_std = np.std(test_scores, axis=1) plt.fill_between(train_sizes, train_scores_mean - train_scores_std, train_scores_mean + train_scores_std, alpha=0.1, color="r") plt.fill_between(train_sizes, test_scores_mean - test_scores_std, test_scores_mean + test_scores_std, alpha=0.1, color="g") plt.plot(train_sizes, train_scores_mean, 'o-', color="r", label="Training score") plt.plot(train_sizes, test_scores_mean, 'o-', color="g", label="Cross-validation score") plt.xlabel("Training examples") plt.ylabel("Score") plt.legend(loc="best") plt.grid("on") if ylim: plt.ylim(ylim) plt.title(title) plt.show() #少样本的状况状况下绘出学习曲线 plot_learning_curve(LinearSVC(C=10.0), "LinearSVC(C=10.0)", X, y, ylim=(0.8, 1.01), train_sizes=np.linspace(.05, 0.2, 5))
这幅图上,咱们发现随着样本量的增长,训练集上的得分有必定程度的降低,交叉验证集上的得分有必定程度的上升,但整体说来,二者之间有很大的差距,训练集上的准确度远高于交叉验证集。这其实意味着咱们的模型处于过拟合的状态,也即模型太努力地刻画训练集,一不当心把不少噪声的分布也拟合上了,致使在新数据上的泛化能力变差了。
问题来了,过拟合咋办?
针对过拟合,有几种办法能够处理:
这个比较好理解吧,过拟合的主要缘由是模型太努力地去记住训练样本的分布情况,而加大样本量,可使得训练集的分布更加具有普适性,噪声对总体的影响降低。恩,咱们提升点样本量试试:
#增大一些样本量 plot_learning_curve(LinearSVC(C=10.0), "LinearSVC(C=10.0)", X, y, ylim=(0.8, 1.1), train_sizes=np.linspace(.1, 1.0, 5))
是否是发现问题好了不少?随着咱们增大训练样本量,咱们发现训练集和交叉验证集上的得分差距在减小,最后它们已经很是接近了。增大样本量,最直接的方法固然是想办法去采集相同场景下的新数据,若是实在作不到,也能够试试在已有数据的基础上作一些人工的处理生成新数据(好比图像识别中,咱们可能能够对图片作镜像变换、旋转等等),固然,这样作必定要谨慎,强烈建议想办法采集真实数据。
好比在这个例子中,咱们以前的数据可视化和分析的结果代表,第11和14维特征包含的信息对识别类别很是有用,咱们能够只用它们。
plot_learning_curve(LinearSVC(C=10.0), "LinearSVC(C=10.0) Features: 11&14", X[:, [11, 14]], y, ylim=(0.8, 1.0), train_sizes=np.linspace(.05, 0.2, 5))
从上图上能够看出,过拟合问题也获得必定程度的缓解。不过咱们这是本身观察后,手动选出11和14维特征。那能不能自动进行特征组合和选择呢,其实咱们固然能够遍历特征的组合样式,而后再进行特征选择(前提依旧是这里特征的维度不高,若是高的话,遍历全部的组合是一个很是很是很是耗时的过程!!):
from sklearn.pipeline import Pipeline from sklearn.feature_selection import SelectKBest, f_classif # SelectKBest(f_classif, k=2) 会根据Anova F-value选出 最好的k=2个特征 plot_learning_curve(Pipeline([("fs", SelectKBest(f_classif, k=2)), # select two features ("svc", LinearSVC(C=10.0))]), "SelectKBest(f_classif, k=2) + LinearSVC(C=10.0)", X, y, ylim=(0.8, 1.0), train_sizes=np.linspace(.05, 0.2, 5))
若是你本身跑一下程序,会发如今咱们本身手造的这份数据集上,这个特征筛选的过程超级顺利,但依旧像咱们以前提过的同样,这是由于特征的维度不过高。
从另一个角度看,咱们之因此作特征选择,是想下降模型的复杂度,而更不容易刻画到噪声数据的分布。从这个角度出发,咱们还能够有(1)多项式你和模型中下降多项式次数 (2)神经网络中减小神经网络的层数和每层的结点数 (c)SVM中增长RBF-kernel的bandwidth等方式来下降模型的复杂度。
话说回来,即便以上提到的办法下降模型复杂度后,好像能在必定程度上缓解过拟合,可是咱们通常仍是不建议一遇到过拟合,就用这些方法处理,优先用下面的方法:
plot_learning_curve(LinearSVC(C=0.1), "LinearSVC(C=0.1)", X, y, ylim=(0.8, 1.0), train_sizes=np.linspace(.05, 0.2, 5))
调整正则化系数后,发现确实过拟合现象有必定程度的缓解,但依旧是那个问题,咱们如今的系数是本身敲定的,有没有办法能够自动选择最佳的这个参数呢?能够。咱们能够在交叉验证集上作grid-search查找最好的正则化系数(对于大数据样本,咱们依旧须要考虑时间问题,这个过程可能会比较慢):
from sklearn.grid_search import GridSearchCV estm = GridSearchCV(LinearSVC(), param_grid={"C": [0.001, 0.01, 0.1, 1.0, 10.0]}) plot_learning_curve(estm, "LinearSVC(C=AUTO)", X, y, ylim=(0.8, 1.0), train_sizes=np.linspace(.05, 0.2, 5)) print "Chosen parameter on 100 datapoints: %s" % estm.fit(X[:500], y[:500]).best_params_
在500个点获得的结果是:{‘C’: 0.01}
使用新的C参数,咱们再看看学习曲线:
对于特征选择的部分,我打算多说几句,咱们刚才看过了用sklearn.feature_selection中的SelectKBest来选择特征的过程,也提到了在高维特征的状况下,这个过程可能会很是很是慢。那咱们有别的办法能够进行特征选择吗?好比说,咱们的分类器本身可否甄别那些特征是对最后的结果有益的?这里有个实际工做中用到的小技巧。
咱们知道:
那基于这个理论,咱们能够把SVC中的正则化替换成l1正则化,让其自动甄别哪些特征应该留下权重。
plot_learning_curve(LinearSVC(C=0.1, penalty='l1', dual=False), "LinearSVC(C=0.1, penalty='l1')", X, y, ylim=(0.8, 1.0), train_sizes=np.linspace(.05, 0.2, 5))
好了,咱们一块儿来看看最后特征得到的权重:
estm = LinearSVC(C=0.1, penalty='l1', dual=False) estm.fit(X[:450], y[:450]) # 用450个点来训练 print "Coefficients learned: %s" % est.coef_ print "Non-zero coefficients: %s" % np.nonzero(estm.coef_)[1]
获得结果:
Coefficients learned: [[ 0. 0. 0. 0. 0. 0.01857999 0. 0. 0. 0.004135 0. 1.05241369 0.01971419 0. 0. 0. 0. -0.05665314 0.14106505 0. ]] Non-zero coefficients: [5 9 11 12 17 18]
你看,5 9 11 12 17 18这些维度的特征得到了权重,而第11维权重最大,也说明了它影响程度最大。
咱们再随机生成一份数据[1000*20]的数据(可是分布和以前有变化),从新使用LinearSVC来作分类。
#构造一份环形数据 from sklearn.datasets import make_circles X, y = make_circles(n_samples=1000, random_state=2) #绘出学习曲线 plot_learning_curve(LinearSVC(C=0.25),"LinearSVC(C=0.25)",X, y, ylim=(0.5, 1.0),train_sizes=np.linspace(.1, 1.0, 5))
简直烂出翔了有木有,二分类问题,咱们作随机猜想,准确率都有0.5,这比随机猜想都高不了多少!!!怎么办?
不要盲目动手收集更多资料,或者调整正则化参数。咱们从学习曲线上其实能够看出来,训练集上的准确度和交叉验证集上的准确度都很低,这其实就对应了咱们说的『欠拟合』状态。别急,咱们回到咱们的数据,仍是可视化看看:
f = DataFrame(np.hstack((X, y[:, None])), columns = range(2) + ["class"]) _ = sns.pairplot(df, vars=[0, 1], hue="class", size=3.5)
你发现什么了,数据根本就没办法线性分割!!!,因此你再找更多的数据,或者调整正则化参数,都是无济于事的!!!
那咱们又怎么解决欠拟合问题呢?一般有下面一些方法:
# 加入原始特征的平方项做为新特征 X_extra = np.hstack((X, X[:, [0]]**2 + X[:, [1]]**2)) plot_learning_curve(LinearSVC(C=0.25), "LinearSVC(C=0.25) + distance feature", X_extra, y, ylim=(0.5, 1.0), train_sizes=np.linspace(.1, 1.0, 5))
from sklearn.svm import SVC # note: we use the original X without the extra feature plot_learning_curve(SVC(C=2.5, kernel="rbf", gamma=1.0), "SVC(C=2.5, kernel='rbf', gamma=1.0)",X, y, ylim=(0.5, 1.0), train_sizes=np.linspace(.1, 1.0, 5))
你看,效果依旧很赞。
咱们在小样本的toy dataset上,怎么捣鼓都有好的方法。可是当数据量和特征样本空间膨胀很是厉害时,不少东西就没有那么好使了,至少是一个很耗时的过程。举个例子说,咱们如今从新生成一份数据集,可是此次,咱们生成更多的数据,更高的特征维度,而分类的类别也提升到5。
在上面提到的那样一份数据上,咱们用LinearSVC可能就会有点慢了,咱们注意到机器学习算法使用图谱推荐咱们使用SGDClassifier
。其实本质上说,这个模型也是一个线性核函数的模型,不一样的地方是,它使用了随机梯度降低作训练,因此每次并无使用所有的样本,收敛速度会快不少。再多提一点,SGDClassifier
对于特征的幅度很是敏感,也就是说,咱们在把数据灌给它以前,应该先对特征作幅度调整,固然,用sklearn的StandardScaler
能够很方便地完成这一点。
SGDClassifier
每次只使用一部分(mini-batch)作训练,在这种状况下,咱们使用交叉验证(cross-validation)并非很合适,咱们会使用相对应的progressive validation:简单解释一下,estimator每次只会拿下一个待训练batch在本次作评估,而后训练完以后,再在这个batch上作一次评估,看看是否有优化。
#生成大样本,高纬度特征数据 X, y = make_classification(200000, n_features=200, n_informative=25, n_redundant=0, n_classes=10, class_sep=2, random_state=0) #用SGDClassifier作训练,并画出batch在训练先后的得分差 from sklearn.linear_model import SGDClassifier est = SGDClassifier(penalty="l2", alpha=0.001) progressive_validation_score = [] train_score = [] for datapoint in range(0, 199000, 1000): X_batch = X[datapoint:datapoint+1000] y_batch = y[datapoint:datapoint+1000] if datapoint > 0: progressive_validation_score.append(est.score(X_batch, y_batch)) est.partial_fit(X_batch, y_batch, classes=range(10)) if datapoint > 0: train_score.append(est.score(X_batch, y_batch)) plt.plot(train_score, label="train score") plt.plot(progressive_validation_score, label="progressive validation score") plt.xlabel("Mini-batch") plt.ylabel("Score") plt.legend(loc='best') plt.show()
获得以下的结果:
从这个图上的得分,咱们能够看出在50个mini-batch迭代以后,数据上的得分就已经变化不大了。可是好像得分都不过高,因此咱们猜想一下,这个时候咱们的数据,处于欠拟合状态。咱们刚才在小样本集合上提到了,若是欠拟合,咱们可使用更复杂的模型,好比把核函数设置为非线性的,但遗憾的是像rbf核函数是没有办法和SGDClassifier
兼容的。所以咱们只能想别的办法了,好比这里,咱们能够把SGDClassifier
整个替换掉了,用多层感知神经网
来完成这个任务,咱们之因此会想到多层感知神经网
,是由于它也是一个用随机梯度降低训练的算法,同时也是一个非线性的模型。固然根据机器学习算法使用图谱,也可使用核估计(kernel-approximation)来完成这个事情。
大样本数据的可视化是一个相对比较麻烦的事情,通常状况下咱们都要用到降维的方法先处理特征。咱们找一个例子来看看,能够怎么作,好比咱们数据集取经典的『手写数字集』,首先找个方法看一眼这个图片数据集。
#直接从sklearn中load数据集 from sklearn.datasets import load_digits digits = load_digits(n_class=6) X = digits.data y = digits.target n_samples, n_features = X.shape print "Dataset consist of %d samples with %d features each" % (n_samples, n_features) # 绘制数字示意图 n_img_per_row = 20 img = np.zeros((10 * n_img_per_row, 10 * n_img_per_row)) for i in range(n_img_per_row): ix = 10 * i + 1 for j in range(n_img_per_row): iy = 10 * j + 1 img[ix:ix + 8, iy:iy + 8] = X[i * n_img_per_row + j].reshape((8, 8)) plt.imshow(img, cmap=plt.cm.binary) plt.xticks([]) plt.yticks([]) _ = plt.title('A selection from the 8*8=64-dimensional digits dataset') plt.show()
咱们总共有1083个训练样本,包含手写数字(0,1,2,3,4,5),每一个样本图片中的像素点平铺开都是64位,这个维度显然是没办法直接可视化的。下面咱们基于scikit-learn的示例教程对特征用各类方法作降维处理,再可视化。
随机投射
咱们先看看,把数据随机投射到两个维度上的结果:
#import所需的package from sklearn import (manifold, decomposition, random_projection) rp = random_projection.SparseRandomProjection(n_components=2, random_state=42) #定义绘图函数 from matplotlib import offsetbox def plot_embedding(X, title=None): x_min, x_max = np.min(X, 0), np.max(X, 0) X = (X - x_min) / (x_max - x_min) plt.figure(figsize=(10, 10)) ax = plt.subplot(111) for i in range(X.shape[0]): plt.text(X[i, 0], X[i, 1], str(digits.target[i]), color=plt.cm.Set1(y[i] / 10.), fontdict={'weight': 'bold', 'size': 12}) if hasattr(offsetbox, 'AnnotationBbox'): # only print thumbnails with matplotlib > 1.0 shown_images = np.array([[1., 1.]]) # just something big for i in range(digits.data.shape[0]): dist = np.sum((X[i] - shown_images) ** 2, 1) if np.min(dist) < 4e-3: # don't show points that are too close continue shown_images = np.r_[shown_images, [X[i]]] imagebox = offsetbox.AnnotationBbox( offsetbox.OffsetImage(digits.images[i], cmap=plt.cm.gray_r), X[i]) ax.add_artist(imagebox) plt.xticks([]), plt.yticks([]) if title is not None: plt.title(title) #记录开始时间 start_time = time.time() X_projected = rp.fit_transform(X) plot_embedding(X_projected, "Random Projection of the digits (time: %.3fs)" % (time.time() - start_time))
结果以下:
PCA降维
在维度约减/降维领域有一个很是强大的算法叫作PCA(Principal Component Analysis,主成分分析),它能将原始的绝大多数信息用维度远低于原始维度的几个主成分表示出来。PCA在咱们如今的数据集上效果还不错,咱们来看看用PCA对原始特征降维至2维后,原始样本在空间的分布情况:
from sklearn import (manifold, decomposition, random_projection) #TruncatedSVD 是 PCA的一种实现 X_pca = decomposition.TruncatedSVD(n_components=2).fit_transform(X) #记录时间 start_time = time.time() plot_embedding(X_pca,"Principal Components projection of the digits (time: %.3fs)" % (time.time() - start_time))
获得的结果以下:
咱们能够看出,效果还不错,不一样的手写数字在2维平面上,显示出了区域集中性。即便它们之间有必定的重叠区域。
若是咱们用一些非线性的变换来作降维操做,从原始的64维降到2维空间,效果更好,好比这里咱们用到一个技术叫作t-SNE,sklearn的manifold对其进行了实现:
from sklearn import (manifold, decomposition, random_projection) #降维 tsne = manifold.TSNE(n_components=2, init='pca', random_state=0) start_time = time.time() X_tsne = tsne.fit_transform(X) #绘图 plot_embedding(X_tsne, "t-SNE embedding of the digits (time: %.3fs)" % (time.time() - start_time))
咱们发现结果很是的惊人,彷佛这个非线性变换降维事后,仅仅2维的特征,就能够将原始数据的不一样类别,在平面上很好地划分开。不过t-SNE也有它的缺点,通常说来,相对于线性变换的降维,它须要更多的计算时间。也不太适合在大数据集上全集使用。
损失函数的选择对于问题的解决和优化,很是重要。咱们先来看一眼各类不一样的损失函数:
import numpy as np import matplotlib.plot as plt # 改自http://scikit-learn.org/stable/auto_examples/linear_model/plot_sgd_loss_functions.html xmin, xmax = -4, 4 xx = np.linspace(xmin, xmax, 100) plt.plot([xmin, 0, 0, xmax], [1, 1, 0, 0], 'k-', label="Zero-one loss") plt.plot(xx, np.where(xx < 1, 1 - xx, 0), 'g-', label="Hinge loss") plt.plot(xx, np.log2(1 + np.exp(-xx)), 'r-', label="Log loss") plt.plot(xx, np.exp(-xx), 'c-', label="Exponential loss") plt.plot(xx, -np.minimum(xx, 0), 'm-', label="Perceptron loss") plt.ylim((0, 8)) plt.legend(loc="upper right") plt.xlabel(r"Decision function $f(x)$") plt.ylabel("$L(y, f(x))$") plt.show()
获得结果图像以下:
不一样的损失函数有不一样的优缺点:
全文到此就结束了。先蜻蜓点水看了一遍机器学习的算法,而后给出了对应scikit-learn的『秘密武器』机器学习算法使用图谱,紧接着从了解数据(可视化)、选择机器学习算法、定位过/欠拟合及解决方法、大量极的数据可视化和损失函数优缺点与选择等方面介绍了实际机器学习问题中的一些思路和方法。本文和文章机器学习系列(3)_逻辑回归应用之Kaggle泰坦尼克之灾都说起了一些处理实际机器学习问题的思路和方法,有类似和互补之处,欢迎你们参照着看。