分类算法的目标值是离散型的 如果目标值是连续型的值,就需要回归算法 比如房价预测、销售额预测、贷款额度预测等
举个栗子
期末成绩:0.7×考试成绩+0.3×平时成绩(各个特征跟某个值组合在一起去预测)
西瓜好坏:0.2×色泽+0.5×根蒂+0.3×敲声(把回归问题转换为分类问题)
为权重,称为偏置项,可以理解为:
定义:线性回归通过一个或者多个自变量与因变量之间之间进行建模的回归分析。其中特点为一个或多个称为回归系数的模型参数的线性组合
一元线性回归:涉及到的变量只有一个
多元线性回归:涉及到的变量两个或两个以上
通用公式:
其中w,x为矩阵:
属性和权重的一种组合来预测结果
矩阵也是大多数算法的计算基础
矩阵乘法:
行列行列行行
(这线性代数我是记不住咯…)
单变量:
回归算法是迭代的算法
总损失定义:
又称最小二乘法
如何去求模型当中的W,使得损失最小?(目的是找到最小损失对应的W值)
求解:
为特征值矩阵,为目标值矩阵
缺点:当特征过于复杂,求解速度太慢 对于复杂的算法,不能使用正规方程求解(逻辑回归等)
损失函数直观图(单变量举例)
直接求解到最小值
我们以单变量中的w0,w1为例子:
为学习效率,需要手动指定,表示方向
理解:沿着这个函数下降的方向找,最后就能找到山谷的最低点,然后更新W值
使用:面对训练数据规模十分庞大的任务
正规方程: sklearn.linear_model.LinearRegression
梯度下降: sklearn.linear_model.SGDRegressor
普通最小二乘线性回归
通过使用SGD最小化线性模型
波士顿房价数据案例分析流程
属性名 | 解释 | 类型 |
---|---|---|
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.metrics.mean_squared_error
mean_squared_error
mean_squared_error(y_true, y_pred)
注:真实值,预测值为标准化之前的值
梯度下降 | 正规方程 |
---|---|
需要选择学习率α | 不需要 |
需要多次迭代 | 一次运算得出 |
当特征数量n大时也能较好适用 | 需要计算(X^TX)^-1 如果特征数量n较大则运算代价大,因为矩阵逆的计算时间复杂度为O(n^3),通常来说当n小于10000时还是可以接受的 |
适用于各种类型的模型 | 只适用于线性模型,不适合逻辑回归模型等其他模型 |
线性回归器是最为简单、易用的回归模型。
从某种程度上限制了使用,尽管如此,在不知道特征之间关系的前提下,我们仍然使用线性回归器作为大多数系统的首要选择。
问题:训练数据训练的很好啊,误差也不大,为什么在测试集上面有问题呢?
分析图1:
经过训练后,知道了天鹅是有翅膀的,天鹅的嘴巴是长长的。简单的认为有这些特征的都是天鹅。因为机器学习到的天鹅特征太少了,导致区分标准太粗糙,不能准确识别出天鹅。
分析图2:
机器通过这些图片来学习天鹅的特征,经过训练后,知道了天鹅是有翅膀的,天鹅的嘴巴是长长的弯曲的,天鹅的脖子是长长的有点曲度,天鹅的整个体型像一个"2"且略大于鸭子。这时候机器已经基本能区别天鹅和其他动物了。然后,很不巧已有的天鹅图片全是白天鹅的,于是机器经过学习后,会认为天鹅的羽毛都是白的,以后看到羽毛是黑的天鹅就会认为那不是天鹅。
过拟合:一个假设在训练数据上能够获得比其他假设更好的拟合, 但是在训练数据外的数据集上却不能很好地拟合数据,此时认为这个假设出现了过拟合的现象。(模型过于复杂)
欠拟合:一个假设在训练数据上不能获得更好的拟合, 但是在训练数据外的数据集上也不能很好地拟合数据,此时认为这个假设出现了欠拟合的现象。(模型过于简单)
原因:原始特征过多,存在一些嘈杂特征, 模型过于复杂是因为模型尝试去兼顾各个测试数据点,数据的特征和目标值之间不仅仅是线性关系
解决办法:
回忆一下特征选择方法:
作用:可以使得W的每个元素都很小,都接近于0
优点:越小的参数说明模型越简单,越简单的模型则越不容易产生过拟合现象
线性回归:LinearRegression 容易出现过拟合,为了把训练接数据表现更好
L2正则化:Ridge:岭回归 带有正则化的线性回归 解决过拟合
sklearn.linear_model.Ridge
具有l2正则化的线性最小二乘法
sklearn.linear_model.Ridge(alpha=1.0)
观察正则化程度的变化,对结果的影响
正则化力度越来越大,模型越来越简单
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()
岭回归:回归得到的回归系数更符合实际,更可靠。另外,能让估计参数的波动范围变小,变的更稳定。在存在病态数据偏多的研究中有较大的实用价值。
import joblib
保存:joblib.dump(rf, 'test.pkl')
加载:estimator = joblib.load('test.pkl')
注:文件格式pkl
他叫逻辑回归…可他是分类算法
逻辑回归:线性回归的式子作为逻辑回归的输入,适用于二分类场景,他也能得出概率值
输入:
逻辑回归的输入-sigmoid→分类
sigmodid函数会把值映射到[0, 1],也就是把我们的输入值转换成一个概率值
公式:
输出:[0,1]区间的概率值,默认0.5作为阀值
注:g(z)为sigmoid函数
与线性回归原理相同,但由于是分类问题,损失函数不一样,只能通过梯度下降求解
对数似然损失函数:
完整的损失函数:
cost损失的值越小,那么预测的类别准确度更高
损失函数:
对数似然损失求出来的不一定是总函数的最小值,目前还是一个解决不了的问题,但是我们可以采取一些方案去尽量改善:
尽管没有全局最低点,但是效果都是不错的
sklearn.linear_model.LogisticRegression
sklearn.linear_model.LogisticRegression(penalty=‘l2’, C = 1.0)
良/恶性乳腺癌肿瘤预测
原始数据的下载地址:
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
应用:广告点击率预测、电商购物搭配推荐
优点:适合需要得到一个分类概率的场景
缺点:当特征空间很大时,逻辑回归的性能不是很好(看硬件能力)
先验概率:从历史的数据中总结出概率信息。
需要进行先验概率的模型就是生成模型。
判别模型:k-近邻,决策树,随机森林,神经网络
生成模型:朴素贝叶斯,隐马尔可夫模型
逻辑回归 | 朴素贝叶斯 | |
---|---|---|
解决问题 | 二分类 | 多分类 |
应用场景 | 二分类需要概率的问题 | 文本分类 |
参数 | 正则化力度 | 没有 |
得出的结果都有概率解释
sklearn.cluster.KMeans(n_clusters=8,init=‘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
轮廓系数:
计算公式:
注:对于每个点i 为已聚类数据中的样本 ,b_i 为i 到其它族群的所有样本的平均距离,a_i 为i 到本身簇的距离平均值
最终计算出所有的样本点的轮廓系数平均值
如果sc_i 小于0,说明a_i 的平均距离大于最近的其他簇。聚类效果不好
如果sc_i 越大,说明a_i 的平均距离小于最近的其他簇。聚类效果好
轮廓系数的值是介于 [-1,1] ,越趋近于1代表内聚度和分离度都相对较优
对于每一个样本 这里以蓝1为例
极端情况:
b_i>>a_i: 1 完美
a_i>> b_i: -1 最差
sklearn.metrics.silhouette_score(X, labels)
特点分析:采用迭代式算法,直观易懂并且非常实用
缺点:容易收敛到局部最优解(多次聚类) 需要预先设定簇的数量(k-means++解决)
"日出于东,落于西。登高弃梯,未来可期。"
Macsen Chu