通过计算距离来判断样本之间的相似程度
距离越近两个样本就越相似, 就可以划归到一个类别中
如该例子:唐人街探案属于什么类型的电影?
序号 | 电影名称 | 搞笑镜头 | 拥抱镜头 | 打斗镜头 | 电影类型 |
---|---|---|---|---|---|
1 | 功夫熊猫 | 39 | 0 | 31 | 喜剧片 |
2 | 叶问3 | 3 | 2 | 65 | 动作片 |
3 | 伦敦陷落 | 2 | 3 | 55 | 动作片 |
4 | 代理情人 | 9 | 38 | 2 | 爱情片 |
5 | 新步步惊心 | 8 | 34 | 17 | 爱情片 |
6 | 谍影重重 | 5 | 2 | 57 | 动作片 |
7 | 功夫熊猫 | 39 | 0 | 31 | 喜剧片 |
8 | 美人鱼 | 21 | 17 | 5 | 喜剧片 |
9 | 宝贝当家 | 45 | 2 | 9 | 喜剧片 |
10 | 唐人街探案 | 23 | 3 | 17 | ? |
根据欧式距离计算公式:
可得伦敦陷落与唐人街探案的距离为
以此类推可以求得唐人街探案距离各电影的距离,因此可以得到下表:
序号 | 电影名称 | 搞笑镜头 | 拥抱镜头 | 打斗镜头 | 电影类型 | 距离 | K=5时 |
---|---|---|---|---|---|---|---|
1 | 功夫熊猫 | 39 | 0 | 31 | 喜剧片 | 21.47 | √ |
2 | 叶问3 | 3 | 2 | 65 | 动作片 | 52.01 | |
3 | 伦敦陷落 | 2 | 3 | 55 | 动作片 | 43.42 | |
4 | 代理情人 | 9 | 38 | 2 | 爱情片 | 40.57 | |
5 | 新步步惊心 | 8 | 34 | 17 | 爱情片 | 34.44 | √ |
6 | 谍影重重 | 5 | 2 | 57 | 动作片 | 43.87 | |
7 | 功夫熊猫 | 39 | 0 | 31 | 喜剧片 | 21.47 | √ |
8 | 美人鱼 | 21 | 17 | 5 | 喜剧片 | 18.55 | √ |
9 | 宝贝当家 | 45 | 2 | 9 | 喜剧片 | 23.43 | √ |
10 | 唐人街探案 | 23 | 3 | 17 | ? | —— | ? |
? 若将K设置为5时,距离唐人街探案最近的5部电影便是功夫熊猫,新步步惊心,功夫熊猫,美人鱼,宝贝当家,根据投票原则,4票喜剧片,1票爱情片,所以唐人街探案属于喜剧片
K 就是当前算法的一个超参数
上面谈到了距离,具体有哪些距离计算公式来看看吧:
欧氏距离
曼哈顿距离
切比雪夫距离
闵可夫斯基距离 多种距离的总的表示公式
分类问题:
# 1.工具包
from sklearn.neighbors import KNeighborsClassifier,KNeighborsRegressor
# from sklearn.neighbors import KNeighborsRegressor
# 2.数据(特征工程)
# 分类
x = [[0,2,3],[1,3,4],[3,5,6],[4,7,8],[2,3,4]]
y = [0,0,1,1,0]
# 创建算法对象 K近邻的分类器
knn = KNeighborsClassifier(n_neighbors=1)
# 算法模型对象 调用fit 模型训练
knn.fit(x,y) # X 训练集特征值 y 训练集目标值
# 使用训练好的模型进行预测
knn.predict([[4,4,5]])
回归问题:
# 准备数据 x 特征值
x = [[0,1,2],[1,2,3],[2,3,4],[3,4,5]]
# y 目标值
y = [0.1,0.2,0.3,0.4]
# 创建K近邻的回归器
knn = KNeighborsRegressor(n_neighbors=2)
# 模型训练 对于KNN来说, 就是把所有样本保存起来
knn.fit(x,y)
# 利用模型输出预测结果
knn.predict([[4,4,5]])
SKlearn 的API 都有固定的套路
- 创建算法模型对象
- fit 模型训练
- predict 使用训练好的模型进行预测
模型训练的时候, 使用的数据, 有几个特征, 是什么样的维度, 在predict的时候传入的数据需要有相同的维度
? 在正式开始该案例之前,为了让模型有一个好的应用效果,先了解一个特征工程中的概念。
是特征工程中特征预处理的一个环节
应用场景:
归一化/标准化 可以把量纲不统一的特征, 缩放到同一取值范围内
归一化
标准化
需要注意的是
# 如果数据中有特别大的取值/特别小的取值 收入 10000小目标 0.00001个小目标
from sklearn.preprocessing import MinMaxScaler
x = [[90, 2, 10, 40], [60, 4, 15, 45], [75, 3, 13, 46]]
# 创建一个Scaler对象
scaler = MinMaxScaler()
# fit 就是在计算每一列特征的最大值和最小值, 并保存到scaler对象中
scaler.fit(x)
# Transform 变化, 利用上一步计算出来的 最大最小值, 作用到原始数据上, 得到缩放之后的结果
scaler.transform(x)
标准化
# 标准化没有固定取值范围, 基本上会在 -10 10
from sklearn.preprocessing import StandardScaler
x = [[90, 2, 10, 40], [60, 4, 15, 45], [75, 3, 13, 46]]
# 创建一个Scaler对象
scaler = StandardScaler()
# fit 就是在计算每一列特征的均值和方差
scaler.fit(x)
# Transform 变化, 利用上一步计算出来的 最大最小值, 作用到原始数据上, 得到缩放之后的结果
scaler.transform(x)
iris_data = load_iris()
iris.feature_names # 特征名字
[‘sepal length (cm)’,
‘sepal width (cm)’,
‘petal length (cm)’,
‘petal width (cm)’]
iris.target_names # 目标值名称
[‘setosa’ ‘versicolor’ ‘virginica’]
X,y = load_iris(return_X_y=True) # 如果加上return_X_y=True 只会返回特征值和目标值
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# X 数据集的特征, y 数据集的目标, test_size 测试集的比例 random_state 随机数种子, 写死了一个随机数种子每次得到的数据集划分结果都是一样的
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2,random_state=42)
# 特征工程
scaler = StandardScaler() # 标准化
# 训练集 测试集 要不要都做标准化 都要做
scaler.fit(X_train) # 计算均值 方差 120
X_train_scaled = scaler.transform(X_train) # 做标准化计算
# scaler.fit(X_test) # 计算均值 方差 30
X_test_scaled = scaler.transform(X_test) # 做标准化计算
特征工程需要注意
- 训练集 fit transform
- 测试集 直接transform
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train_scaled,y_train) # 使用标准化之后的特征值, 进行模型训练
KNN 特点, 不需要训练, 数据就是模型本身, 数据发生了变化, 模型就发生了变化
fit的时候就是把 X_train_scaled 和 y_train保存下来
y_train_pred = knn.predict(X_train_scaled) # 用训练好的模型 对训练集进行分类
y_test_pred = knn.predict(X_test_scaled) # 用训练好的模型 对测试集进行分类
from sklearn.metrics import accuracy_score
accuracy_score(y_train,y_train_pred) # 准确率 利用模型输出的结果和 真实标签进行比较, 如果两者一致说明 模型分类正确, 如果不一致说明分类错误
#准确率 计算的是 分类正确样本的比例
accuracy_score(y_test,y_test_pred)
accuracy_score 准确率 分类问题的评价方法之一
# 对数据做简单的可视化
import pandas as pd
iris_df = pd.DataFrame(iris.data,columns=iris.feature_names)
iris_df['label'] = iris.target
iris_df
import seaborn as sns
# data 要绘图的数据, x x轴数据在df中的列名 y = y轴数据在df中的列名 hue 传入类别型取值的特征列, 会自动用不同颜色来表示, fit_reg=默认会拟合一个回归直线
sns.lmplot(data=iris_df,x='sepal length (cm)',y='petal width (cm)',fit_reg=False,hue ='label')
# hue = 'label' 用标签列, 对数据点进行区分展示, 3种不同的鸢尾花分别用不同的颜色显示
可以使用交叉验证和网格搜索来做超参数的调整
网格搜索
交叉验证
可以把训练数据进一步划分成训练集和验证集
把网格搜索和交叉验证结合起来, 就是在不同的数据中(训练集和验证集), 来尝试不同的参数组合
knn_estimator = KNeighborsClassifier(n_neighbors=3) # 创建K近邻模型对象
param_grid_ = {'n_neighbors':[2,3,4,5,6],'p':[1,2],'weights':['uniform','distance']}# 创建网格搜索的超参数空间
grid_estimator = GridSearchCV(estimator=knn_estimator,param_grid=param_grid_,cv=4)
n_neighbors KNN k的取值
p 1,2 1 曼哈顿距离, 2 欧氏距离
weights 权重 投票时的权重
- 默认uniform 平权投票, 所有的样本权重都一样
- distance 加权投票 考虑距离的倒数作为权重
grid_estimator.fit(x_train_scaled,y_train) # 使用标准化之后的 训练集数据进行模型训练
y_train_pred = grid_estimator.predict(x_train_scaled) # 使用训练好的模型, 对训练集数据进行分类
print('训练集:',accuracy_score(y_train,y_train_pred))
y_test_pred = grid_estimator.predict(x_test_scaled) # 使用训练好的模型, 对测试集数据进行分类
print('测试集:',accuracy_score(y_test,y_test_pred))
grid_estimator.cv_results_
grid_estimator.best_params_ # 最佳的参数组合, 如果有并列的情况, 默认返回的是以一个第一名对应的参数组合
grid_estimator.best_score_ # 最佳分数 交叉验证时的最好的平均分数
red = grid_estimator.predict(x_test_scaled) # 使用训练好的模型, 对测试集数据进行分类
print(‘测试集:’,accuracy_score(y_test,y_test_pred))
grid_estimator.cv_results_
- 记录了交叉验证网格搜索的全部过程, 每组验证集的评价结果
grid_estimator.best_params_ # 最佳的参数组合, 如果有并列的情况, 默认返回的是以一个第一名对应的参数组合
grid_estimator.best_score_ # 最佳分数 交叉验证时的最好的平均分数
希望可以帮到大家,不要忘记点赞收藏欧!