Welcome to scikit-learn
Installing scikit-learn
首先需要安装IPython,此时附带安装了NumPy、SciPy和matplotlib,然后使用pip install -U scikit-learn。记住,不能使用pip安装NumPy和SciPy,因为配置不恰当的话可能会导致计算慢的问题。Windows上直接安装Python(x,y),然后在Additional plugins安装scikit-learn即可。
(文档的1.2.14节,使用n_jobs>1有时会程序崩溃的原因,没看懂)
Related Projects
深度学习库:pylearn2、keras
图像处理库:scikit-image
自然语言处理库:nltk、gensim
Scikit-learn Tutorials
An introduction to machine learning with scikit-learn
看下面的一段示例代码,示范了sklearn中的一些基本用法:
from sklearn import datasets
from sklearn import svm
from sklearn.externals import joblib
digits = datasets.load_digits() #sklearn中自带了一些数据集,可用于学习sklearn的基本用法
clf = svm.SVC(gamma=0.001, C=100.) #手动设置了gamma和C参数,这是高斯核SVM分类器的参数,clf为模型的句柄
clf.fit(digits.data[:-1], digits.target[:-1]) #fit()函数表示拟合数据,即学习一个模型
joblib.dump(clf, 'filename.pkl') #使用joblib模块将模型保存到本地磁盘,将会生成多个文件,这些文件在模型加载时都是需要的,缺一不可
clf = joblib.load('filename.pkl') #使用joblib模块从本地磁盘加载模型
clf.predict(digits.data[-1:]) #predict()函数表示使用训练好的模型对数据进行预测,输出离散值0或1,predict_proba()输出预测概率值
clf.set_params(kernel='linear').fit(digits.data[:-1], digits.target[:-1]) #改变分类器的参数并重新训练
clf.predict(digits.data[-1:])
A tutorial on statistical-learning for scientific data processing
transformer也有fit()方法。The curse of dimensionality这节没看懂。
Shrinkage
Shrinkage(p86)在《机器学习实战》p146被翻译为缩减,缩减的含义是使用l2正则项将一些系数缩减成很小的值。仅使用误差函数(如最小平方误差)作为代价函数就没有使用缩减方法,使用误差项和正则项构成代价函数就使用了缩减方法。
常用的正则项是ridge和lasso,即系数的l2范数和l1范数。正则项是如何起到缩减作用的呢?如果没有正则项,仅有误差项,优化过程仅使得误差最小即可,不管系数是大还是小。如果最小化代价函数时同时考虑了误差项和正则项,优化过程就会使得误差和系数范数都尽量小,由于系数的范数约束了系数的大小,使系数不会太大,甚至某些直接为零,因此起到了缩减作用。
ridge和lasso两种正则项有什么区别呢?
简单地讲,ridge可以使模型更“稳定”,lasso给模型增加了稀疏约束。以简单线性回归$y=w^TX$
为例,w的最优解有解析解$\hat{w}=(X^TX)^{-1}X^Ty$
,增加ridge正则项后,解析解变成$w=(X^TX+\lambda I)^{-1}X^Ty$
。ridge起作用的情形有两种,第一种情形是当特征比样本点还多(n>m),或者特征之间有线性相关时,X就不是满秩矩阵,$(X^TX)^{-1}$
不可求解,但是增加ridge后的解析解$(X^TX+\lambda I)^{-1}$
可以求解。第二种情形是$(X^TX)^{-1}$
有解,但是$(X^TX)$
主元上的元素很小,矩阵中某个元素的一个很小的变动,会引起$(X^TX)^{-1}$
计算结果误差很大,这种矩阵$X^TX$
称为“病态矩阵”,ridge加入了$\lambda I$
,使得矩阵病态程度降低,使模型更稳定。ridege引入了$\lambda I$
,单位矩阵对角线全是1,形象地在0构成的平面上有一条1组成的“岭”,这就是岭回归名字的由来。
ridge能使得不重要特征的系数变小,但不会变成零,lasso能使得不重要特征的系数直接变成零,使得系数成为稀疏的,lasso正则没有解析解,也不能使用梯度下降法求解,需要使用二次规划算法,sklearn.linear_model.LogisticRegression使用liblinear库求解lasso正则约束。为了使用ridge和lasso,需要对特征做归一化处理,使每维特征具有相同的重要性,如果不归一化,可能会导致优化过程收敛很慢,甚至不收敛,关于归一化的更多内容,参考知乎问答。
正则项的系数越大,偏差越大,方差越小(p87),偏差与方差的概念在《机器学习实战》p152中讲到。模型预测值与观测值之间总是会有误差的,我们一般考虑训练误差和测试误差,这两种误差有三个部分组成:模型偏差、测量误差和随机噪声,我们只能控制模型偏差的大小。偏差可简单理解为模型对训练数据的拟合程度,方差为模型的泛化能力,模型越复杂,偏差越低,方差越高。偏差是指模型预测值与样本真实值之间的差异,方差是指模型之间的差异,由于不知道样本真实值,所以偏差不可度量,但方差是可以度量的,取一个随机样本集,用某个模型去拟合,得到一组系数W,再取另一个随机样本集,用同样的模型去拟合,得到另一组系数K,两组系数W和K直接的差异就是模型方差的反应。增大正则项的系数将会倾向于得到一个更简单的模型,偏差会增大,方差会减小。正则项的系数的大小应使用交叉验证法进行选择,根据多次训练集和验证集划分的平均模型得分选择最佳正则项系数。
生成模型:根据样本学习数据的联合概率分布P(X,Y),然后根据联合概率分布计算后验概率P(Y|X),然后比较概率判定类别。基于贝叶斯和极大似然的概率估计方法都是生成方法。
判别模型:不学习数据的联合概率分布,直接学习一个判决边界(隐含地直接学习P(Y|X)),直接对样本进行分类。线性判别式、SVM、神经网络都是判别方法。
更多内容可参考zouxy09博客和知乎问答。
选择最佳alpha参数值的代码:
regr = linear_model.Lasso()
scores = [regr.set_params(alpha=alpha
... ).fit(diabetes_X_train, diabetes_y_train
... ).score(diabetes_X_test, diabetes_y_test)
... for alpha in alphas]
best_alpha = alphas[scores.index(max(scores))]
regr.alpha = best_alpha
regr.fit(diabetes_X_train, diabetes_y_train)
对于分类问题,线性回归不是合适的方法,因为它会给远离决策边界的数据太多的权值。这句怎么理解?
p90支持向量回归(SVR),查一下是什么东西。
p94画出正则项系数与得分的关系图,该图说明,正则项系数会在某个范围内对模型起线性提升作用,低于这个范围或高于这个范围,即使正则项系数过大或过小,模型的表现都是差不多的,所以交叉验证调正则项系数时要确保考查了合适的范围。
交叉验证调最佳正则项系数的经验:如果模型有自带CV的版本,就用自带CV的模型,自带CV的模型交叉验证的速度很快,参考sklearn文档,否则就只能使用GridSearchCV(),要慢很多。sklearn.linear_model.LassoLarsIC()不用进行交叉验证选择最佳正则项系数,该模型的最佳正则项系数有解析解。确定模型之后,下一步要确定正则项系数Cs的范围,可以先设比较粗的范围,如Cs=list(np.logspace(-10, 10, 20)),用clf.C查看最佳系数,clf.score查看每个系数对应的得分,根据得分情况再进一步缩小范围,比如下一步可设置Cs=list(np.logspace(-2, 0, 20)),直到最佳系数前后的几个值的系数的得分变化不大的时候就可以停止了,不用再进行更细范围的搜索。