1、K-近邻算法
- K-近邻算法(KNN)概念
- 如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
- 距离公式:欧式距离
- KNN算法流程
- 1、计算已知类别数据集中的点与当前点之间的距离
- 2、按距离递增次序排序
- 3、选取与当前点距离最小的k个点
- 4、统计前k个点所在的类别出现的频率
- 5、返回前k个点出现频率最高的类别作为当前点的预测分类
- k近邻算法api
- Scikit-learn工具
- pip3 install scikit-learn==0.19.1
- import sklearn
- 注:安装scikit-learn需要Numpy, Scipy等库
- Scikit-learn包含的内容:
- 分类、聚类、回归
- 特征工程
- 模型选择、调优
- Scikit-learn工具
- 距离度量
1.欧式距离(Euclidean Distance):
通过距离平方值进行计算
2.曼哈顿距离(Manhattan Distance):
通过距离的绝对值进行计算
3.切比雪夫距离 (Chebyshev Distance):
维度的最大值进行计算
4.闵可夫斯基距离(Minkowski Distance):
当p=1时,就是曼哈顿距离;
当p=2时,就是欧氏距离;
当p→∞时,就是切比雪夫距离。
前四个距离公式小结:前面四个距离公式都是把单位相同看待了,所以计算过程不是很科学
5.标准化欧氏距离 (Standardized EuclideanDistance):
在计算过程中添加了标准差,对量刚数据进行处理
6.余弦距离(Cosine Distance):
通过cos思想完成
7.汉明距离(Hamming Distance):
一个字符串到另一个字符串需要变换几个字母,进行统计
8.杰卡德距离(Jaccard Distance):
通过交并集进行统计
9.马氏距离(Mahalanobis Distance):
通过样本分布进行计算sklearn.neighbors.KNeighborsClassifier(n_neighbors=5)
* n_neighbors:int,可选(默认= 5),k_neighbors查询默认使用的邻居数- 案例:步骤分析
- 1.获取数据集
- 2.数据基本处理(该案例中省略)
- 3.特征工程(该案例中省略)
- 4.机器学习
- 5.模型评估(该案例中省略)
- 案例:步骤分析
- k值的选择
- K值过小:
*容易受到异常点的影响 - k值过大:
- 受到样本均衡的问题
- K值的减小就意味着整体模型变得复杂,容易发生过拟合;
- 与输入实例较远(不相似的)训练实例也会对预测器作用,使预测发生错误,且K值的增大就意味着整体的模型变得简单。
- 实际应用中,K值一般取一个比较小的数值
- K值过小:
- 过拟合、欠拟合
- 欠拟合是指模型没有能够很好的表现数据的结构,而出现的拟合度不高的情况。
- 过拟合是指模型过分的拟合训练样本,但对测试样本预测准确率不高的情况,也就是说模型泛化能力很差
- 过拟合原因:
- 数据特征的角度
数据噪声导致的过拟合:噪声具有一定的随机性与欺骗性,如果把噪声作为有效信息的话,将会导致过拟合。
缺乏代表性样本导致的过拟合:训练数据集不能很好的反应整体分布可能会导致过拟合;训练数据集较小,但模型过度细化会导致过拟合。 - 模型的角度
由于模型过度复杂,使得模型对训练数据拟合较好,但同时拟合了噪声或者与目标不相关的信息导致了过拟合。
- 数据特征的角度
- 过拟合、欠拟合的解决方法
-
过拟合的可能解决方法:
a、减少特征:删除与目标不相关特征,如一些特征选择方法 -
正则化:正则化会保证每个特征有一定的效用,不会使某一特征特别重要。
-
得到更多的训练样本
-
迁移学习-----可以解决由于训练数据较小引起的过拟合
-
- 近似误差:
- 对现有训练集的训练误差,关注训练集,
- 如果近似误差过小可能会出现过拟合的现象,对现有的训练集能有很好的预测,但是对未知的测试样本将会出现较大偏差的预测。
- 模型本身不是最接近最佳模型。
估计误差: - 可以理解为对测试集的测试误差,关注测试集,
- 估计误差小说明对未知数据的预测能力好,
- 模型本身最接近最佳模型。
- kd树
- kd树(K-dimension tree)是一种对k维空间中的实例点进行存储以便对其进行快速检索的树形数据结构。kd树是一种二叉树,表示对k维空间的一个划分,构造kd树相当于不断地用垂直于坐标轴的超平面将K维空间切分,构成一系列的K维超矩形区域。
- kd树的构造:
- 1.构造根节点
- 2.通过递归的方法,不断地对k维空间进行切分,生成子节点
- 3.重复第二步骤,直到子区域中没有示例时终止
- 需要关注细节:a.选择向量的哪一维进行划分;b.如何划分数据
- kd树的搜索过程
- 1.二叉树搜索比较待查询节点和分裂节点的分裂维的值,(小于等于就进入左子树分支,大于就进入右子树分支直到叶子结点)
- 2.顺着“搜索路径”找到最近邻的近似点
- 3.回溯搜索路径,并判断搜索路径上的结点的其他子结点空间中是否可能有距离查询点更近的数据点,如果有可能,则需要跳到其他子结点空间中去搜索
- 4.重复这个过程直到搜索路径为空.
- scikit-learn数据集
- sklearn.datasets
- 加载获取流行数据集
- datasets.load_*()
- 获取小规模数据集,数据包含在datasets里
- datasets.fetch_*(data_home=None)
- 获取大规模数据集,需要从网络上下载,函数的第一个参数是data_home,表示数据集下载的目录,默认是 ~/scikit_learn_data/
- load和fetch返回的数据类型datasets.base.Bunch(字典格式)
- data:特征数据数组,是 [n_samples * n_features] 的二维 numpy.ndarray 数组
- target:标签数组,是 n_samples 的一维 numpy.ndarray 数组
- DESCR:数据描述
- feature_names:特征名,新闻数据,手写数字、回归数据集没有
- target_names:标签名
- sklearn.datasets
- 查看数据分布
- seaborn介绍
-
Seaborn 是基于 Matplotlib 核心库进行了更高级的 API 封装,可以让你轻松地画出更漂亮的图形。而 Seaborn 的漂亮主要体现在配色更加舒服、以及图形元素的样式更加细腻。
安装 pip3 install seaborn
seaborn.lmplot() 是一个非常有用的方法,它会在绘制二维散点图时,自动完成回归拟合 -
sns.lmplot() 里的 x, y 分别代表横纵坐标的列名,
-
data= 是关联到数据集,
-
hue=*代表按照 species即花的类别分类显示,
-
fit_reg=是否进行线性拟合
-
- seaborn介绍
- %matplotlib inline是一个魔法函数(Magic Functions) 可以在Ipython编译器里直接使用,功能是可以内嵌绘图,并且可以省略掉plt.show()这一步
- 交叉验证
- 交叉验证的目的:为了让被评估的模型更加准确可信
- 有很多参数是需要手动指定的(如k-近邻算法中的K值),这种叫超参数。但是手动过程繁杂,所以需要对模型预设几种超参数组合。每组超参数都采用交叉验证来进行评估。最后选出最优参数组合建立模型
sklearn.model_selection.GridSearchCV(estimator, param_grid=None,cv=None)- 对估计器的指定参数值进行详尽搜索
- estimator:估计器对象
- param_grid:估计器参数(dict){“n_neighbors”:[1,3,5]}
- cv:指定几折交叉验证
- fit:输入训练数据
- score:准确率
- 结果分析:
- bestscore__:在交叉验证中验证的最好结果
- bestestimator:最好的参数模型
- cvresults:每次交叉验证后的验证集准确率结果和训练集准确率结果
sklearn.model_selection.GridSearchCV(estimator, param_grid=None,cv=None)
对估计器的指定参数值进行详尽搜索
estimator:估计器对象
param_grid:估计器参数(dict){“n_neighbors”:[1,3,5]}
cv:指定几折交叉验证
fit:输入训练数据
score:准确率
结果分析:
bestscore__:在交叉验证中验证的最好结果
bestestimator:最好的参数模型
cvresults:每次交叉验证后的验证集准确率结果和训练集准确率结果
4 鸢尾花案例增加K值调优
使用GridSearchCV构建估计器
# 1、获取数据集
iris = load_iris()
# 2、数据基本处理 -- 划分数据集
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=22)
# 3、特征工程:标准化
# 实例化一个转换器类
transfer = StandardScaler()
# 调用fit_transform
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 4、KNN预估器流程
# 4.1 实例化预估器类
estimator = KNeighborsClassifier()
# 4.2 模型选择与调优——网格搜索和交叉验证
# 准备要调的超参数
param_dict = {"n_neighbors": [1, 3, 5]}
estimator = GridSearchCV(estimator, param_grid=param_dict, cv=3)
# 4.3 fit数据进行训练
estimator.fit(x_train, y_train)
# 5、评估模型效果
# 方法a:比对预测结果和真实值
y_predict = estimator.predict(x_test)
print("比对预测结果和真实值:\n", y_predict == y_test)
# 方法b:直接计算准确率
score = estimator.score(x_test, y_test)
print("直接计算准确率:\n", score)
print("在交叉验证中验证的最好结果:\n", estimator.best_score_)
print("最好的参数模型:\n", estimator.best_estimator_)
print("每次交叉验证后的准确率结果:\n", estimator.cv_results_)
注意:交叉验证不会优化准确率 但是网格搜索可以
- 案例2:预测facebook签到位置
- 机器学习流程:
- 1、获取数据
- 2、数据基本处理
- 1、缩小数据范围
- 2、时间转化星期,小时,天
- 3、删除到的次数少的数据
- 4、确定特征值和目标值
- 5、切割数据
- 3、特征工程
- 数据标准化
- 4、建立模型
- KNN+CV
- 5、模型评估
# 2.基本数据处理
# 2.1 缩小数据范围
facebook_data = facebook.query("x>2.0 & x<2.5 & y>2.0 & y<2.5")
# 2.2 选择时间特征
time = pd.to_datetime(facebook_data["time"], unit="s")
time = pd.DatetimeIndex(time)
facebook_data["day"] = time.day
facebook_data["hour"] = time.hour
facebook_data["weekday"] = time.weekday
# 2.3 去掉签到较少的地方
place_count = facebook_data.groupby("place_id").count()
place_count = place_count[place_count["row_id"]>3]
facebook_data = facebook_data[facebook_data["place_id"].isin(place_count.index)]
# 2.4 确定特征值和目标值
x = facebook_data[["x", "y", "accuracy", "day", "hour", "weekday"]]
y = facebook_data["place_id"]
# 2.5 分割数据集
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=22)
# 3.特征工程--特征预处理(标准化)
# 3.1 实例化一个转换器
transfer = StandardScaler()
# 3.2 调用fit_transform
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)
# 4.机器学习--knn+cv
# 4.1 实例化一个估计器
estimator = KNeighborsClassifier()
# 4.2 调用gridsearchCV
param_grid = {"n_neighbors": [1, 3, 5, 7, 9]}
estimator = GridSearchCV(estimator, param_grid=param_grid, cv=5)
# 4.3 模型训练
estimator.fit(x_train, y_train)
# 5.模型评估
# 5.1 基本评估方式
score = estimator.score(x_test, y_test)
print("最后预测的准确率为:\n", score)
y_predict = estimator.predict(x_test)
print("最后的预测值为:\n", y_predict)
print("预测值和真实值的对比情况:\n", y_predict == y_test)
# 5.2 使用交叉验证后的评估方式
print("在交叉验证中验证的最好结果:\n", estimator.best_score_)
print("最好的参数模型:\n", estimator.best_estimator_)
print("每次交叉验证后的验证集准确率结果和训练集准确率结果:\n",estimator.cv_results_)
2、线性回归
- 线性回归api
- 线性回归(Linear regression)是利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式
- 特点:只有一个自变量的情况称为单变量回归,多于一个自变量情况的叫做多元回归
- sklearn.linear_model.LinearRegression()
- LinearRegression.coef_:回归系数
- 非线性回归
- 线性回归(Linear regression)是利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式
x = [[80, 86],
[82, 80],
[85, 78],
[90, 90],
[86, 82],
[82, 90],
[78, 80],
[92, 94]]
y = [84.2, 80.6, 80.1, 90, 83.2, 87.6, 79.4, 93.4]
# 实例化API
estimator = LinearRegression()
# 使用fit方法进行训练
estimator.fit(x,y)
estimator.coef_
estimator.predict([[100, 80]])
- 求导
- 常见的求导方法
- 导数的四则运算
- 常见的求导方法
- 线性回归的损失和优化
- 损失函数
- yi为第i个训练样本的真实值
- h(xi)为第i个训练样本特征值组合预测函数
- 又称最小二乘法
- 优化算法:
- 正规方程
- 利用矩阵的逆,转置进行一步求解
- 只适合样本和特征比较少的情况
正规方程推导:
- 梯度下降法
- α – 就是步长
- 梯度下降法:SGDRegressor
- 适合大规模数据
- 梯度下降法和正规方程选择依据
- 小规模数据:
- 正规方程:LinearRegression(不能解决拟合问题)
- 岭回归
- 大规模数据:
- 梯度下降法:SGDRegressor
- 小规模数据:
- 正规方程
梯度下降 | 正规方程 |
---|---|
需要选择学习率 | 不需要 |
需要迭代求解 | 一次运算得出 |
特征数量较大可以使用 | 需要计算方程,时间复杂度高 |
- 梯度下降法
- 全梯度下降算法(FG)
- 计算训练集所有样本误差,对其求和再取平均值作为目标函数
- 随机梯度下降算法(SG)
- 每次只带入一个随机样本来更新权重,重复此过程,直到损失函数数值停止下降或者损失函数值小于某个可以容忍的阀值
- 小批量梯度下降算法(mini-batch)
- 每次从训练样本中随机抽取一个小样本集,在抽出来的小样本集采用FG迭代更新权重
- 随机平均梯度下降算法(SAG)
- 在内存中为每一个样本都维护一个旧的梯度,随机选择一个样本来更新此样本的梯度,其他样本的梯度保持不变,然后求得所有梯度的平均值,进而更新了参数
- 全梯度下降算法(FG)
- 线性回归
- 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_:偏置
- loss:损失类型
- 波士顿房价预测
def linear_model1():
"""
线性回归:正规方程
:return:None
"""
# 1.获取数据
data = load_boston()
# 2.数据集划分
x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)
# 3.特征工程-标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)
# 4.机器学习-线性回归(正规方程)
estimator = LinearRegression()
# 4.1梯度下降法
#estimator = SGDRegressor(max_iter=1000)
# 4.2 岭回归
# estimator = Ridge(alpha=100)
# 4.3 交叉验证
# estimator = RidgeCV(alphas=(0.1,10,20,100))
estimator.fit(x_train, y_train)
# 5.模型评估
# 5.1 获取系数等值
y_predict = estimator.predict(x_test)
print("预测值为:\n", y_predict)
print("模型中的系数为:\n", estimator.coef_)
print("模型中的偏置为:\n", estimator.intercept_)
# 5.2 评价
# 均方误差
error = mean_squared_error(y_test, y_predict)
print("误差为:\n", error)
return None
-
欠拟合和过拟合
- 过拟合:训练集效果好,测试集效果不好(模型复杂)
理解:模型复杂,特征较多,测试集里对象特征部分难以满足 导致效果不好
原因: - 欠拟合:训练集效果不好,测试集效果不好(模型简单)
理解:模型简单,特征较少,导致测试集部分数据特征训练集中没有,顾名思义欠拟合
- 过拟合:训练集效果好,测试集效果不好(模型复杂)
-
正则化类别
- L1正则化:直接把高次项前面的系数变为0
- Lasso回归
- L2正则化:把高次项前面的系数变成特别小的值
- 岭回归
- Elastic Net 弹性网络
- L1,L2的综合
- 设置了一个r,如果r=0–岭回归;r=1–Lasso回归
- L1正则化:直接把高次项前面的系数变为0
-
线性回归的改进-岭回归
-
sklearn.linear_model.Ridge(alpha=1.0, fit_intercept=True,solver=“auto”, normalize=False)
- 具有l2正则化的线性回归
- alpha:正则化力度,也叫 λ
- λ取值:0~1 1~10
- 正则化力度越大,权重系数会越小
- 正则化力度越小,权重系数会越大
- ag:如果数据集、特征都比较大,选择该随机梯度下降优化
- normalize:数据是否进行标准化
- normalize=False:可以在fit之前调用preprocessing.StandardScaler标准化数据
- Ridge.coef_:回归权重
- Ridge.intercept_:回归偏置
-
sklearn.linear_model.RidgeCV(_BaseRidgeCV, RegressorMixin)
- 具有l2正则化的线性回归,可以进行交叉验证
- coef_:回归系数
-
回归性能评估
yi为预测值,y为真实值- sklearn.metrics.mean_squared_error(y_true, y_pred)
- 均方误差回归损失
- y_true:真实值
- y_pred:预测值
- return:浮点数结果
- sklearn.metrics.mean_squared_error(y_true, y_pred)
-
模型的保存和加载
-
from sklearn.externals import joblib
- 保存:joblib.dump(estimator, ‘test.pkl’)
- 加载:estimator = joblib.load(‘test.pkl’)
- 注意:1.保存文件,后缀名是**.pkl
2.加载模型是需要通过一个变量进行承接
def load_dump_demo():
"""
模型保存和加载
:return:
"""
# 1.获取数据
data = load_boston()
# 2.数据集划分
x_train, x_test, y_train, y_test = train_test_split(data.data, data.target, random_state=22)
# 3.特征工程-标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.fit_transform(x_test)
# 4.机器学习-线性回归(岭回归)
# # 4.1 模型训练
# estimator = Ridge(alpha=1)
# estimator.fit(x_train, y_train)
#
# # 4.2 模型保存
# joblib.dump(estimator, "./data/test.pkl")
# 4.3 模型加载
estimator = joblib.load("./data/test.pkl")
# 5.模型评估
# 5.1 获取系数等值
y_predict = estimator.predict(x_test)
print("预测值为:\n", y_predict)
print("模型中的系数为:\n", estimator.coef_)
print("模型中的偏置为:\n", estimator.intercept_)
# 5.2 评价
# 均方误差
error = mean_squared_error(y_test, y_predict)
print("误差为:\n", error)