分类算法的目标值是离散型的
如果目标值是连续型的值,就需要回归算法
比如房价预测、销售额预测、贷款额度预测等
回归算法-线性回归分析
举个栗子
期末成绩:0.7×考试成绩+0.3×平时成绩(各个特征跟某个值组合在一起去预测)
西瓜好坏:0.2×色泽+0.5×根蒂+0.3×敲声(把回归问题转换为分类问题)
线性关系模型
一个通过属性的线性组合来进行预测的函数:
线性回归
定义:线性回归通过一个或者多个自变量与因变量之间之间进行建模的回归分析。其中特点为一个或多个称为回归系数的模型参数的线性组合
一元线性回归:涉及到的变量只有一个
多元线性回归:涉及到的变量两个或两个以上
通用公式:
其中w,x为矩阵:
属性和权重的一种组合来预测结果
矩阵也是大多数算法的计算基础
矩阵乘法:
(这线性代数我是记不住咯…)
预测结果与真实值是有一定的误差
单变量:
多变量:
回归算法是迭代的算法
损失函数(误差大小)
- y_i为第i个训练样本的真实值
- h_w (x_i)为第i个训练样本特征值组合预测函数
总损失定义:
又称最小二乘法
如何去求模型当中的W,使得损失最小?(目的是找到最小损失对应的W值)
最小二乘法之正规方程
求解:
为特征值矩阵,为目标值矩阵
缺点:当特征过于复杂,求解速度太慢
对于复杂的算法,不能使用正规方程求解(逻辑回归等)
损失函数直观图(单变量举例)
直接求解到最小值
最小二乘法之梯度下降
我们以单变量中的w0,w1为例子:
理解:沿着这个函数下降的方向找,最后就能找到山谷的最低点,然后更新W值
使用:面对训练数据规模十分庞大的任务
sklearn线性回归正规方程、梯度下降API
正规方程: sklearn.linear_model.LinearRegression
梯度下降: sklearn.linear_model.SGDRegressor
LinearRegression、SGDRegressor
普通最小二乘线性回归
- sklearn.linear_model.LinearRegression()
- coef_:回归系数
通过使用SGD最小化线性模型
- sklearn.linear_model.SGDRegressor( )
- coef_:回归系数
波士顿房价数据案例分析流程
波士顿地区房价数据获取
波士顿地区房价数据分割
训练与测试数据标准化处理
使用最简单的线性回归模型LinearRegression和梯度下降估计SGDRegressor对房价进行预测
属性名 | 解释 | 类型 |
---|---|---|
CRIM | 城镇人均犯罪率 | 连续值 |
ZN | 住宅用地超过 25000 sq.ft. 的比例 | 连续值 |
INDUS | 城镇非零售商用土地的比例 | 连续值 |
CHAS | 查理斯河空变量(如果边界是河流, 则为1; 否则为0) | 离散值 |
NOX | 一氧化氮浓度 | 连续值 |
RM | 住宅平均房间数 | 连续值 |
AGE | 1940 年之前建成的自用房屋比例 | 连续值 |
DIS | 到波士顿五个中心区域的加权距离 | 连续值 |
RAD | 辐射性公路的接近指数 | 连续值 |
TAX | 每 10000 美元的全值财产税率 | 连续值 |
PTRATIO | 城镇师生比例 | 连续值 |
B | 1000(Bk-0.63)^ 2,其中 Bk 指代城镇中黑人的比例 | 连续值 |
LSTAT | 人口中地位低下者的比例 | 连续值 |
这个数据集一共有13个特征,所以我们需要求出13个权重
正规方程
from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression, SGDRegressor
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
def mylinear():
"""
线性回归直接预测房子价格
:return: None
"""
# 获取数据
lb = load_boston()
# 分割数据集到训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.25)
# 进行标准化处理(目标值要进行标准化处理)
# 特征值和目标值都必须进行标准化处理, 实例化两个标准化API
std_x = StandardScaler()
x_train = std_x.fit_transform(x_train)
x_test = std_x.transform(x_test)
# 目标值
std_y = StandardScaler()
y_train = std_y.fit_transform(y_train.reshape(-1, 1))
y_test = std_y.transform(y_test.reshape(-1, 1))
# estimator预测
# 正规方程求解方式预测结果
lr = LinearRegression()
lr.fit(x_train, y_train)
print(lr.coef_)
# 预测测试集的房子价格
y_lr_predict = std_y.inverse_transform(lr.predict(x_test))
print("正规方程测试集里面每个房子的预测价格: ", y_lr_predict)
print("正规方程的均方误差: ", mean_squared_error(std_y.inverse_transform(y_test), y_lr_predict))
if __name__ == "__main__":
mylinear()
梯度下降
from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression, SGDRegressor
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
def mylinear():
"""
线性回归直接预测房子价格
:return: None
"""
# 获取数据
lb = load_boston()
# 分割数据集到训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.25)
# 进行标准化处理(目标值要进行标准化处理)
# 特征值和目标值都必须进行标准化处理, 实例化两个标准化API
std_x = StandardScaler()
x_train = std_x.fit_transform(x_train)
x_test = std_x.transform(x_test)
# 目标值
std_y = StandardScaler()
y_train = std_y.fit_transform(y_train.reshape(-1, 1))
y_test = std_y.transform(y_test.reshape(-1, 1))
# estimator预测
# 梯度下降进行房价预测
sgd = SGDRegressor()
sgd.fit(x_train, y_train)
print(sgd.coef_)
# 预测测试集的房子价格
y_sgd_predict = std_y.inverse_transform(sgd.predict(x_test))
print("梯度下降测试集里面每个房子的预测价格: ", y_sgd_predict)
print("梯度下降的均方误差: ", mean_squared_error(std_y.inverse_transform(y_test), y_lr_predict))
if __name__ == "__main__":
mylinear()
回归性能评估
(均方误差(Mean Squared Error)MSE) 评价机制:
这个非常简单,就是你的预测值和真实值之间的差值的平方和求一个平均值
sklearn回归评估API
sklearn.metrics.mean_squared_error
mean_squared_error
mean_squared_error(y_true, y_pred)
- 均方误差回归损失
- y_true:真实值
- y_pred:预测值
- return:浮点数结果
注:真实值,预测值为标准化之前的值
官方给我们的一些建议
正规方程与梯度下降的对比
梯度下降 | 正规方程 |
---|---|
需要选择学习率α | 不需要 |
需要多次迭代 | 一次运算得出 |
当特征数量n大时也能较好适用 | 需要计算(XTX)-1 如果特征数量n较大则运算代价大,因为矩阵逆的计算时间复杂度为O(n^3),通常来说当n小于10000时还是可以接受的 |
适用于各种类型的模型 | 只适用于线性模型,不适合逻辑回归模型等其他模型 |
线性回归器是最为简单、易用的回归模型。
从某种程度上限制了使用,尽管如此,在不知道特征之间关系的前提下,我们仍然使用线性回归器作为大多数系统的首要选择。
- 小规模数据:LinearRegression(不能解决拟合问题)以及其它
- 大规模数据:SGDRegressor
过拟合与欠拟合
问题:训练数据训练的很好啊,误差也不大,为什么在测试集上面有问题呢?
分析图1:
经过训练后,知道了天鹅是有翅膀的,天鹅的嘴巴是长长的。简单的认为有这些特征的都是天鹅。因为机器学习到的天鹅特征太少了,导致区分标准太粗糙,不能准确识别出天鹅。
分析图2:
机器通过这些图片来学习天鹅的特征,经过训练后,知道了天鹅是有翅膀的,天鹅的嘴巴是长长的弯曲的,天鹅的脖子是长长的有点曲度,天鹅的整个体型像一个"2"且略大于鸭子。这时候机器已经基本能区别天鹅和其他动物了。然后,很不巧已有的天鹅图片全是白天鹅的,于是机器经过学习后,会认为天鹅的羽毛都是白的,以后看到羽毛是黑的天鹅就会认为那不是天鹅。
过拟合与欠拟合
过拟合:一个假设在训练数据上能够获得比其他假设更好的拟合, 但是在训练数据外的数据集上却不能很好地拟合数据,此时认为这个假设出现了过拟合的现象。(模型过于复杂)
欠拟合:一个假设在训练数据上不能获得更好的拟合, 但是在训练数据外的数据集上也不能很好地拟合数据,此时认为这个假设出现了欠拟合的现象。(模型过于简单)
对线性模型进行训练学习会变成复杂模型
欠拟合原因以及解决办法
- 原因:学习到数据的特征过少
- 解决办法:增加数据的特征数量
过拟合原因以及解决办法
原因:原始特征过多,存在一些嘈杂特征, 模型过于复杂是因为模型尝试去兼顾各个测试数据点,数据的特征和目标值之间不仅仅是线性关系
-
解决办法:
- 进行特征选择,消除关联性大的特征(很难做)
- 交叉验证(让所有数据都有过训练)
- 正则化
回忆一下特征选择方法:
- 过滤式:低方差特征
- 嵌入式:正则化,决策树,神经网络
L2正则化
作用:可以使得W的每个元素都很小,都接近于0
优点:越小的参数说明模型越简单,越简单的模型则越不容易产生过拟合现象
线性回归:LinearRegression 容易出现过拟合,为了把训练接数据表现更好
L2正则化:Ridge:岭回归 带有正则化的线性回归 解决过拟合
岭回归
带有正则化的线性回归-Ridge
sklearn.linear_model.Ridge
Ridge
具有l2正则化的线性最小二乘法
- sklearn.linear_model.Ridge(alpha=1.0)
- alpha:正则化力度
- coef_:回归系数
观察正则化程度的变化,对结果的影响
正则化力度越来越大,模型越来越简单
from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression, SGDRegressor, Ridge
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
def mylinear():
"""
线性回归直接预测房子价格
:return: None
"""
# 获取数据
lb = load_boston()
# 分割数据集到训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.25)
# 进行标准化处理(目标值要进行标准化处理)
# 特征值和目标值都必须进行标准化处理, 实例化两个标准化API
std_x = StandardScaler()
x_train = std_x.fit_transform(x_train)
x_test = std_x.transform(x_test)
# 目标值
std_y = StandardScaler()
y_train = std_y.fit_transform(y_train.reshape(-1, 1))
y_test = std_y.transform(y_test.reshape(-1, 1))
# estimator预测
# 岭回归去进行房价预测
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(std_y.inverse_transform(y_test), y_rd_predict))
if __name__ == "__main__":
mylinear()
线性回归 LinearRegression与Ridge对比
岭回归:回归得到的回归系数更符合实际,更可靠。另外,能让估计参数的波动范围变小,变的更稳定。在存在病态数据偏多的研究中有较大的实用价值。
模型的保存与加载
import joblib
保存:joblib.dump(rf, 'test.pkl')
加载:estimator = joblib.load('test.pkl')
注:文件格式pkl
分类算法-逻辑回归
他叫逻辑回归…可他是分类算法
逻辑回归:线性回归的式子作为逻辑回归的输入,适用于二分类场景,他也能得出概率值
- 广告点击率
- 判断用户的性别
- 预测用户是否会购买给定的商品类
- 判断一条评论是正面的还是负面的
逻辑回归是解决二分类问题的利器
逻辑回归
输入:
sigmoid函数
逻辑回归的输入-sigmoid→分类
sigmodid函数会把值映射到[0, 1],也就是把我们的输入值转换成一个概率值
逻辑回归公式
公式:
输出:[0,1]区间的概率值,默认0.5作为阀值
注:g(z)为sigmoid函数
逻辑回归的损失函数、优化
与线性回归原理相同,但由于是分类问题,损失函数不一样,只能通过梯度下降求解
对数似然损失函数:
完整的损失函数:
cost损失的值越小,那么预测的类别准确度更高
损失函数:
- 均方误差:不存在多个局部最低点,只有一个最小值
- 对数似然损失:多个局部最小值
对数似然损失求出来的不一定是总函数的最小值,目前还是一个解决不了的问题,但是我们可以采取一些方案去尽量改善:
- 多次随机初始化,多次比较最小值结果
- 求解过程中,调整学习率
尽管没有全局最低点,但是效果都是不错的
sklearn逻辑回归API
sklearn.linear_model.LogisticRegression
LogisticRegression
sklearn.linear_model.LogisticRegression(penalty=‘l2’, C = 1.0)
- Logistic回归分类器
- coef_:回归系数
LogisticRegression回归案例
良/恶性乳腺癌肿瘤预测
原始数据的下载地址:
https://archive.ics.uci.edu/ml/machine-learning-databases/
数据描述
(1)699条样本,共11列数据,第一列用语检索的id,后9列分别是与肿瘤相关的医学特征,最后一列表示肿瘤类型的数值。
(2)包含16个缺失值,用”?”标出。
from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression, SGDRegressor, Ridge, LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, classification_report
import joblib
import pandas as pd
import numpy as np
import ssl
def logistic():
"""
逻辑回归做二分类进行癌症预测(根据细胞的属性特征)
:return: None
"""
ssl._create_default_https_context = ssl._create_unverified_context
# 构造列标签名字
column = ['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)
print(data)
# 缺失值进行处理
data = data.replace(to_replace='?', value=np.nan)
data = data.dropna()
# 进行数据的分割
x_train, x_test, y_train, y_test = train_test_split(data[column[1:10]], data[column[10]], test_size=0.25)
# 进行标准化处理
std = StandardScaler()
x_train = std.fit_transform(x_train)
x_test = std.transform(x_test)
# 逻辑回归预测
lg = LogisticRegression(C=1.0)
lg.fit(x_train, y_train)
print(lg.coef_)
y_predict = lg.predict(x_test)
print("准确率:", lg.score(x_test, y_test))
print("召回率:", classification_report(y_test, y_predict, labels=[2, 4], target_names=["良性", "恶性"]))
return None
if __name__ == "__main__":
logistic()
运行结果
Sample code number Clump Thickness ... Mitoses Class
0 1000025 5 ... 1 2
1 1002945 5 ... 1 2
2 1015425 3 ... 1 2
3 1016277 6 ... 1 2
4 1017023 4 ... 1 2
.. ... ... ... ... ...
694 776715 3 ... 1 2
695 841769 2 ... 1 2
696 888820 5 ... 2 4
697 897471 4 ... 1 4
698 897471 4 ... 1 4
[699 rows x 11 columns]
[[1.30052154 0.14422948 0.87413413 1.00049744 0.13566855 1.20200872
0.95905237 0.61479529 0.74051181]]
准确率: 0.9766081871345029
召回率: precision recall f1-score support
良性 0.98 0.98 0.98 123
恶性 0.96 0.96 0.96 48
accuracy 0.98 171
macro avg 0.97 0.97 0.97 171
weighted avg 0.98 0.98 0.98 171
LogisticRegression总结
应用:广告点击率预测、电商购物搭配推荐
优点:适合需要得到一个分类概率的场景
缺点:当特征空间很大时,逻辑回归的性能不是很好(看硬件能力)
生成模型和判别模型
先验概率:从历史的数据中总结出概率信息。
需要进行先验概率的模型就是生成模型。
判别模型:k-近邻,决策树,随机森林,神经网络
生成模型:朴素贝叶斯,隐马尔可夫模型
逻辑回归 | 朴素贝叶斯 | |
---|---|---|
解决问题 | 二分类 | 多分类 |
应用场景 | 二分类需要概率的问题 | 文本分类 |
参数 | 正则化力度 | 没有 |
得出的结果都有概率解释
非监督学习
- 随机在数据当中抽取三个样本,当作三个类别的中心点(k1, k2, k3)
- 计算其余的点分别到这三个中心店的距离,每一个样本有三个距离(a, b, c),从中选出距离最近的一个点作为自己的标记形成三个族群。
- 分别计算这三个族群的平均值,把三个平均值与之前的三个旧中心点进行比较,如果相同:结束聚类。如果不相同:把这三个平均值当作新的中心点,重复第二步。
k-means步骤
- 随机设置K个特征空间内的点作为初始的聚类中心
- 对于其他每个点计算到K个中心的距离,未知的点选择最近的一个聚类中心点作为标记类别
- 接着对着标记的聚类中心之后,重新计算出每个聚类的新中心点(平均值)
- 如果计算得出的新中心点与原中心点一样,那么结束,否则重新进行第二步过程
k-means API
sklearn.cluster.KMeans(n_clusters=8,init=‘k-means++’)
- k-means聚类
- n_clusters:开始的聚类中心数量
- init:初始化方法,默认为'k-means ++’
- labels_:默认标记的类型,可以和真实值比较(不是值比较)
k-means对Instacart Market用户聚类
- 降维之后的数据
- k-means聚类
- 聚类结果显示
import pandas as pd
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.metrics import silhouette_score
# 读取四张表的数据
prior = pd.read_csv("./data/instacart/order_products__prior.csv")
products = pd.read_csv("./data/instacart/products.csv")
orders = pd.read_csv("./data/instacart/orders.csv")
aisles = pd.read_csv("./data/instacart/aisles.csv")
# 合并四张表到一张表 (用户-物品类别)
_mg = pd.merge(prior, products, on=['product_id', 'product_id'])
_mg = pd.merge(_mg, orders, on=['order_id', 'order_id'])
mt = pd.merge(_mg, aisles, on=['aisle_id', 'aisle_id'])
print(mt.head(10))
# 交叉表(特殊的分组工具)
cross = pd.crosstab(mt['user_id'], mt['aisle'])
print(cross.head(10))
# 进行主成分分析
pca = PCA(n_components=0.9)
data = pca.fit_transform(cross)
# 把样本数量减少
x = data[:500]
print(x.shape)
# 假设用户一共分为四个类别
km = KMeans(n_clusters=4)
km.fit(x)
predict = km.predict(x)
print(predict)
# 显示聚类的结果
plt.figure(figsize=(10,10))
# 建立四个颜色的列表
colored = ['orange', 'green', 'blue', 'purple']
colr = [colored[i] for i in predict]
plt.scatter(x[:, 1], x[:, 20], color=colr)
plt.xlabel("1")
plt.ylabel("20")
plt.show()
# 评判聚类效果,轮廓系数
print(silhouette_score(x, predict))
运行结果
order_id product_id ... days_since_prior_order aisle
0 2 33120 ... 8.0 eggs
1 26 33120 ... 7.0 eggs
2 120 33120 ... 10.0 eggs
3 327 33120 ... 8.0 eggs
4 390 33120 ... 9.0 eggs
5 537 33120 ... 3.0 eggs
6 582 33120 ... 10.0 eggs
7 608 33120 ... 12.0 eggs
8 623 33120 ... 3.0 eggs
9 689 33120 ... 3.0 eggs
[10 rows x 14 columns]
aisle air fresheners candles asian foods ... white wines yogurt
user_id ...
1 0 0 ... 0 1
2 0 3 ... 0 42
3 0 0 ... 0 0
4 0 0 ... 0 0
5 0 2 ... 0 3
6 0 0 ... 0 0
7 0 0 ... 0 5
8 0 1 ... 0 0
9 0 0 ... 0 19
10 0 1 ... 0 2
[10 rows x 134 columns]
(500, 27)
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 2
0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 2 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 2 0 0 0
2 0 0 0 0 0 0 0 0 0 0 2 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 2 0 0 0 2 0 0
0 0 0 1 2 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 2 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 2 0 2 0 0 0 0 0 3 0 0 0 2 0 0 0 0 0 0 0 0
1 0 0 0 2 0 0 0 0 2 2 2 0 2 0 0 0 0 0 0 2 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 2 0 0 0 0 0 0 0 3 2 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 3 0 0 0 0 0 0 0 2 0 1 0 0 0 2 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 3 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 2 0 0 0 0 2 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 3
0 0 0 2 0 0 0 2 0 2 0 0 0 0 0 0 0 1 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2
0 0 0 0 2 2 0 0 0 0 0 0 0 0 2 0 0 0 0]
0.6123125240469242
Kmeans性能评估指标
轮廓系数:
注:对于每个点i 为已聚类数据中的样本 ,b_i 为i 到其它族群的所有样本的平均距离,a_i 为i 到本身簇的距离平均值
最终计算出所有的样本点的轮廓系数平均值
如果sc_i 小于0,说明a_i 的平均距离大于最近的其他簇。聚类效果不好
如果sc_i 越大,说明a_i 的平均距离小于最近的其他簇。聚类效果好
轮廓系数的值是介于 [-1,1] ,越趋近于1代表内聚度和分离度都相对较优
对于每一个样本 这里以蓝1为例
计算蓝1到自身类别的点距离的平均值a_i
计算蓝1分别到红色类别,绿色类别所有的点的距离,求出平均值b1, b2,取其中最小的值当做b_i
用公式计算蓝1的轮廓系数[-1, 1]
极端情况:
b_i>>a_i: 1 完美
a_i>> b_i: -1 最差
Kmeans性能评估指标API
sklearn.metrics.silhouette_score(X, labels)
- 计算所有样本的平均轮廓系数
- X:特征值
- labels:被聚类标记的目标值
特点分析:采用迭代式算法,直观易懂并且非常实用
缺点:容易收敛到局部最优解(多次聚类)
需要预先设定簇的数量(k-means++解决)
"日出于东,落于西。登高弃梯,未来可期。"
Macsen Chu