请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  量化平台 帖子:3365825 新帖:0

【机器学习】用于分类的线性模型:Logistic回归与

醒掌天下权发表于:5 月 10 日 06:52回复(1)

线性模型用于分类,分类的原理还要从公式说起。

y=w[0]?x[0] w[1]?x[1] ... w[p]?x[p] by=w[0]?x[0]w[1]?x[1]...w[p]?x[p]b

y = w[0]x[0] w1x1 ... w[p]*x[p] b

线性模型的公司的结果y是一个连续的输出结果,如果将y的值与0作一个界限上的区分,那y的值将被分成两个区域。公式的表达如下:

y=w[0]?x[0] w[1]?x[1] ... w[p]?x[p] b>0y=w[0]?x[0]w[1]?x[1]...w[p]?x[p]b>0

y = w[0]x[0] w1x1 ... w[p]*x[p] b>0

也就是说,如果该公式(函数)预测的结果值小于0,就归类为-1,如果结果值大于0,就归类为1.

需要重点理解的地方在于:

  • 对于用于回归的线性模型来说,输出y是特征的线性函数,是直线、平面或超平面(对于更高维的数据集)。

  • 对于用于分类的线性模型,决策边界是输入的线性函数。

不同线性模型算法之间的区别在于:

  • 系数和截距的特定组合对训练集数据拟合好坏的度量方法;

  • 是否使用正则化,以及使用哪种正则化方法。

最觉的两种线性分类算法是Logistic回归线性支持向量机。前者在linear_model.LogisticRegression中实现,后者在svm.LinearSVC(SVC代表支持向量分类器)中实现 。

接下来对这两个模型做一个初步认识吧!

# 在学习之前,先导入这些常用的模块import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport mglearn

Logistic 与 LinearSVC  模型

下面,将这两个模型用在二分类数据forge数据集上,并显示模型得出的决策边界。

先展示下二分类的展示图:

# 导入二分类数据X, y = mglearn.datasets.make_forge()mglearn.discrete_scatter(X[:, 0], X[:, 1], y)plt.show()

# 导入Logisticfrom sklearn.linear_model import LogisticRegression# 导入LinearSVCfrom 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=.5, ax=ax, alpha=.7)# 绘制二分类的训练数据mglearn.discrete_scatter(X[:, 0], X[:, 1], y, ax=ax)# 设置标题为模型名称ax.set_title('{}'.format(clf.__class__.__name__))# 设置x坐标轴标签名称ax.set_xlabel('Feature 0')# 设置y坐标轴标签名称ax.set_ylabel('Feature 1')# 在第一个绘图区上显示图例axes[0].legend()
plt.show()

说明:

  • forge数据集有两个特征,分别对应X轴与Y轴。

  • LinearSVC与LogisticRegression得到的决策边界,都是直线,将数据分为了上下两个区域。

  • 两个模型默认使用了L2正则化。

继续探讨:

  • 对于LinearSVC与LogisticRegression而言,决定正则化强度的权衡参数叫做CC值越大,对就的正则化越弱

  • 也就是说,越大的C将拥有越上的约束力,即系数的大小更自由,模型对于数据的贴合度将变得更复杂。

  • 如果C越小,则对系数的约束越大,甚至趋向于0,使模型更能贴合大多数数据,模型也更简单。

下面直接展示一下LinearSVC模型的C分别取0.011100时模型的决策边界效果:

mglearn.plots.plot_linear_svc_regularization()

对上图的总结:

  1. 最左侧的图,C值很小,所以对应强正则化。要求模型更贴合于大多数数据,因此对于图中两个错误的点进行了忽略。

  2. 中间的图,C值稍大,由于对模型的约束变小,模型对于数据的反应则变得更加第三一些,决策线向着两个错误的点进行偏移,希望更好的贴合训练数据。

  3. 右侧图C值很大,因为对模型的约束很小,导致模型的决策边界要求对所有数据都贴合,造成了过拟合现象。

再来看看使用乳腺癌数据集对LogisticRegression模型做出分析:

# 导入乳腺癌数据from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()# 将数据分为训练集测试集from sklearn.model_selection import train_test_split
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('训练集评估分数:', logreg.score(X_train, y_train))print('测试集评估分数:', logreg.score(X_test, y_test))
训练集评估分数: 0.9553990610328639测试集评估分数: 0.958041958041958

这里模型置信的C值是1.如果训练集的评分与测试集的评分差不多,那可能存在欠拟合的现象。

现在给模型增大C值,再看看评估结果:

logreg100 = LogisticRegression(C=100).fit(X_train, y_train)print('训练集评估分数:', logreg100.score(X_train, y_train))print('测试集评估分数:', logreg100.score(X_test, y_test))
训练集评估分数: 0.971830985915493测试集评估分数: 0.965034965034965

通过增大模型的C值,发现模型的精度变高了。

现在再减小C值看看模型的评估分数:

logreg001 = LogisticRegression(C=0.01).fit(X_train, y_train)print('训练集评估分数:', logreg001.score(X_train, y_train))print('测试集评估分数:', logreg001.score(X_test, y_test))
训练集评估分数: 0.9342723004694836测试集评估分数: 0.9300699300699301

可以看出,模型的精度变小了,并且存在欠拟合的可能。

按照老办法,我们当不同C值情况下,模型得出的系数图例化,看看结果:

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('Codefficient index')
plt.ylabel('Coefficient magnitude')
plt.legend()
plt.show()

从这个图例可以看出,C值越小,模型的系数就越趋向于0.

另外,该模型默认使用L2正则,也可以将其改成L1正则,以减少模型使用的特征:

# 评估for C, marker in zip([0.001, 1, 100], ['o', '^', 'v']):
    lr_l1 = LogisticRegression(C=C, penalty='l1').fit(X_train, y_train)print('训练集,C={0},评估分数={1}'.format(C, lr_l1.score(X_train, y_train)))print('测试集,C={0},评估分数={1}'.format(C, lr_l1.score(X_test, y_test)))# 绘图plt.plot(lr_l1.coef_.T, marker, label='C={}'.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('Codefficient index')
plt.ylabel('Coefficient magnitude')
plt.legend(loc=3)
plt.show()
训练集,C=0.001,评估分数=0.9131455399061033
测试集,C=0.001,评估分数=0.9230769230769231
训练集,C=1,评估分数=0.960093896713615
测试集,C=1,评估分数=0.958041958041958
训练集,C=100,评估分数=0.9859154929577465
测试集,C=100,评估分数=0.9790209790209791

Ok,上图对于不同C值所对应的L正则下的系数分布有了直观的了解,也就明白了对应的约束力。

这里主要需要明白设置L1L2需要通过参数penalty来设置。

用于多分类的线性模型

多分类其实也是一处二分类的模式,它是一对其余的方法。

这里展示一个三类的gf数据:

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()

然后使用该数据对LinearSVC分类器进行训练:

linear_svm = LinearSVC().fit(X, y)print('模型斜率集:', linear_svm.coef_.shape)print('模型截距集:', linear_svm.intercept_.shape)
模型斜率集: (3, 2)
模型截距集: (3,)

通过形状可以明白:斜率集有3行,每行代表类别之一的一个系数向量;有2列,每列包含某个特征对应的系数值。而截距是个一维数据,包含每个类别的截距值。

现在将分类器给出的直线进行可视化:

mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
line = np.linspace(-15, 15)for coef, intercept, color in zip(linear_svm.coef_, linear_svm.intercept_, ['b', 'r', 'g']):
    plt.plot(line, -(line * coef[0]   intercept) / coef[1], c=color)
plt.ylim(-10, 15)
plt.xlim(-10, 8)
plt.xlabel('Feature 0')
plt.ylabel('Feature 1')
plt.legend(['Class 0', 'Class 1', 'Class 2'], loc=(1.01, 0.3))
plt.show()

在这里,线条的颜色与各点的颜色是一致的。从图中可以很直观的看到这三个点是如何被分成三类的。

但是,这三条线交叉的地方,有一个空白的三角区,那这个区域属于哪个类别呢?

答案是分类方程结果最大的那个类别,即最接近的那条结对应的类别!

下面将展示整个二维空间是如何被分类的:

mglearn.plots.plot_2d_classification(linear_svm, X, alpha=.7)
mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
line = np.linspace(-15, 15)for coef, intercept, color in zip(linear_svm.coef_, linear_svm.intercept_, ['b', 'r', 'g']):
    plt.plot(line, -(line * coef[0]   intercept) / coef[1], c=color)
plt.xlabel('Feature 0')
plt.ylabel('Feature 1')
plt.legend(['Class 0', 'Class 1', 'Class 2'], loc=(1.01, 0.3))
plt.show()

通过上图很明白的就看出中间的三角区是如何被分类的了!

好吧,到现在,机器学习的基础模型的探讨就告一段落了。不过,这些模型并不常用,在接下来,将着重学习朴素贝叶斯分类器、决策树、核支持向量机、神经网络等经典模型!

线性模型用于分类,分类的原理还要从公式说起。

$y = w[0]*x[0]+w[1]*x[1]+...+w[p]*x[p]+b$

线性模型的公司的结果y是一个连续的输出结果,如果将y的值与0作一个界限上的区分,那y的值将被分成两个区域。公式的表达如下:

$y = w[0]*x[0]+w[1]*x[1]+...+w[p]*x[p]+b>0$

也就是说,如果该公式(函数)预测的结果值小于0,就归类为-1,如果结果值大于0,就归类为1.

需要重点理解的地方在于:

  • 对于用于回归的线性模型来说,输出y是特征的线性函数,是直线、平面或超平面(对于更高维的数据集)。

  • 对于用于分类的线性模型,决策边界是输入的线性函数。

不同线性模型算法之间的区别在于:

  • 系数和截距的特定组合对训练集数据拟合好坏的度量方法;

  • 是否使用正则化,以及使用哪种正则化方法。

最觉的两种线性分类算法是Logistic回归线性支持向量机。前者在linear_model.LogisticRegression中实现,后者在svm.LinearSVC(SVC代表支持再是分类器)中实现 。

接下来对这两个模型做一个初步认识吧!

# 在学习之前,先导入这些常用的模块import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport mglearn

Logistic 与 LinearSVC  模型¶

下面,将这两个模型用在二分类数据forge数据集上,并显示模型得出的决策边界。

先展示下二分类的展示图:

# 导入二分类数据X, y = mglearn.datasets.make_forge()mglearn.discrete_scatter(X[:, 0], X[:, 1], y)plt.show()
C:\Users\Administrator\Anaconda3\lib\site-packages\sklearn\utils\deprecation.py:77: DeprecationWarning: Function make_blobs is deprecated; Please import make_blobs directly from scikit-learn
  warnings.warn(msg, category=DeprecationWarning)
# 导入Logisticfrom sklearn.linear_model import LogisticRegression# 导入LinearSVCfrom 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=.5, ax=ax, alpha=.7)# 绘制二分类的训练数据mglearn.discrete_scatter(X[:, 0], X[:, 1], y, ax=ax)# 设置标题为模型名称ax.set_title('{}'.format(clf.__class__.__name__))# 设置x坐标轴标签名称ax.set_xlabel('Feature 0')# 设置y坐标轴标签名称ax.set_ylabel('Feature 1')# 在第一个绘图区上显示图例axes[0].legend()plt.show()
C:\Users\Administrator\Anaconda3\lib\site-packages\sklearn\utils\deprecation.py:77: DeprecationWarning: Function make_blobs is deprecated; Please import make_blobs directly from scikit-learn
  warnings.warn(msg, category=DeprecationWarning)

说明:

  • forge数据集有两个特征,分别对应X轴与Y轴。

  • LinearSVC与LogisticRegression得到的决策边界,都是直线,将数据分为了上下两个区域。

  • 两个模型默认使用了L2正则化。

继续探讨:

  • 对于LinearSVC与LogisticRegression而言,决定正则化强度的权衡参数叫做CC值越大,对就的正则化越弱

  • 也就是说,越大的C将拥有越上的约束力,即系数的大小更自由,模型对于数据的贴合度将变得更复杂。

  • 如果C越小,则对系数的约束越大,甚至趋向于0,使模型更能贴合大多数数据,模型也更简单。

下面直接展示一下LinearSVC模型的C分别取0.011100时模型的决策边界效果:

mglearn.plots.plot_linear_svc_regularization()

对上图的总结:

  1. 最左侧的图,C值很小,所以对应强正则化。要求模型更贴合于大多数数据,因此对于图中两个错误的点进行了忽略。

  2. 中间的图,C值稍大,由于对模型的约束变小,模型对于数据的反应则变得更加第三一些,决策线向着两个错误的点进行偏移,希望更好的贴合训练数据。

  3. 右侧图C值很大,因为对模型的约束很小,导致模型的决策边界要求对所有数据都贴合,造成了过拟合现象。

再来看看使用乳腺癌数据集对LogisticRegression模型做出分析:

# 导入乳腺癌数据from sklearn.datasets import load_breast_cancercancer = load_breast_cancer()# 将数据分为训练集测试集from sklearn.model_selection import train_test_splitX_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('训练集评估分数:', logreg.score(X_train, y_train))print('测试集评估分数:', logreg.score(X_test, y_test))
训练集评估分数: 0.9553990610328639
测试集评估分数: 0.958041958041958

这里模型置信的C值是1.如果训练集的评分与测试集的评分差不多,那可能存在欠拟合的现象。

现在给模型增大C值,再看看评估结果:

logreg100 = LogisticRegression(C=100).fit(X_train, y_train)print('训练集评估分数:', logreg100.score(X_train, y_train))print('测试集评估分数:', logreg100.score(X_test, y_test))
训练集评估分数: 0.971830985915493
测试集评估分数: 0.965034965034965

通过增大模型的C值,发现模型的精度变高了。

现在再减小C值看看模型的评估分数:

logreg001 = LogisticRegression(C=0.01).fit(X_train, y_train)print('训练集评估分数:', logreg001.score(X_train, y_train))print('测试集评估分数:', logreg001.score(X_test, y_test))
训练集评估分数: 0.9342723004694836
测试集评估分数: 0.9300699300699301

可以看出,模型的精度变小了,并且存在欠拟合的可能。

按照老办法,我们当不同C值情况下,模型得出的系数图例化,看看结果:

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('Codefficient index')plt.ylabel('Coefficient magnitude')plt.legend()plt.show()

从这个图例可以看出,C值越小,模型的系数就越趋向于0.

另外,该模型默认使用L2正则,也可以将其改成L1正则,以减少模型使用的特征:

# 评估for C, marker in zip([0.001, 1, 100], ['o', '^', 'v']):lr_l1 = LogisticRegression(C=C, penalty='l1').fit(X_train, y_train)print('训练集,C={0},评估分数={1}'.format(C, lr_l1.score(X_train, y_train)))print('测试集,C={0},评估分数={1}'.format(C, lr_l1.score(X_test, y_test)))# 绘图plt.plot(lr_l1.coef_.T, marker, label='C={}'.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('Codefficient index')plt.ylabel('Coefficient magnitude')plt.legend(loc=3)plt.show()
训练集,C=0.001,评估分数=0.9131455399061033
测试集,C=0.001,评估分数=0.9230769230769231
训练集,C=1,评估分数=0.960093896713615
测试集,C=1,评估分数=0.958041958041958
训练集,C=100,评估分数=0.9859154929577465
测试集,C=100,评估分数=0.9790209790209791

Ok,上图对于不同C值所对应的L正则下的系数分布有了直观的了解,也就明白了对应的约束力。

这里主要需要明白设置L1L2需要通过参数penalty来设置。

用于多分类的线性模型¶

多分类其实也是一处二分类的模式,它是一对其余的方法。

这里展示一个三类的gf数据:

from sklearn.datasets import make_blobsX, 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()

然后使用该数据对LinearSVC分类器进行训练:

linear_svm = LinearSVC().fit(X, y)print('模型斜率集:', linear_svm.coef_.shape)print('模型截距集:', linear_svm.intercept_.shape)
模型斜率集: (3, 2)
模型截距集: (3,)

通过形状可以明白:斜率集有3行,每行代表类别之一的一个系数向量;有2列,每列包含某个特征对应的系数值。而截距是个一维数据,包含每个类别的截距值。

现在将分类器给出的直线进行可视化:

mglearn.discrete_scatter(X[:, 0], X[:, 1], y)line = np.linspace(-15, 15)for coef, intercept, color in zip(linear_svm.coef_, linear_svm.intercept_, ['b', 'r', 'g']):plt.plot(line, -(line * coef[0] + intercept) / coef[1], c=color)plt.ylim(-10, 15)plt.xlim(-10, 8)plt.xlabel('Feature 0')plt.ylabel('Feature 1')plt.legend(['Class 0', 'Class 1', 'Class 2'], loc=(1.01, 0.3))plt.show()

在这里,线条的颜色与各点的颜色是一致的。从图中可以很直观的看到这三个点是如何被分成三类的。

但是,这三条线交叉的地方,有一个空白的三角区,那这个区域属于哪个类别呢?

答案是分类方程结果最大的那个类别,即最接近的那条结对应的类别!

下面将展示整个二维空间是如何被分类的:

mglearn.plots.plot_2d_classification(linear_svm, X, alpha=.7)mglearn.discrete_scatter(X[:, 0], X[:, 1], y)line = np.linspace(-15, 15)for coef, intercept, color in zip(linear_svm.coef_, linear_svm.intercept_, ['b', 'r', 'g']):plt.plot(line, -(line * coef[0] + intercept) / coef[1], c=color)plt.xlabel('Feature 0')plt.ylabel('Feature 1')plt.legend(['Class 0', 'Class 1', 'Class 2'], loc=(1.01, 0.3))plt.show()

通过上图很明白的就看出中间的三角区是如何被分类的了!

好吧,到现在,机器学习的基础模型的探讨就告一段落了。不过,这些模型并不常用,在接下来,将着重学习朴素贝叶期斯分类器、决策树、核支持向量机、神经网络等经典模型!¶

 

全部回复

0/140

量化课程

    移动端课程