线性回归
学习目标
- 记忆线性回归的原理过程
- 应用LinearRegression或SGDRegressor实现回归预测
- 记忆回归算法的评估标准及其公式
应用
- 波士顿房价预测
1、 线性回归的原理
1.1 线性回归应用场景\
- 房价预测
- 销售额度预测
- 金融:贷款额度预测、利用线性回归以及系数分析因子
1.2 什么是线性回归
1.2.1定义与公式
线性回归(Linear regression)是利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式。
- 特点:只有一个自变量的情况称为单变量回归,大于一个自变量情况的叫做多元回归
那么怎么理解呢?我们来看几个例子
- 期末成绩:0.7×考试成绩+0.3×平时成
- 房子价格 = 0.02×中心区域的距离 + 0.04×城市一氧化氮浓度 + (-0.12×自住房平均房价) + 0.254×城镇犯罪率
上面两个例子,我们看到特征值与目标值之间建立的一个关系,这个可以理解为回归方程。
1.2.2 线性回归的特征与目标的关系分析
线性回归当中的关系有两种,一种是线性关系,另一种是非线性关系。在这里我们只能画一个平面更好去理解,所以都用单个特征举例子。
- 线性关系
- 多变量线性关系
注释:如果在单特征与目标值的关系呈直线关系,或者两个特征与目标值呈现平面的关系, 更高维度的我们不用自己去想,记住这种关系即可
非线性关系
注释:为什么会这样的关系呢?原因是什么?
我们后面 讲解过拟合欠拟合
重点介绍. 如果是非线性关系,那么回归方程可以理解为:
θ0 + θ1×x1 + θ2×x^2 + θ3×x^3
2、线性回归的损失和优化原理(理解记忆)
假设刚才的房子例子,真实的数据之间存在这样的关系:
1 |
真实房子价格 = 0.02×中心区域的距离 + 0.04×城市一氧化氮浓度 + (-0.12×自住房平均房价) + 0.254×城镇犯罪率 |
那么现在呢,我们随意指定一个关系(猜测), 随机指定关系:
1 |
预测房子价格 = 0.25×中心区域的距离 + 0.14×城市一氧化氮浓度 + 0.42×自住房平均房价 + 0.34×城镇犯罪率 |
请问这样的话,会发生什么?真实结果与我们预测的结果之间是不是存在一定的误差呢?类似这样样子
那么存在这个误差,我们将这个误差给衡量出来
2.1 损失函数
总损失定义为:
y_i
为第i个训练样本的真实值h(x_i)
为第i个训练样本特征值组合预测函数- 又称最小二乘法
如何去减少这个损失,使我们预测的更加准确些?既然存在了这个损失,我们一直说机器学习有自动学习的功能,在线性回归这里更是能够体现。这里可以通过一些优化方法去优化(其实是数学当中的求导功能)回归的总损失!!!
2.2 优化算法
如何去求模型当中的W,使得损失最小?(目的是找到最小损失对应的W值)
线性回归经常使用的两种优化算法
正规方程
理解:X为特征值矩阵,y为目标值矩阵。直接求到最好的结果
缺点:当特征过多过复杂时,求解速度太慢并且得不到结果
损失行数求解1
梯度下降(Gradient Descent)公式:
理解:α为学习速率,需要手动指定(超参数),α旁边的整体表示方向. 沿着这个函数下降的方向找,最后就能找到山谷的最低点,然后更新W值.
使用:面对训练数据规模十分庞大的任务 ,能够找到较好的结果
我们通过两个图更好理解梯度下降的过程
单变量的梯度下降:
多变量的梯度下降:
所以有了梯度下降这样一个优化算法,回归就有了”自动学习”的能力
2.3 优化动态图演示
线性回归优化动态图
3、 线性回归API
- sklearn.linear_model.LinearRegression(fit_intercept=True)
- 通过正规方程优化
- fit_intercept:是否计算偏置
- LinearRegression.coef_:回归系数
- LinearRegression.intercept_:偏置
- sklearn.linear_model.SGDRegressor(loss=”squared_loss”, fit_intercept=True, learning_rate =’invscaling’, eta0=0.01)
- SGDRegressor类实现了随机梯度下降学习,它支持不同的loss函数和正则化惩罚项来拟合线性回归模型。
- loss:损失类型
- loss=”squared_loss”: 普通最小二乘法
- fit_intercept:是否计算偏置
- learning_rate : string, optional
- 学习率填充
- ‘constant’: eta = eta0
- ‘optimal’: eta = 1.0 / (alpha * (t + t0)) [default]
- ‘invscaling’: eta = eta0 / pow(t, power_t)
- power_t=0.25:存在父类当中
- 对于一个常数值的学习率来说,可以使用learning_rate=’constant’ ,并使用eta0来指定学习率。
- SGDRegressor.coef_:回归系数
- SGDRegressor.intercept_:偏置
sklearn提供给我们两种实现的API, 可以根据选择使用
4、波士顿房价预测
数据介绍
属性:
给定的这些特征,是专家们得出的影响房价的结果属性。我们此阶段不需要自己去探究特征是否有用,只需要使用这些特征。到后面量化很多特征需要我们自己去寻找
4.1 分析
回归当中的数据大小不一致,是否会导致结果影响较大。所以需要做标准化处理。同时我们对目标值也需要做标准化处理。
- 数据分割与标准化处理
- 回归预测
- 线性回归的算法效果评估
4.2 回归性能评估
均方误差(Mean Squared Error)MSE)评价机制:
线性回归评估:
注:y^i
为预测值,¯y
为真实值
- sklearn.metrics.mean_squared_error(y_true, y_pred)
- 均方误差回归损失
- y_true:真实值
- y_pred:预测值
- return:浮点数结果
4.2 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
def mylinearregression(): """ 线性回归预测房子价格 :return: """ lb = load_boston() # # print(lb.data) # # print(lb.target) # 对数据集进行划分 x_train, x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.3, random_state=24) # 需要做标准化处理对于特征值处理 std_x = StandardScaler() x_train = std_x.fit_transform(x_train) x_test = std_x.fit_transform(x_test) # print(x_train) # 对于目标值进行标准化 std_y = StandardScaler() y_train = std_y.fit_transform(y_train) y_test = std_y.transform(y_test) y_test = std_y.inverse_transform(y_test) # 使用线性模型进行预测 # 使用正规方程求解 lr = LinearRegression() # # 此时在干什么? lr.fit(x_train, y_train) y_lr_predict = std_y.inverse_transform(lr.predict(x_test)) print(lr.coef_) print("正规方程预测的结果为:", y_lr_predict) print("正规方程的均方误差为:", mean_squared_error(y_test, y_lr_predict)) # 梯度下降进行预测 sgd = SGDRegressor() # sgd.fit(x_train, y_train) print("SGD的权重参数为:", sgd.coef_) # y_sgd_predict = std_y.inverse_transform(sgd.predict(x_test)) # print("SGD的预测的结果为:", y_sgd_predict) # # # 怎么评判这两个方法好坏 print("SGD的均方误差为:", mean_squared_error(y_test, y_sgd_predict)) return None |
我们也可以尝试去修改学习率
1 2 |
sgd = SGDRegressor(learning_rate='constant', eta0=0.001) |
此时我们可以通过调参数,找到学习率效果更好的值。
4.3 正规方程和梯度下降对比
- 文字对比
梯度下降 | 正规方程 |
---|---|
需要选择学习率 | 不需要 |
需要迭代求解 | 一次运算得出 |
特征数量较大可以使用 | 需要计算方程,时间复杂度高O(n3) |
- 选择:
- 小规模数据:
- LinearRegression(不能解决拟合问题)
- 岭回归
- 大规模数据:SGDRegressor
- 小规模数据:
5、拓展-关于优化方法GD、SGD、SAG
5.1 GD
梯度下降(Gradient Descent),原始的梯度下降法需要计算所有样本的值才能够得出梯度,计算量大,所以后面才有会一系列的改进。
5.2 SGD
随机梯度下降(Stochastic gradient descent)是一个优化方法。它在一次迭代时只考虑一个训练样本。
- SGD的优点是:
- 高效
- 容易实现
- SGD的缺点是:
- SGD需要许多超参数:比如正则项参数、迭代数。
- SGD对于特征标准化是敏感的。
5.3 SAG
随机平均梯度法(Stochasitc Average Gradient),由于收敛的速度太慢,有人提出SAG等基于梯度下降的算法
Scikit-learn:SGDRegressor、岭回归、逻辑回归等当中都会有SAG优化
6、总结
- 线性回归的损失函数-均方误差
- 线性回归的优化方法
- 正规方程
- 梯度下降
- 线性回归的性能衡量方法-均方误差
- sklearn的SGDRegressor API 参数
欠拟合与过拟合
- 学习目标
- 说明线性回归(不带正则化)的缺点
- 说明过拟合与欠拟合的原因以及解决方法
问题:训练数据训练的很好啊,误差也不大,为什么在测试集上面有问题呢?
当算法在某个数据集当中出现这种情况,可能就出现了过拟合现象。
1、 什么是过拟合与欠拟合
- 欠拟合
- 过拟合
- 分析
- 第一种情况:因为机器学习到的天鹅特征太少了,导致区分标准太粗糙,不能准确识别出天鹅。
- 第二种情况:机器已经基本能区别天鹅和其他动物了。然后,很不巧已有的天鹅图片全是白天鹅的,于是机器经过学习后,会认为天鹅的羽毛都是白的,以后看到羽毛是黑的天鹅就会认为那不是天鹅。
1.1 定义
- 过拟合:一个假设在训练数据上能够获得比其他假设更好的拟合, 但是在测试数据集上却不能很好地拟合数据,此时认为这个假设出现了过拟合的现象。(模型过于复杂)
- 欠拟合:一个假设在训练数据上不能获得更好的拟合,并且在测试数据集上也不能很好地拟合数据,此时认为这个假设出现了欠拟合的现象。(模型过于简单)
那么是什么原因导致模型复杂?线性回归进行训练学习的时候变成模型会变得复杂,这里就对应前面说的线性回归的两种关系,非线性关系的数据,也就是存在很多无用的特征或者现实中的事物特征跟目标值的关系并不是简单的线性关系。
2、 原因以及解决办法
- 欠拟合原因以及解决办法
- 原因:学习到数据的特征过少
- 解决办法:增加数据的特征数量
- 过拟合原因以及解决办法
- 原因:原始特征过多,存在一些嘈杂特征, 模型过于复杂是因为模型尝试去兼顾各个测试数据点
- 解决办法:
- 正则化
在这里针对回归,我们选择了正则化。但是对于其他机器学习算法如分类算法来说也会出现这样的问题,除了一些算法本身作用之外(决策树、神经网络),我们更多的也是去自己做特征选择,包括之前说的删除、合并一些特征
如何解决?
正则化:
在学习的时候,数据提供的特征有些影响模型复杂度或者这个特征的数据点异常较多,所以算法在学习的时候尽量减少这个特征的影响(甚至删除某个特征的影响),这就是正则化
注:调整时候,算法并不知道某个特征影响,而是去调整参数得出优化的结果
2.1 正则化类别
- L2正则化
- 作用:可以使得其中一些W的都很小,都接近于0,削弱某个特征的影响
- 优点:越小的参数说明模型越简单,越简单的模型则越不容易产生过拟合现象
- 岭(Ridge)回归
- L1正则化
- 作用:可以使得其中一些W的值直接为0,删除这个特征的影响
- LASSO回归
2.2 拓展-原理(了解)
线性回归的损失函数用最小二乘法,等价于当预测值与真实值的误差满足正态分布时的极大似然估计;
岭回归的损失函数,是最小二乘法+L2范数,等价于当预测值与真实值的误差满足正态分布,且权重值也满足正态分布(先验分布)时的最大后验估计;
LASSO的损失函数,是最小二乘法+L1范数,等价于等价于当预测值与真实值的误差满足正态分布,且且权重值满足拉普拉斯分布(先验分布)时的最大后验估计
线性回归的改进-岭回归
- 学习目标
- 说明岭回归的原理即与线性回归的不同之处
- 说明正则化对于权重参数的影响
- 说明L1和L2正则化的区别
- 实际应用
- 波士顿房价预测
1、 带有L2正则化的线性回归-岭回归
岭回归,其实也是一种线性回归。只不过在算法建立回归方程时候,加上正则化的限制,从而达到解决过拟合的效果
1.1 API
- sklearn.linear_model.Ridge(alpha=1.0, fit_intercept=True,solver=”auto”, normalize=False)
- 具有l2正则化的线性回归
- alpha:正则化力度,也叫 λ
- λ取值:0~1 1~10
- solver:会根据数据自动选择优化方法
- sag:如果数据集、特征都比较大,选择该随机梯度下降优化
- normalize:数据是否进行标准化
- normalize=False:可以在fit之前调用preprocessing.StandardScaler标准化数据
- Ridge.coef_:回归权重
- Ridge.intercept_:回归偏置
1 2 3 |
All last four solvers support both dense and sparse data. However, only 'sag' supports sparse input when `fit_intercept` is True. |
Ridge方法相当于SGDRegressor(penalty=’l2′, loss=”squared_loss”),只不过SGDRegressor实现了一个普通的随机梯度下降学习,推荐使用Ridge(实现了SAG)
- sklearn.linear_model.RidgeCV(_BaseRidgeCV, RegressorMixin)
- 具有l2正则化的线性回归,可以进行交叉验证
- coef_:回归系数
1 2 3 4 5 6 |
class _BaseRidgeCV(LinearModel): def __init__(self, alphas=(0.1, 1.0, 10.0), fit_intercept=True, normalize=False, scoring=None, cv=None, gcv_mode=None, store_cv_values=False): |
1.2 观察正则化程度的变化,对结果的影响?
- 正则化力度越大,权重系数会越小
- 正则化力度越小,权重系数会越大
1.3 波士顿房价预测
1 2 3 4 5 6 7 8 9 10 11 |
rd = Ridge(alpha=1.0) rd.fit(x_train, y_train) print("岭回归的权重参数为:", rd.coef_) y_rd_predict = std_y.inverse_transform(rd.predict(x_test)) print("岭回归的预测的结果为:", y_rd_predict) print("岭回归的均方误差为:", mean_squared_error(y_test, y_rd_predict)) |
分类算法-逻辑回归与二分类
- 学习目标
- 说明逻辑回归的损失函数
- 说明逻辑回归的优化方法
- 说明sigmoid函数
- 知道逻辑回归的应用场景
- 知道精确率、召回率指标的区别
- 知道F1-score指标说明召回率的实际意义
- 说明如何解决样本不均衡情况下的评估
- 了解ROC曲线的意义说明AUC指标大小
- 应用classification_report实现精确率、召回率计算
- 应用roc_auc_score实现指标计算
- 具体应用
- 二分类问题
- 癌症患者预测
- 皮马印第安人糖尿病预测
- 二分类问题
逻辑回归(Logistic Regression)是机器学习中的一种分类模型,逻辑回归是一种分类算法,虽然名字中带有回归,但是它与回归之间有一定的联系, 根据数据特征计算属于某一类别的概率p(x), 根据概率数值判断其所属类别 。由于算法的简单和高效,在实际中应用非常广泛。
1、逻辑回归的应用场景
- 广告点击率
- 是否为垃圾邮件
- 是否患病
- 金融诈骗
- 虚假账号
看到上面的例子,我们可以发现其中的特点,那就是都属于两个类别之间的判断, 比如是不是垃圾邮件,是猫或是狗. 逻辑回归就是解决二分类问题的利器。
(神经网络模型底层也是基于逻辑回归实现的)
2、 逻辑回归的原理
2.1 输入
逻辑回归的输入就是一个线性回归的结果。
2.2 激活函数
- sigmoid函数
特征值x的概率P(x)等于:
当概率大于等于0.5, 输出y=1;
当概率小于0.5, 输出y=0
其中,y为类别结果, P为概率,x为特征值,θ为常量
- 分析
- 回归的结果输入到sigmoid函数当中
- 输出结果:[0, 1]区间中的一个概率值,默认为0.5为阈值
逻辑回归最终的分类是通过属于某个类别的概率值来判断是否属于某个类别,并且这个类别默认标记为1(正例),另外的一个类别会标记为0(反例)。(方便损失计算)
输出结果解释(重要):假设有两个类别A,B,并且假设我们的概率值为属于A(1)这个类别的概率值。现在有一个样本的输入到逻辑回归输出结果0.6,那么这个概率值超过0.5,意味着我们训练或者预测的结果就是A(1)类别。那么反之,如果得出结果为0.3那么,训练或者预测结果就为B(0)类别。
所以接下来我们回忆之前的线性回归预测结果我们用均方误差衡量,那如果对于逻辑回归,我们预测的结果不对该怎么去衡量这个损失呢?我们来看这样一张图
那么如何去衡量逻辑回归的预测结果与真实结果的差异呢?
2.3 损失以及优化
2.3.1 损失
逻辑回归的损失,称之为对数似然损失,公式如下:
- 分开类别:
单个对数似然损失
怎么理解单个的式子呢?这个要根据log的函数图像来理解。
当y=1时:
- 综合完整损失函数
看到这个式子,其实跟我们讲的信息熵类似。
接下来我们呢就带入上面那个例子来计算一遍,就能理解意义了。
我们已经知道,log(P), P值越大,结果越小,所以我们可以对着这个损失的式子去分析
2.3.2 优化
同样使用梯度下降优化算法,去减少损失函数的值。这样去更新逻辑回归前面对应算法的权重参数,提升原本属于1类别的概率,降低原本是0类别的概率。
3、逻辑回归API
- sklearn.linear_model.LogisticRegression(solver=’liblinear’, penalty=‘l2’, C = 1.0)
- solver:优化求解方式(默认开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数)
- sag:根据数据集自动选择,随机平均梯度下降
- penalty:正则化的种类
- C:正则化力度
- solver:优化求解方式(默认开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数)
默认将类别数量少的当做正例
LogisticRegression方法相当于 SGDClassifier(loss=”log”, penalty=” “),SGDClassifier实现了一个普通的随机梯度下降学习,也支持平均随机梯度下降法(ASGD),可以通过设置average=True。而使用LogisticRegression(实现了SAG)
4、 案例:癌症分类预测-良/恶性乳腺癌肿瘤预测
- 数据介绍
原始数据的下载地址:https://archive.ics.uci.edu/ml/machine-learning-databases/
数据描述
(1)699条样本,共11列数据,第一列用语检索的id,后9列分别是与肿瘤
相关的医学特征,最后一列表示肿瘤类型的数值。
(2)包含16个缺失值,用”?”标出。
4.1 分析
- 缺失值处理
- 标准化处理
- 逻辑回归预测
4.2 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
def logisticregression(): """ 逻辑回归进行癌症预测 :return: None """ # 1、读取数据,处理缺失值以及标准化 column_name = ['Sample code number', 'Clump Thickness', 'Uniformity of Cell Size', 'Uniformity of Cell Shape', 'Marginal Adhesion', 'Single Epithelial Cell Size', 'Bare Nuclei', 'Bland Chromatin', 'Normal Nucleoli', 'Mitoses', 'Class'] data = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data", names=column_name) # 删除缺失值 data = data.replace(to_replace='?', value=np.nan) data = data.dropna() # 取出特征值 x = data[column_name[1:10]] y = data[column_name[10]] # 分割数据集 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3) # 进行标准化 std = StandardScaler() x_train = std.fit_transform(x_train) x_test = std.transform(x_test) # 使用逻辑回归 lr = LogisticRegression() lr.fit(x_train, y_train) print("得出来的权重:", lr.coef_) # 预测类别 print("预测的类别:", lr.predict(x_test)) # 得出准确率 print("预测的准确率:", lr.score(x_test, y_test)) return None |
在很多分类场景当中我们不一定只关注预测的准确率!!!!!
比如以这个癌症举例子!!!我们并不关注预测的准确率,而是关注在所有的样本当中,癌症患者有没有被全部预测(检测)出来。
5. 案例: 皮马印第安人糖尿病预测
皮马印第安人糖尿病数据集介绍
数据集来自Kaggle, 也可以从飞浆公开数据集中下载
需求: 根据给定皮马印第安人的样本信息, 包括怀孕次数, 胰岛素水平, 体重指数, 年龄四个特征, 预测是否患有糖尿病(二分类)
导入数据集
1 2 3 4 5 6 7 8 9 10 |
import pandas as pd path = '../data/pima-indians-diabetes.csv' pima = pd.read_csv(path) # 由于csv文件中缺少表头第一行描述信息, 下面将描述信息插入到第一行 pima.loc[-1] = pima.columns.tolist() pima.index = pima.index + 1 pima.sort_index(inplace=True) pima.columns = ['pregnant', 'glucose', 'bp', 'skin', 'insulin', 'bmi', 'pedigree', 'age', 'label'] pima.head() |
输出
pregnant | glucose | bp | skin | insulin | bmi | pedigree | age | label | |
---|---|---|---|---|---|---|---|---|---|
0 | 6 | 148 | 72 | 35 | 0 | 33.6 | 0.627 | 50 | 1 |
1 | 1 | 85 | 66 | 29 | 0 | 26.6 | 0.351 | 31 | 0 |
2 | 8 | 183 | 64 | 0 | 0 | 23.3 | 0.672 | 32 | 1 |
3 | 1 | 89 | 66 | 23 | 94 | 28.1 | 0.167 | 21 | 0 |
4 | 0 | 137 | 40 | 35 | 168 | 43.1 | 2.288 | 33 | 1 |
保存特征和标签到变量中
1 2 3 4 5 6 |
# X y赋值 feature_names = ['pregnant', 'insulin', 'bmi', 'age'] X = pima[feature_names] y = pima.label # 避免后续在logreg.fit时不识别标签的类型object y= y. astype('int') |
1 2 3 |
# 维度确认 print(X.shape) print(y.shape) |
1 2 |
(768, 4) (768,) |
将数据集合分割为训练集和测试集
1 2 3 |
# 数据分离 from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0) |
训练模型
1 2 3 4 |
# 模型训练 from sklearn.linear_model import LogisticRegression logreg = LogisticRegression() logreg.fit(X_train, y_train) |
确认模型
1 2 3 4 5 |
LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True, intercept_scaling=1, l1_ratio=None, max_iter=100, multi_class='auto', n_jobs=None, penalty='l2', random_state=None, solver='lbfgs', tol=0.0001, verbose=0, warm_start=False) |
使用模型预测结果
1 2 |
# 测试数据集结果预测 y_pred = logreg.predict(X_test) |
计算准确率
1 2 3 |
# 使用准确率进行评估 from sklearn import metrics print(metrics.accuracy_score(y_test, y_pred)) |
1 |
0.6770833333333334 |
确认正负样本数据量
1 2 |
# 确认正负样本数据量 y_test.value_counts() |
输出:
1 2 3 |
0 130 1 62 Name: label, dtype: int64 |
判断为正确(1)的比例:
1 2 |
# 1的比例 y_test.mean() |
输出:
1 |
0.3229166666666667 |
判断为正确(0)的比例:
1 2 |
# 0的比例 1 - y_test.mean() |
输出:
1 |
0.6770833333333333 |
空准确率:
1 2 |
# 空准确率(都预测了占比多的标签时的正确率) max(y_test.mean(), 1 -y_test.mean()) |
输出:
1 |
0.6770833333333333 |
发现总的准确率还不如空准确率, 所以这个模型看起来并不是很成功 结论, 分类准确率只能衡量整体预测效果, 但是没有反映真实细节信息
1 2 3 |
# 比对前面25组样本的正样本的预测情况 print(y_test.values[:25]) print(y_pred[:25] ) |
输出:
1 2 |
[1 0 0 1 0 0 1 1 0 0 1 1 0 0 0 0 1 0 0 0 1 1 0 0 0] [0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0] |
6、分类的评估方法
使用准确率进行模型评估的局限性
模型评估回顾
- 目的: 通过模型评估对比模型表现, 确定合适的模型参数
- 方法: 计算测试数据集预测准确率以评估模型表现
使用准确率预测的局限性:
- 无法真实反映模型针对各分类的预测准确度
比如对于0-1预测的准确率:
准确率的评估只能看到整体, 无法得知细节, 比如:
比如1000个数据(900个实际分类是1,100个实际分类是0)
全部预测为1 , 整体准确率是90%
虽然1的准确率是100%, 而0被全部预测为1错误率100%就有大问题了.
6.1 混淆矩阵, 模型衡量指标及其意义
为了解决上述问题, 为了衡量分类算法的准确程度, 这里引入了混淆矩阵, 又称为误差矩阵
6.1.1混淆矩阵
在分类任务下,预测结果(Predicted Condition)与正确标记(True Condition)之间存在四种不同的组合,构成混淆矩阵(适用于多分类)
把样本分成四类:真正例 (TP), 伪正例(FP), 真反例(TN) , 伪 反 例(FN)
6.1.2 混淆矩阵的六个指标:
混淆矩阵指标的特点:
- 分类任务中, 相比单一的预测准确率, 混淆矩阵提供了更全面的模型评估信息
- 通过混淆矩阵, 我们可以计算出多样的模型表现衡量指标, 从而更好的选择模型
哪个指标更关键?
- 取决应用场景
- 对于垃圾邮件检测来说, 正样本为”垃圾邮件”, 希望普通邮件(负样本)不要被判断为垃圾邮件(正样本)
- 希望判断为垃圾邮件的样本都是判断正确的, 需要关注精确率
- 希望所有的垃圾邮件都能尽可能被判断出来, 还需要关注召回率
- 对于异常交易检测来说, 正样本为”异常交易”
- 希望所有的异常交易都被检测到,即判断为正常的交易中尽可能不存在异常交易, 需要关注特异度
那精确率(Precision)与召回率(Recall)来比较:
- 精确率:从你预测结果为正例的样本中, 找出真实也为正例的样本的比例
- 召回率:在真实为正例的样本中, 找出全部预测结果为正例的样本所占比例(查的全,对正样本的区分能力)
那么怎么更好理解这个两个概念,看下图:
还有其他的评估标准,F1-score,反映了模型的稳健型
下面使用混淆矩阵来对上述皮马印第安人糖尿病预测模型进行评估:
计算并展示混淆矩阵
1 2 3 |
# 计算并展示混淆矩阵 confution_matrix = metrics.confusion_matrix(y_test, y_pred) print(confution_matrix) |
1 2 |
[[114 16] [ 46 16]] |
计算从混淆矩阵得来的各种指标:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# 将矩阵中的四个结果赋值 TN = confution_matrix[0, 0] FP = confution_matrix[0, 1] FN = confution_matrix[1, 0] TP = confution_matrix[1, 1] # 计算指标 # 精确度 - 整体样本中预测正确的比率, 和前面得出的准确率结果相等 accuracy = (TP + TN)/(TP + TN + FP + FN) print("accuracy_rate: ", accuracy) # 错误率 - 整体样本中预测错误的比率, 可以用 (100% - 精确度) 直接得出 miss_rate = 1 - accuracy print("miss_rate: ", accuracy) # 召回率 - 在你认为是正样本的样本中, 预测正确的比率 recall = TP/(TP + FN) print("recall_rate: ", recall) # 特异度 - 在你认为是负样本的样本中, 预测正确的比率 specificity = TN/(TN + FP) print("specificity_rate: ", specificity) # 精确率 - 在预测结果为正的样本中, 预测正确的比率 precision = TP/(TP + FP) print("precision_rate: ", precision) # F1分数 - 综合 precision 和 recall 的一个判断指标 f1_score = (2 * precision * recall)/(precision + recall) print("f1_score: ", precision) |
1 2 3 4 5 6 |
accuracy_rate: 0.6770833333333334 miss_rate: 0.6770833333333334 recall_rate: 0.25806451612903225 specificity_rate: 0.8769230769230769 precision_rate: 0.5 f1_score: 0.5 |
观察以上结果, 发现这个模型还是很有问题的, 最大的问题就是召回率过低 – 即在你认为是负样本的样本中预测正确的成功几率过低. 当然最终需要得到什么样的模型, 还是取决于实际应用.
6.1.3 分类评估报告API
- sklearn.metrics.classification_report(y_true, y_pred, labels=[], target_names=None )
- y_true:真实目标值
- y_pred:估计器预测目标值
- labels:指定类别对应的数字
- target_names:目标类别名称
- return:每个类别精确率与召回率
1 2 |
print("精确率和召回率为:", classification_report(y_test, lr.predict(x_test), labels=[2, 4], target_names=['良性', '恶性'])) |
假设这样一个情况,如果99个样本癌症,1个样本非癌症,不管怎样我全都预测正例(默认癌症为正例),准确率就为99%但是这样效果并不好,这就是样本不均衡下的评估问题
问题:如何衡量样本不均衡下的评估?
6.2 ROC曲线与AUC指标
6.2.1 知道TPR与FPR
- TPR = TP / (TP + FN)
- 所有真实类别为1的样本中,预测类别为1的比例
- FPR = FP / (FP + FN)
- 所有真实类别为0的样本中,预测类别为1的比例
6.2.2 ROC曲线
- ROC曲线的横轴就是FPRate,纵轴就是TPRate,当二者相等时,表示的意义则是:对于不论真实类别是1还是0的样本,分类器预测为1的概率是相等的,此时AUC为0.5
6.2.3AUC指标
- AUC的概率意义是随机取一对正负样本,正样本得分大于负样本的概率
- AUC的最小值为0.5,最大值为1,取值越高越好
- AUC=1,完美分类器,采用这个预测模型时,不管设定什么阈值都能得出完美预测。绝大多数预测的场合,不存在完美分类器。
- 0.5<AUC<1,优于随机猜测。这个分类器(模型)妥善设定阈值的话,能有预测价值。
最终AUC的范围在[0.5, 1]之间,并且越接近1越好
6.2.4 AUC计算API
- from sklearn.metrics import roc_auc_score
- sklearn.metrics.roc_auc_score(y_true, y_score)
- 计算ROC曲线面积,即AUC值
- y_true:每个样本的真实类别,必须为0(反例),1(正例)标记
- y_score:每个样本预测的概率值
- sklearn.metrics.roc_auc_score(y_true, y_score)
1 2 3 4 5 |
# 0.5~1之间,越接近于1约好 y_test = np.where(y_test > 2.5, 1, 0) print("AUC指标:", roc_auc_score(y_test, lr.predict(x_test))) |
6.2.5、总结
- AUC只能用来评价二分类
- AUC非常适合评价样本不平衡中的分类器性能
模型保存和加载
- 学习目标
- 应用joblib实现模型的保存与加载
当训练或者计算好一个模型之后,那么如果别人需要我们提供结果预测,就需要保存模型(主要是保存算法的参数)
1、sklearn模型的保存和加载API
- from sklearn.externals import joblib
- 保存:joblib.dump(rf, ‘test.pkl’)
- 加载:estimator = joblib.load(‘test.pkl’)
2、线性回归的模型保存加载案例
- 保存
1 2 3 4 5 6 7 8 |
# 使用线性模型进行预测 # 使用正规方程求解 lr = LinearRegression() # 此时在干什么? lr.fit(x_train, y_train) # 保存训练完结束的模型 joblib.dump(lr, "test.pkl") |
- 加载
1 2 3 |
# 通过已有的模型去预测房价 model = joblib.load("test.pkl") print("从文件加载进来的模型预测房价的结果:", std_y.inverse_transform(model.predict(x_test))) |
无监督学习-K-means算法
- 学习目标
- 说明K-means算法原理
- 说明K-means的性能评估标准轮廓系数
- 说明K-means的优缺点
- 实际应用
- instacart用户聚类
回忆非监督学习的特点?
1、 什么是无监督学习
- 一家广告平台需要根据相似的人口学特征和购买习惯将美国人口分成不同的小组,以便广告客户可以通过有关联的广告接触到他们的目标客户。
- Airbnb 需要将自己的房屋清单分组成不同的社区,以便用户能更轻松地查阅这些清单。
- 一个数据科学团队需要降低一个大型数据集的维度的数量,以便简化建模和降低文件大小。
我们可以怎样最有用地对其进行归纳和分组?我们可以怎样以一种压缩格式有效地表征数据?这都是无监督学习的目标,之所以称之为无监督,是因为这是从无标签的数据开始学习的。
2、 无监督学习包含算法
- 聚类
- K-means(K均值聚类)
- 降维
- PCA
3、 K-means原理
我们先来看一下一个K-means的聚类效果图
3.1 K-means聚类步骤
- 1、随机设置K个特征空间内的点作为初始的聚类中心
- 2、对于其他每个点计算到K个中心的距离,未知的点选择最近的一个聚类中心点作为标记类别
- 3、接着对着标记的聚类中心之后,重新计算出每个聚类的新中心点(平均值)
- 4、如果计算得出的新中心点与原中心点一样,那么结束,否则重新进行第二步过程
我们以一张图来解释效果
4、K-meansAPI
- sklearn.cluster.KMeans(n_clusters=8,init=‘k-means++’)
- k-means聚类
- n_clusters:开始的聚类中心数量
- init:初始化方法,默认为’k-means ++’
- labels_:默认标记的类型,可以和真实值比较(不是值比较)
5、 案例:k-means对Instacart Market用户聚类
5.1 分析
- 1、降维之后的数据
- 2、k-means聚类
- 3、聚类结果显示
5.2 代码
1 2 3 4 5 6 |
# 取500个用户进行测试 cust = data[:500] km = KMeans(n_clusters=4) km.fit(cust) pre = km.predict(cust) |
问题:如何去评估聚类的效果呢?
6、Kmeans性能评估指标
6.1 轮廓系数
轮廓系数公式:
注:对于每个点i 为已聚类数据中的样本 ,b_i 为i 到其它族群的所有样本的距离最小值,a_i 为i 到本身簇的距离平均值。最终计算出所有的样本点的轮廓系数平均值
6.2 轮廓系数值分析
- 分析过程(我们以一个蓝1点为例)
- 1、计算出蓝1离本身族群所有点的距离的平均值a_i
- 2、蓝1到其它两个族群的距离计算出平均值红平均,绿平均,取最小的那个距离作为b_i
- 根据公式:极端值考虑:如果b_i >>a_i: 那么公式结果趋近于1;如果a_i>>>b_i: 那么公式结果趋近于-1
6.3 结论
如果b_i>>a_i:趋近于1效果越好, b_i<<a_i:趋近于-1,效果不好。轮廓系数的值是介于 [-1,1] ,越趋近于1代表内聚度和分离度都相对较优。
6.4 轮廓系数API
- sklearn.metrics.silhouette_score(X, labels)
- 计算所有样本的平均轮廓系数
- X:特征值
- labels:被聚类标记的目标值
6.5 用户聚类结果评估
1 |
silhouette_score(cust, pre) |
7、K-means总结
- 特点分析:采用迭代式算法,直观易懂并且非常实用
- 缺点:容易收敛到局部最优解(多次聚类)
注意:聚类一般做在分类之前
课后回顾
1、线性回归的参数求解的方法是什么?
答案: 正规方程和梯度下降
2、什么是过拟合? 原因有哪些?
答案: 过拟合就是训练误差很小, 但是测试误差很大
原因有: 样本偏差, 模型过于复杂
3、分类问题, 回归问题, 聚类问题的评估方法分别是什么?
答案: 分类问题的评估方法是准确率, 精确率和召回率
回归问题的评估方法是均方差
聚类问题的评估方法是轮廓系数
机器学习的算法选择
以上我们学习了这么多种有关机器学习的算法, 那么面对具体问题的时候该如何选择呢?
sklearn的官方手册给出了一份 cheat sheet, 可以简单的解决你的困惑.
英文版
中文版
Views: 284