机器学习| 第二周:监督学习(1)『附学习资源』

2019-07-15 19:29:45 浏览数 (1)

本节主要内容:

机器学习学习路径初探;监督学习相关知识

1. 机器学习学习路径初探

刚开始入门机器学习,好的学习路径非常重要,以下是我个人最近学习机器学习的心得,与大家分享。

  • 首先,基础知识非常重要,比如Python、常用包的使用(Pandas, Numpy, matplotlib)的使用。这一部分知识可以获取的路径有:廖雪峰Python教程,常用包的学习使用可以使用以下数据,里面介绍了Pandas, Numpy, matplotlib 几个常用库的使用,手头上有一本,以备查阅。
  • 其次,刚开始学习机器学习尽量不要从基础代码开始,如果一上来就让写算法,对于基础不好的同学容易感到挫败感,建议从调包开始学习。 scikit-learn 是一个开源项目,可以免费使用和分发,任何人都可以轻松获取其源代码来,查看其背后的原理。从 scikit-learn 开始学习,能让你对机器学习有个感性的认识,介绍的书籍有 《Python机器学习基础教程》 个人感觉是一本不错的学习资料。
  • 最后,调包可以让你快速完成一个机器学习,增加你对机器学习的兴趣,但是,基本的算法也需要懂得,在 《Python机器学习基础教程》 中也详细介绍了许多常见的算法。如果有需要,建议观看吴恩达机器学习的视频

以上就是我学习机器学习的大概思路,我也会按照这个思路进行学习。

2. 监督学习

常见概念

  • 监督机器学习问题主要有两种,分别叫作分类(classification)与回归(regression)。
  • 泛化、 过拟合与欠拟合: 泛化是指衡量新数据在模型的表现能力好坏
  • 过拟合是指模型能很好的拟合训练数据,在训练集上变现得很好,但是泛化能力不高。
  • 欠拟合是与过拟合相对的一个概念。

模型复杂度与训练精度和测试精度之间的权衡 来源:《Python机器学习基础教程》

以下介绍几个监督学习的算法

K近邻

基本思想

k-NN 算法可以说是最简单的机器学习算法。构建模型只需要保存训练数据集即可。想要对新数据点做出预测,算法会在训练数据集中找到最近的数据点,也就是它的“最近邻”。包所在的位置:sklearn.neighbors.KNeighborsClassifier

举例
代码语言:javascript复制
 1import mglearn 
 2from sklearn.model_selection import train_test_split 
 3# 导入数据
 4X, y = mglearn.datasets.make_forge() 
 5# 该函数用来把数据集进行洗牌,默认选出 75% 的数据作为训练集, 25% 的数据作为测试集
 6X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
 7# K近邻所使用的包
 8from sklearn.neighbors import KNeighborsClassifier
 9# 引入 K 近邻算法对象 
10clf = KNeighborsClassifier(n_neighbors=3) # 选择邻居的个数,邻居越少,模型越复杂。
11# 对模型进行训练
12clf.fit(X_train, y_train)
13# 预测
14clf.predict(X_test)
15# 计算预测精度
16clf.score(X_test, y_test)

输出:0.8571428571428571 说明模型对于测试集有 85% 的概率是能预测准确的。

代码语言:javascript复制
 1# 可视化
 2import matplotlib.pyplot as plt
 3fig, axes = plt.subplots(1, 3, figsize=(10, 3))
 4for n_neighbors, ax in zip([1, 3, 9], axes):
 5    # fit方法返回对象本身,所以我们可以将实例化和拟合放在一行代码中
 6    clf = KNeighborsClassifier(n_neighbors=n_neighbors).fit(X, y)
 7    mglearn.plots.plot_2d_separator(clf, X, fill=True, eps=0.5, ax=ax, alpha=.4)
 8    mglearn.discrete_scatter(X[:, 0], X[:, 1], y, ax=ax)
 9    ax.set_title("{} neighbor(s)".format(n_neighbors))
10    ax.set_xlabel("feature 0")
11    ax.set_ylabel("feature 1")
12axes[0].legend(loc=3)

不同邻居个数下,模型的预测情况

从左边可以看出,当邻居个数为 1 时,此时模型最复杂,模型显现出过拟合的情形,右边邻居为 9 ,模型预测出来的分界线近似直线,过拟合程度不高。

线性模型

常见的线性回归主要有 线性回归(普通最小二乘法)、岭回归(L2正则化)、lasso

1. 线性回归(普通最小二乘法)

基本公式: y = w*x b 线性回归,或者普通最小二乘法(ordinary least squares, OLS),是回归问题最简单也最经典的线性方法。线性回归寻找参数 w 和 b,使得对训练集的预测值与真实的回归目标值 y之间的均方误差最小。均方误差(mean squared error) 是预测值与真实值之差的平方和除以样本数。线性回归没有参数,这是一个优点,但也因此无法控制模型的复杂度

代码语言:javascript复制
1from sklearn.linear_model import LinearRegression
2X, y = mglearn.datasets.make_wave(n_samples=60)
3X_train , X_test, y_train, y_test = train_test_split(X, y, random_state=42)
4lr = LinearRegression() # 线性模型对象化
5lr.fit(X=X_train, y=y_train)
6print("lr.coef : {}".format(lr.coef_))
7print("lr.intercept_ : {}".format(lr.intercept_))

输出 lr.coef : [0.39390555] coef_ 属性用来存储线性模型训练产生的权重系数 w lr.intercept_ : -0.031804343026759746 intercept_ 属性用来存储截距系数 b

代码语言:javascript复制
1lr.predict(X_test)
2print("traiing set score: {:.2f}".format(lr.score(X=X_train, y=y_train)))
3print("test set score: {:.2f}".format(lr.score(X=X_test, y=y_test)))

输出 traiing set score: 0.67 test set score: 0.66

训练和测试的分数接近,说明存在欠拟合 一般对于一维的数据集来说,过拟合的可能性比较小

2. 岭回归(Ridge)

岭回归相当于吴恩达视频讲解的正则化(约束模型的系数,正则化越强,系数越接近于 0 ),下面介绍的 lasso 也是利用正则化,但是二者正则化的方式不同。岭回归使用的是 L2 正则化(系数接近于 0 ,但是不会等于 0)

代码语言:javascript复制
1from sklearn.linear_model import Ridge
2ridge = Ridge().fit(X_train, y_train) # X_train , X_test, y_train, y_test数据同上面
3print("training set score:{:.2f}".format(ridge.score(X_train, y_train)))
4print("test set score :{:.2f}".format(ridge.score(X_test, y_test)))

输出 training set score:0.89 test set score :0.75

对比线性回归,岭回归的训练分数比较低,但是测试分数却比较高 Ridge 是一种 约束更强的模型,更不易出现过拟合。复杂度小的模型意味着训练集上的性能更差,但是泛化性能更好,由于我们对泛化性能感兴趣,所以应该选择 Rideg 而不是 LinearRegression 模型。

》 Ridge 模型在模型的简单性(系数都接近于 0)与训练集性能之间做出权衡。简单性和训练集性能二者对于模型的重要程度可以由用户通过设置 alpha 参数来指定。alpha 的最佳设定值取决于用到的具体数据集。增大 alpha 会使得系数更加趋向于 0,从而降低训练集性能,但可能会提高泛化性能。 默认 alpha 是 1。

代码语言:javascript复制
1ridge10 = Ridge(alpha=10).fit(X_train, y_train)
2print("training set score:{:.2f}".format(ridge10.score(X_train, y_train)))
3print("test set score :{:.2f}".format(ridge10.score(X_test, y_test)))

输出 training set score:0.79 test set score :0.64

代码语言:javascript复制
1ridge01 = Ridge(alpha=0.1).fit(X_train, y_train)
2print("training set score:{:.2f}".format(ridge01.score(X_train, y_train)))
3print("test set score :{:.2f}".format(ridge01.score(X_test, y_test)))

输出 training set score:0.93 test set score :0.77

以下对比不同 alpha 参数,查看其模型的系数如何变化(与线性模型对比)

代码语言:javascript复制
1plt.plot(ridge.coef_, 's', label="Ridge alpha=1")
2plt.plot(ridge10.coef_, '^', label="Ridge alpha=10")
3plt.plot(ridge01.coef_, 'v', label="Ridge alpha=0.1")
4plt.plot(lr.coef_, 'o', label="LinearRegression")
5plt.xlabel("Coefficient index")
6plt.ylabel("Coefficient magnitude")
7plt.hlines(0, 0, len(lr.coef_))
8plt.ylim(-25, 25)
9plt.legend()

横坐标是 x=0 对应第一个特征的系数, x=1 对应第二个特征的系数,以此类推,一直到 x=100, 纵坐标是每个系数的取值。

3. lasso

与岭回归相同,使用 lasso 也是约束系 数使其接近于 0,但用到的方法不同,叫作 L1 正则化 L1 正则化的结果是,使用 lasso 时 某些系数刚好为 0。这说明某些特征被模型完全忽略。这可以看作是一种自动化的特征选择。某些系数刚好为 0,这样模型更容易解释,也可以呈现模型最重要的特征。

代码语言:javascript复制
1#  lasso 应用在扩展的波士顿房价数据集上
2from sklearn.linear_model import Lasso
3import numpy as np
4lasso = Lasso().fit(X_train, y_train)
5print("Training set score: {:.2f}".format(lasso.score(X_train, y_train)))
6print("Test set score: {:.2f}".format(lasso.score(X_test, y_test)))
7print("Number of features used: {}".format(np.sum(lasso.coef_ != 0)))

输出 Training set score: 0.29 Test set score: 0.21 Number of features used: 4 Lasso 在训练集与测试集上的表现都很差。这表示存在欠拟合,我们发现模型 只用到了 105 个特征中的 4 个。

与 Ridge 类似, Lasso 也有一个正则化参数 alpha,可以控制系数趋向于 0 的强度。在上一个例子中,我们用的是默认值 alpha=1.0。为了降低欠拟合,我们尝试减小 alpha。这么做的同时,我们还需要增加 max_iter 的值(运行迭代的最大次数) alpha 值越大,正则化作用越大,模型越简单

代码语言:javascript复制
1lasso001 = Lasso(alpha=0.01, max_iter=100000).fit(X_train, y_train)
2print("Training set score: {:.2f}".format(lasso001.score(X_train, y_train)))
3print("Test set score: {:.2f}".format(lasso001.score(X_test, y_test)))
4print("Number of features used: {}".format(np.sum(lasso001.coef_ != 0)))

输出 Training set score: 0.90 Test set score: 0.77 Number of features used: 33

代码语言:javascript复制
1lasso00001 = Lasso(alpha=0.0001, max_iter=100000).fit(X_train, y_train)
2print("Training set score: {:.2f}".format(lasso00001.score(X_train, y_train)))
3print("Test set score: {:.2f}".format(lasso00001.score(X_test, y_test)))
4print("Number of features used: {}".format(np.sum(lasso00001.coef_ != 0)))

输出 Training set score: 0.95 Test set score: 0.64 Number of features used: 96 系数可视化

代码语言:javascript复制
1plt.plot(lasso.coef_, 's', label="Lasso alpha=1")
2plt.plot(lasso001.coef_, '^', label="Lasso alpha=0.01")
3plt.plot(lasso00001.coef_, 'v', label="Lasso alpha=0.0001")
4plt.plot(ridge01.coef_, 'o', label="Ridge alpha=0.1")
5plt.legend(ncol=2, loc=(0, 1.05))
6plt.ylim(-25, 25)
7plt.xlabel("Coefficient index")
8plt.ylabel("Coefficient magnitude")

alpha 值越大,正则化作用越大, 所以当 alpha=1 时,模型大部分参数都接近于 0。

  • 在实践中,在两个模型中一般首选岭回归。但如果特征很多,你认为只有其中几个是重要 的,那么选择 Lasso 可能更好。同样,如果你想要一个容易解释的模型, Lasso 可以给出 更容易理解的模型,因为它只选择了一部分输入特征。

以上就是监督学习的一部分内容,下一节将推出剩下内容。利用 scikit-learn 学习,事半功倍! 后台回复『机器学习』获取学习资源


您的关注和点赞是对我最大的支持!

0 人点赞