Python机器学习基础教程学习笔记(6)——线性模型(分类)

Python机器学习基础教程学习笔记(6)——线性模型(分类)

1. 二分类

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import mglearn
# 不想看到warnings
import warnings
warnings.filterwarnings("ignore", category=Warning)
# 拆分训练集与测试集
from sklearn.model_selection import train_test_split
# 使用两个分类算法:LogisticRegression和LinearSVC
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC

X, y = mglearn.datasets.make_forge()

fig, axes = plt.subplots(1, 2, figsize=(10, 3))

for model, ax in zip([LinearSVC(), LogisticRegression()], axes):
    clf = model.fit(X, y)
    mglearn.plots.plot_2d_separator(clf, X, fill=False, eps=0.5,
                                    ax=ax, alpha=.7)
    mglearn.discrete_scatter(X[:, 0], X[:, 1], y, ax=ax)
    ax.set_title(clf.__class__.__name__)
    ax.set_xlabel("Feature 0")
    ax.set_ylabel("Feature 1")
    ax.legend()

output_3_0.png
  • LinearSVC和LogisticRegression两个模型默认都使用L2正则化
  • 决定正则化强度的权衡参数叫做C。
  • C值越大,对应的正则化越弱。
  • C值较大,模型将尽可能将训练集拟合到最好
  • C值较小,模型更强调使用系统向量接近于0
mglearn.plots.plot_linear_svc_regularization()
output_5_0.png
from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(
    cancer.data, cancer.target, stratify=cancer.target, random_state=42)
logreg = LogisticRegression().fit(X_train, y_train)
print("Training set score: {:.3f}".format(logreg.score(X_train, y_train)))
print("Test set score: {:.3f}".format(logreg.score(X_test, y_test)))
Training set score: 0.953
Test set score: 0.958
  • C=1的默认值给出了相当好的性能,都是95%的精度。
  • 训练集和测试集的性能非常接近,所以很可能是欠拟合。
  • 尝试增大C来拟合一个更灵活的模型
logreg100 = LogisticRegression(C=100).fit(X_train, y_train)
print("Training set score: {:.3f}".format(logreg100.score(X_train, y_train)))
print("Test set score: {:.3f}".format(logreg100.score(X_test, y_test)))
Training set score: 0.972
Test set score: 0.965
  • 当减小C值时,正则化更强,训练集和测试集精度都变小
logreg001 = LogisticRegression(C=0.01).fit(X_train, y_train)
print("Training set score: {:.3f}".format(logreg001.score(X_train, y_train)))
print("Test set score: {:.3f}".format(logreg001.score(X_test, y_test)))
Training set score: 0.934
Test set score: 0.930
plt.plot(logreg.coef_.T,'o',label="C=1")
plt.plot(logreg100.coef_.T,'^',label="C=100")

plt.plot(logreg001.coef_.T,'v',label="C=0.01")

# 给横坐标赋值
plt.xticks(range(cancer.data.shape[1]),cancer.feature_names,rotation=90)

# 加中间的横线
plt.hlines(0,0,cancer.data.shape[1])
plt.ylim(-5,5)
plt.xlabel("coefficient index")
plt.ylabel("coeffient magnitude")
plt.legend()
plt.show()
output_11_0.png
  • LogisticRegression使用的是L2正则化
  • 更强的正则化使用得系统趋向于0,但是系统永远不会正好等于0
  • 对线性模型系统的解释应该始终持保留态度
  • 如果想要解释性更强的模型,使用L1正则化可能更好,因为它约束模型只使用少数的几个特征
for C,marker in zip([0.001,1,100],['o','^','v']):
    # 这里把penalty参数设置为l1,表示使用L1正则化
    lr_l1= LogisticRegression(C=C,penalty="l1").fit(X_train,y_train)
    print("C={:.3f}".format(C))
    print("Training set score : {:.3f}".format(lr_l1.score(X_train, y_train)))
    print("Test set score : {:.3f}".format(lr_l1.score(X_test, y_test)))
    print("---------------------------------------")
    plt.plot(lr_l1.coef_.T,marker,label="C={:.3f}".format(C))
# 给横坐标赋值
plt.xticks(range(cancer.data.shape[1]),cancer.feature_names,rotation=90)

# 加中间的横线
plt.hlines(0,0,cancer.data.shape[1])
plt.ylim(-5,5)
plt.xlabel("coefficient index")
plt.ylabel("coeffient magnitude")
plt.legend()
plt.show()
C=0.001
Training set score : 0.913
Test set score : 0.923
---------------------------------------
C=1.000
Training set score : 0.960
Test set score : 0.958
---------------------------------------
C=100.000
Training set score : 0.986
Test set score : 0.979
---------------------------------------
output_13_1.png
  • 模型的主要差别在于penalty参数,这个参数会影响正则化,也会影响模型是使用所有可用特征还是只选择特征的一个子集

2. 多分类

将二分类算法推广到多分类算法的一种常见方法是“一对其余”(one-vs.-rest)

from sklearn.datasets import make_blobs
X ,y = make_blobs(random_state=42)
mglearn.discrete_scatter(X[:,0],X[:,1],y)
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")
plt.legend(["Class 0","Class 1","Class 2"])
plt.show()
output_17_0.png
linear_svm = LinearSVC().fit(X,y)
# coef_的形状是(3,2),说明coef_每行包含三个类别之一的系统微量每列包含某个特征(这个数据集有2个特征)对应的系数值。
print("Coefficient shape:{}".format(linear_svm.coef_.shape))
# intercept_的形状是(3,),是一维数组,保存每个类别的截距
print("Intercept shape:{}".format(linear_svm.intercept_.shape))
Coefficient shape:(3, 2)
Intercept shape:(3,)
mglearn.discrete_scatter(X[:,0],X[:,1],y)
line = np.linspace(-15,15)
# -(line*coef[0]+ intercept)/coef[1] 这个值可以简单理解一下
for coef,intercept,color in zip(linear_svm.coef_,linear_svm.intercept_,['b','r','g']):
    plt.plot(line,-(line*coef[0]+ intercept)/coef[1],color)
plt.xlim(-10,8)
plt.ylim(-10,15)
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")
plt.legend(["Class 0","Class 1","Class 2","Line class 0","Line class 1","Line class 2"],loc=(1.01,0.3))
plt.show()
output_19_0.png
  • 从图中可以看出这种“一对其余”(one-vs.-rest)的样子
  • 但是图中间的三角形区域属于哪一个类别呢,3个二类分类器都将这一区域内的点划分为“其余”
  • 答案是,分类方程结果最大的那个类别,即最接近的那条线对应的类别。
mglearn.plots.plot_2d_classification(linear_svm,X,fill=True,alpha=.3)
mglearn.discrete_scatter(X[:,0],X[:,1],y)
line = np.linspace(-15,15)
# -(line*coef[0]+ intercept)/coef[1] 这个值可以简单理解一下
for coef,intercept,color in zip(linear_svm.coef_,linear_svm.intercept_,['b','r','g']):
    plt.plot(line,-(line*coef[0]+ intercept)/coef[1],color)
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")
plt.legend(["Class 0","Class 1","Class 2","Line class 0","Line class 1","Line class 2"],loc=(1.01,0.3))
plt.show()
output_21_0.png

3 优点、缺点和参数

  • 线性模型的主要参数是正则化参数
    • 回归模型中叫alpha
    • 分类模型中叫C
    • alpha值较大或C值较小,说明模型比较简单
  • 还需要确定使用L1正则化还是L2正则化
    • 如果假定只有几个特征是真正重要的,那么使用L1正则化,否则默认使用L2正则化
    • 如果模型的可解释性很重要,使用L1会有帮助
  • 线性模型的训练速度非常快,预测速度也很快。
  • 可推广到非常大的数据集
  • 稀疏数据也很有效
    • 如果数据包含数十万甚至上百万个样本,需要研究如何使用LogisticRegression和Ridge模型的solver='sag'选项,在处理大数据时,这一选项比默认值更快
    • 其他选项还有SGDClassifier类和SDGRegressor类,对本节介绍的线性模型实现了可扩展性更强的版本。
  • 如果特征数量大于样本数量,线性模型表现通常都很好。
  • 常用于非常大的数据集,只是因为训练其他模型并不可行。
  • 在更低维的空间中,其他模型的泛化性能可能更好

你可能感兴趣的:(Python机器学习基础教程学习笔记(6)——线性模型(分类))