四、线性分类与回归
1 线性函数
大家知道,在二维空间内,线性函数可以表达为:
y=kx+b
或者
ax+by=0
在第一个表达式中k叫做斜率,b叫做截距(即x=0的时候,直线与y轴的交叉点)
把线性函数扩展到n维空间,其表达式为:
y=k1x1+k2x2+…kn-1xn-1+b
或者
a1x1+ a2x2+…an-1xn-1+ anxn=0
同样在第一个表达式中k1…kn-1叫做斜率,b叫做截距(即x1= x2=…=xn-1=0的时候,直线与y轴的交叉点)
2 线性分类
这里,我们用一个例子来说明线性分类的使用。假设一个函数:
y=a1x1+ a2x2+ a3x3+ a4x4
通过y的值评价西瓜的好坏,其值落在[0-1]之间(数学里这样的函数很多,比如sigmoid函数,通过某种变化就可以让值落在[0-1]之间)。x1表示敲瓜的清脆声;x2表示瓜的颜色;x3表示瓜楴的长度;x4表示瓜比重。当0为好瓜,当0.5为坏瓜。分类算法的目标就是通过训练找到a1,a2,a3和a4使得判断更为准确。
3 线性回归
在二维图上分布着一些点,我们通过算法找出一条直线,使得所有点到这条直线的均差最小,也就是说这条线拟合了这些点。
案例:著名学者查尔斯·达尔文的表弟的高尔顿,发现子女的身高存在这样的关系:
Y = 0.516X+33.73(其中Y :子带身高(英寸),X:父代身高(英寸))。
下面我们主要来介绍线性分类。
4 逻辑回归
虽然叫逻辑回归,但是它本质上是一个分类问题。它通过sklearn.linear_model.LogisticRegression来实现。
sklearn.linear_model.LogisticRegression(penalty='l2', dual=False, tol=0.0001, C=1.0, fit_intercept=True, intercept_scaling=1, class_weight=None, random_state=None, solver='liblinear', max_iter=100, multi_class='ovr', verbose=0, warm_start=False, n_jobs=1)
4.1主要参数
参数 |
解释 |
penalty |
字符串,'L1' or'L2', 默认:'L2'。用于指定惩罚中使用的规范。"牛顿CG"、"SAG"和"LBFGS"解算器只支持L2惩罚。版本0.19:La1惩罚与SAGA求解器(允许"多项"+L1) |
C |
浮点数, 默认: 1.0。正则化强度的逆;必须是正浮点。像支持向量机一样,较小的值指定更强的正则化。 |
4.2主要属性
属性 |
解释 |
classes_ |
ndarray of shape (n_classes, ).分类器已知的类标签列表。 |
coef_ |
ndarray of shape (1, n_features) or (n_classes, n_features).决策函数中特征的系数。 |
intercept_ |
ndarray of shape (1,) or (n_classes,). 截距(又称偏差)添加到决策函数中。 |
n_iter_ |
ndarray of shape (n_classes,) or (1, ).所有类的实际迭代次数。如果是二进制或多项式,它只返回1个元素。对于liblinear solver,只给出所有类的最大迭代次数。 |
4.3主要方法
decision_function(X) |
预测样本的置信度得分。 |
densify() |
将系数矩阵转换为密集数组格式。 |
fit(X, y[, sample_weight]) |
根据给定的训练数据对模型进行拟合。 |
get_params([deep]) |
获取此估计器的参数。 |
predict(X) |
预测X中样本的类标签。 |
predict_log_proba(X) |
预测概率估计的对数。 |
predict_proba(X) |
概率估计。 |
score(X, y[, sample_weight]) |
返回给定测试数据和标签的平均精度。 |
set_params(**params) |
设置此估计器的参数。 |
sparsify() |
将系数矩阵转换为稀疏格式。 |
4.4 代码
4.4.1逻辑回归分析make_blobs数据集
#LogisticRegression分析make_blobs数据 def LogisticRegression_for_make_blobs(): myutil = util() X,y = make_blobs(n_samples=500,centers=5, random_state=8) clf = LogisticRegression(max_iter=100000) clf.fit(X,y) print('模型正确率:{:.2%}'.format(clf.score(X,y)))
其中
util类在Util.py文件中定义。
获得结果
模型正确率:94.80%
在util类定义了一个画散点图方法:draw_scatter和学习曲线的函数:plot_learning_curve
#画一个算法的散点图 def draw_scatter(self,X, y,clf,title): plt.scatter(X[:,0],X[:,1],c=y,cmap=plt.cm.spring,edgecolor='k') x_min,x_max = X[:,0].min()-1,X[:,0].max()+1 y_min,y_max = X[:,1].min()-1,X[:,1].max()+1 xx,yy = np.meshgrid(np.arange(x_min,x_max,.02),np.arange(y_min,y_max,.02))#生成网格点坐标矩阵 Z = clf.predict(np.c_[xx.ravel(),yy.ravel()])#预测数据集X的结果 Z = Z.reshape(xx.shape) plt.pcolormesh(xx, yy, Z,shading='auto',cmap=plt.cm.Spectral)#绘制分类图 plt.scatter(X[:,0],X[:,1],c=y,cmap=plt.cm.spring,edgecolor='k') plt.xlim(xx.min(),xx.max())#设置或查询 x 轴限制 plt.ylim(yy.min(),yy.max())#设置或查询 y 轴限制 self.show_pic(title)
#定义一个绘制学习曲线的函数 def plot_learning_curve(self,est, X, y,title):#learning_curve:学习曲线 tarining_set_size,train_scores,test_scores = learning_curve( est,X,y,train_sizes=np.linspace(.1,1,20),cv=KFold(20,shuffle=True,random_state=1)) estimator_name = est.__class__.__name__ line = plt.plot(tarining_set_size,train_scores.mean(axis=1),'o-',label=u'训练得分'+estimator_name,c='r') plt.plot(tarining_set_size,test_scores.mean(axis=1),'o-',label=u'测试得分'+estimator_name,c='g') plt.grid() plt.xlabel(u'训练设置值') plt.ylabel(u"得分") plt.ylim(0,1.1) plt.legend(loc='lower right')
我们把make_blobs数据集通过逻辑回归处理后的散点图画出来。
title = "逻辑回归_make_blobs" myutil.draw_scatter(X,y,clf, title) myutil.plot_learning_curve(LogisticRegression(max_iter=100000),X,y,title) myutil.show_pic(title)
散点分布图
由此可见由于make_blobs方法中定义了5个类,500个点(n_samples=500,centers=5),其分布在同中一目了然。
学习曲线图
学习得分,随着样本的变化波动不是很大,基本上在可以接收的范围内。
下面我们分别用LogisticRegression分析一下乳腺癌数据、鸢尾花数据和红酒数据
4.4.2逻辑回归分析乳腺癌数据集
#LogisticRegression分析乳腺癌数据 def LogisticRegression_for_load_breast_cancer(): myutil = util() X,y = datasets.load_breast_cancer().data,datasets.load_breast_cancer().target X1 = datasets.load_breast_cancer().data[:,:2] print("X的shape={},正样本数:{},负样本数:{}".format(X.shape, y[y == 1].shape[0], y[y == 0].shape[0])) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) # 训练模型 clf = LogisticRegression(max_iter=100000) clf.fit(X_train, y_train) # 查看模型得分 train_score = clf.score(X_train, y_train) test_score = clf.score(X_test, y_test) print("乳腺癌训练集得分:{trs:.2%},乳腺癌测试集得分:{tss:.2%}".format(trs=train_score, tss=test_score)) title = "逻辑回归_乳腺癌数据" myutil.plot_learning_curve(LogisticRegression(max_iter=100000),X,y,title) myutil.show_pic(title) clf = LogisticRegression(max_iter=100000).fit(X1,y) myutil.draw_scatter_for_clf(X1,y,clf,title)
说明
- X:所有的样本。
- y:对应每个样本应该的结果。
- train_test_split(X, y, test_size=0.2):将样本分为训练类和测试类,测试类占20%。
- X_train:为训练类的样本。
- X_test:为测试类的样本。
- y_train:为训练类的应该结果。
- y_test:为测试类的应该结果。
- clf.fit:进行训练。
- train_score:测试类得分。
- test_score:测试类得分。
在乳腺癌数据集中,总共有569个样本,每个样本有30属性,其中正样本数(良性):357,负样本数(恶性):212。最后获得的输出如下:
乳腺癌训练集得分:94.95%,乳腺癌测试集得分:97.37%
散点图
分类为两个结果的,我们成为二分类
学习曲线
学习曲线也是在可以接受范围之内。
4.4.3逻辑回归分析鸢尾花数据集
#LogisticRegression分析鸢尾花数据 def LogisticRegression_for_load_iris(): myutil = util() X,y = datasets.load_iris().data,datasets.load_iris().target X1 = datasets.load_iris().data[:,:2] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) clf = LogisticRegression(max_iter=100000) clf.fit(X_train, y_train) train_score = clf.score(X_train, y_train) test_score = clf.score(X_test, y_test) print("鸢尾花训练集得分:{trs:.2%},鸢尾花测试集得分:{tss:.2%}".format(trs=train_score, tss=test_score)) title = "逻辑回归_鸢尾花数据" myutil.plot_learning_curve(LogisticRegression(max_iter=100000),X,y,title) myutil.show_pic(title) clf = LogisticRegression(max_iter=100000).fit(X1,y) myutil.draw_scatter_for_clf(X1,y,clf,title)
最后输出
鸢尾花训练集得分:96.67%,鸢尾花测试集得分:100.00%。
散点图
学习曲线
数据少的时候,测试集的得分比较低,随着测试集数据的增加而增加。
4.4.4逻辑回归分析红酒数据集
#LogisticRegression分析红酒数据 def LogisticRegression_for_load_wine(): myutil = util() X,y = datasets.load_wine().data,datasets.load_wine().target X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) X1 = datasets.load_wine().data[:,:2] clf = LogisticRegression(max_iter=100000) clf.fit(X_train, y_train) train_score = clf.score(X_train, y_train) test_score = clf.score(X_test, y_test) print("红酒训练集得分:{trs:.2%},红酒测试集得分:{tss:.2%}".format(trs=train_score, tss=test_score)) title = "逻辑回归_红酒数据" myutil.plot_learning_curve(LogisticRegression(max_iter=100000),X,y,title) myutil.show_pic(title) clf = LogisticRegression(max_iter=100000).fit(X1,y) myutil.draw_scatter_for_clf(X1,y,clf,title)
最后输出
红酒训练集得分:100.00%,红酒测试集得分:94.44%
散点图
学习曲线
同鸢尾花一样,在数据少的时候,测试集的得分比较低,随着测试集数据的增加而增加。
由于我们这里用的是线性分类,所以在散点图中可以看出,分类的边界是一条直线。