机器学习的分类
机器学习(监督)的基本概念
机器学习,就是让电脑模仿人进行学习 人在做任何事,也需要学习,比如说考试,需要看文档或者查资料,再或者有人传授。那么这个人在文档中、资料中、听课中,得到一个一个个的问题,以及这些问题所对应的正确答案,对自己进行训练。训练完毕之后,人就会从里边得到一些规则,道理。然后,人会进行自我测试,自己对于自己所学习的知识进行总结,反思,自我审查,看看是否掌握。如果自认为已经掌握,那就进行模拟测试,真实的考验这些知识是否掌握,掌握的程度是多少,以这样的方式来应对未来中未知、同类型知识的真实考试。 那么实际上,机器学习,也是需要走和人一模一样的路线 整理大量的样本数据(资料、文档),以及每个样本中所对应的正确答案,送入给机器,对于机器进行训练,训练完毕之后,机器就会从里边得到一些道理、规则、公式,也就是所谓的模型。之后,我们也可以直接使用这些训练过的数据对于机器进行测试,实际上,就是属于机器自我反省的过程,要是成绩较好,我们可以对于机器进行模拟考试,用一些没有训练过的数据对于机器进行测试,要是成绩还是不错的时候,那我们可以说,这个机器已经真正的掌握的这个知识,那么,就可以去参加真实的考试了(就是部署上线)。 总结,机器学习,就是将大量的有效数据送入机器,机器从数据中得到规则,建立模型,然后传入未知样本给模型,模型对于未知样本进行预测。
学习结果
人在学习的时候,会有俩种情况:
学不会,死学习,死记硬背。结果,要是针对学习内容考试,那就成绩优秀,要是稍微变个花样,那就成绩糟糕。 没学好,学的浅,了解皮毛。拿出学习过的内容原题考试,都成绩糟糕,更别说模拟测试了。好一点的,还能答对几道题,不好的,和蒙的差不多,甚至不如蒙的 机器在学习的时候,也有这俩种情况:
过拟合,俗称,学不好,就往死里学。训练程度太大,过于贴合样本数据,机器不断的去了解样本数据,将样本近乎百分百的还原,不懂得扩展。哪怕是再多的样本,在整个事件、考试的知识范围内,都只能算是少数,所以,对于少数的样本的过于拟合,贴切,导致,机器不懂得变通,在应对未来真实的考试的时候,成绩降低 欠拟合,俗称,略懂一二。学习的时候,并没有了解知识的内涵,真正的规则,只是片面的了解了皮毛。学习、训练得到的模型过于简单,不足以应对目前的知识,所以在训练集和测试集的表现都很糟糕。
反思,改正
不论是死学,还是学的浅,都不是好的现象 根据自己的情况调整自己的学习方式
增加自己的学习量, 多练习题 学习、训练的时候,细心些,多思考,考虑问题全面些 调整自己的学习方式,实际上就是机器学习中调整超参数,正则化,多项式扩展等的过程
算法与模型(个人理解)
模型就是我们需要让机器从大量的样本中找出的规则,规律 那么算法,就是机器从大量数据中找规则,规律的时候,用到的手段 下边,就将开始正题,监督学习中,常用的几个算法 每种算法将分为三个部分组成, 算法背景概述、算法思想解析、算法代码实现
线性回归
线性回归是机器学习-监督学习-回归任务中的一种; 回归分析,就是用来评估自变量和因变量之间关系的统计过程,当自变量x发生改变的时候,因变量y会如何发生改变; 通俗的将,线性回归适应于自变量(特征)和对应的因变量(标签),映射到空间中,大体呈现出偏向线形的情况; 当然,我们在现实世界中,基本上不可能出现完美的线性,只能说,大体上,似线形; 我们希望按照线形的趋势对未来进行预测,并且希望预测的结果尽可能的精准;故而,我们可在这个大体呈现线性的图像中,画出一条线,让这条线,尽可能的距离图像中的所有的点的距离达到最小。 线性回归可以表示为:
y
^
=
w
T
∗
x
+
b
\hat{y} = w ^ {T} * x + b
y ^ = w T ∗ x + b ,我们就是求一个w和b,让在这个w和b的值下,画出的线,与所有的样本点的距离之和达到最小。所谓的线性回归,也就是求这个w和b的过程,通过训练数据,找到这个w和b,然后依据这个w和b,进行预测。
重要库
sklearn.linear_model 该模块提供一些线性的模型。 LinearRegression 线性回归的类, 在linear_model 模块下。 train_test_split 该方法用于切割训练集和测试集,在from sklearn.model_selection 模块下 sklearn中的metrics模块,提供各种对模型进行评估的方法。 r2_score R^ 2 决定系数 R方值。
代码实现
# 得到线性回归的对象
lr = LinearRegression()
# 分裂测试你与训练集,使用训练集对于模型进行训练,得到x与y,使用测试集对于模型进行预测,
# 然后将预测值与测试集原本的标签对比,查看测试的效果
train_X, test_X, train_y, test_y = train_test_split(x, y, test_size=0.25, random_state=0)
# fit 函数,模型的训练方法,要求X是二维数组类型
lr.fit(train_X, train_y)
# 获取模型的参数权重w(不含偏置)。
print(f"权重:{lr.coef_}")
# 获取模型的参数偏置b。
print(f"截距:{lr.intercept_}")
# 当训练好模型之后,模型中的位置参数w与b就确定了。因此,我们就可以使用训练好的模型
# 对未知数据(未知的样本X)进行预测。
# 我们可以调用模型的predict方法来实现预测功能。该方法接收一个参数(数组,即位置样本),并返回
# predict函数,用来预测结果。
result = lr.predict(test_X)
线性回归模型评估
模型评估有很多,最常用的
R
2
R ^ {2}
R 2 ,这个表示 模型拟合性的分值,值越高越好,最高为1,低可能为 负值
代码实现
from sklearn.metrics import r2_score
# 计算R^2 的值。传递y的真实值与预测值。
print(f"训练集R^2:{r2_score(train_y, lr.predict(train_X))}")
print(f"测试集R^2:{r2_score(test_y, result)}")
# 在线性回归模型中,也提供了对R^2的计算。
# 我们可以调用score方法来求解R^2的值
print(f"训练集R^2:{lr.score(train_X, train_y)}")
print(f"测试集R^2:{lr.score(test_X, test_y)}")
二者的差别:
# 对于r2_score,要求传递的是真实标签与预测标签,
# 对于lr.score,需要传递的是样本X与真实标签y。
三种正则化的回归(解决过拟合)
上文说,线性回归就是画一条线,让这条线尽可能的去拟合、穿过线形图形中所有的点,但是现实中,我们的线形图像不可能是一条直直的线,所以我们画出的线与实际肯定会有误差存在。 而当我们一味的去追求让我们画出的线去尽可能的拟合所有的点的时候,就会发生过拟合的情况。就是说,当我们画出一条线,与所有的点都的距离之和达到最小的时候,那随着这条线的趋势,我们的预测值也会尽可能的与真实值的误差达到最小,而发生了过拟合的情况,这条线几乎穿过了所有的现有的点,那这条线的未来的发展趋势我们也不可捉摸,预测值的准确度也就降低了 另外一种叫角度,就是说我们用于训练模型的数据在所有的数据中(包含未知的数据)只是一小部分,我们从这些数据中找出一个通用的规律来,这个规律可能距离实际有些误差,但是可预测性较高,而如果我们近乎完全的去拟合当前的训练数据,那就可以说是将这个模型限制在了当前的数据中,或许在训练集上表现特别的好,但是可预测性不高 站在模型的角度上,就是,模型过于复杂了,将很多不必要的情况(异常情况)都考虑了进去 当发生过拟合的时候,可以发现,模型的参数(w的绝对值)特别的大,可以说,模型的参数过于大,就容易发生过拟合的情况。 所谓正则化,就是通过损失函数,加入关于权重(w)的惩罚项,限制参数过大,减低过拟合。 我们有三种方式加入惩罚项
L2正则化(损失函数+所有的权重的平方和) L1正则化(损失函数+所有权重的绝对值和) Elastic Net(即弹性网络Elastic Net,损失函数+所有权重平方和与所有权重的绝对值和取折中)
重要库
Lasso, Ridge, ElasticNet,分别为L1正则,L2正则,以及弹性网络的包,在linear_model 下。
代码实现
# 导入线性回归,以及进行三种正则化的回归包
from sklearn.linear_model import LinearRegression, Lasso, Ridge, ElasticNet
# 得到L2正则化后的回归类,岭回归,alpha参数指定就是惩罚力度。
# ElasticNet(alpha=0.01, l1_ratio=0.5)) 得到弹性网络,l1_ratio,指L1正则占有比例
ridge = Ridge(alpha=0.01)
# 进行训练
ridge.fit(X, y)
正则化间的比较
L2正则化不会产生稀疏解,L1正则化会产生稀疏解,这也使得LASSO成为一种监督特征选择技术。 如果数据的维度中存在噪音和冗余,稀疏的解可以找到有用的维度并且减少冗余,提高回归预测的准确性和鲁棒性。 Ridge模型具有较高的准确性、鲁棒性以及稳定性,而LASSO模型具有较高的求解速度。 如果既要考虑稳定性也考虑求解的速度,可考虑使用Elasitc Net。
训练集,验证集与测试集
在我们想方设法去建立一个最好的模型的时候,我们不但要选择正确的模型,使用数据对于这个模型进行训练,还要对于模型进行测试,而在训练模型的时候,涉及到模型中超参数的选择问题。 故而,我们需要将原本的训练集再次分化出来,作为验证集,来验证超参数 为了在尽可能的不减少训练样本的情况下,去验证超参数,我们使用交叉验证的方式 交叉验证,测试集不变,在训练集中,我们分成k个部分,然后使用其中的k - 1个部分作为训练集,剩下的一部分作为验证集来对模型进行评估。如此重复的进行k次,最终取k次评估的平均值。这种交叉验证方式我们称为“k折交叉验证”。
必要的库
LassoCV, RidgeCV, ElasticNetCV 分别为 L1正则,L2正则,弹性网络的交叉验证类,在sklearn.linear_model 包下
代码实现
import numpy as np
# 导入交叉验证的各种类
from sklearn.linear_model import LassoCV, RidgeCV, ElasticNetCV
# 定义个超参数
alphas = [0.001,0.005,0.01, 0.05, 0.1, 0.5]
# cv参数设置交叉验证的折数。
Lcv = LassoCV(alphas=alphas,cv=10,max_iter=5000)
# 训练
Lcv.fit(X_train, y_train)
# # 输出最佳的超参数alpha。
Lcv.alpha_
多项式扩展,解决欠拟合问题
当我们选择线性回归来解决问题的时候,会发现,现实数据不一定都线性或者近似线性的,我们可以使用其他的合适模型,或者对于线性模型进行多项式扩展,使模型的覆盖面积扩大 多项式扩展,通俗的讲,可以认为对于现有的数据进行映射到更加高位的空间中,可以拟合更广泛的数据 拟合之后仍然是一个线性的模型 当然,如果多项式扩展的阶数特别多,那可能会产生过拟合情况
扩展的规则
令所有的特征相乘,每个特征都带有一个指数。(指数为非负整数) 令所有特征的指数进行任意值的组合,但是,要保证指数之和小于等于(不大于)扩展的阶数。
必要的库
sklearn.preprocessing 提供关于数据预处理的功能(类)。 PolynomialFeatures,多项式扩展的类,在preprocessing下
代码实现
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
# 进行5阶扩展
poly = PolynomialFeatures(degree=5)
# 对于样本进行训练扩展
X_transform = poly.fit_transform(X)
# 实例化线性回归类
lr = LinearRegression()
# 将多项式扩展之后的数据集传入LinearRegression类,用于训练。
lr.fit(X_transform, y)
流水线,解决简化操作的问题
当我们的数据预处理过程中,可能涉及特别多的步骤,比如说,我们需要转化,拟合,训练,测试,等等,那么这个时候,按部就班的去写代码无疑会有繁琐 创建流水线,多个步骤(环节)合成一个整体,便于我们操作 流水线,将每个评估器视为一个步骤,将多个步骤作为一个整体,依次去执行 流水线的除了最后一个评估器外,必须具有转化功能(transform) 流水线具有最后一个评估器的所有的方法 当使用创建出来的流水线对象来调用函数的时候,会首先对于前n-1个评估器执行transform(如果调用是fit方法,则执行fit_transform方法),然后在最后一个评估器调用我们调用的函数。
必要的库
from sklearn.pipeline import Pipeline , 流水线的类
流水线参数
定义流水线的步骤,提供一个含有元组的列表。元组中含有两个元素。第1个元素为评估器对象的名称,第2个元素为评估器的对象(处理数据的对象)。
代码实现
# 定义流水线的步骤
estimators = [("poly", PolynomialFeatures()), ("lr", LinearRegression())]
# 实例化流水线对象
pipeline = Pipeline(estimators)
# 调用fit方法,在前n-1个评估器执行fit_transform,在最后一个评估器执行fit
pipeline.fit(X, y)
# 对于模型进行评测
score = pipeline.score(X, y)