机器学习(监督学习算法):KNN(K近邻算法)交叉验证、网格搜索
·
KNN算法(K-Nearest Neighbors): 一种基本的分类与回归方法,属于监督学习算法。
该算法核心思想:通过计算给定样本与数据集中所有样本的距离,找到距离最近的K个样本,然后根据这K个样本的类别或值来预测当前样本的类别或值
- 计算距离,计算待分类样本与训练集中每个样本的距离
- 选择K个近邻,根据计算的距离,选择距离最近的K个样本
- 分类任务-统计K个近邻各类别的数量,将待分类样本归为数量最多的类别;回归任务-取K个近邻的平均值作为预测结果

关于距离度量的种类:
①、欧氏距离:欧几里得距离,这是我们最为熟悉的距离度量方法,指连接两点线段的长度
②、曼哈顿距离:曼哈顿距离得名于纽约曼哈顿的街道布局。由于曼哈顿的街道多为规则的网格状,车辆只能沿水平和垂直方向行驶,无法直接斜穿。因此,两点之间的实际行驶距离是沿街道行走的距离,而非直线距离。在坐标系中,是两点的轴距之和
③、切比雪夫距离:点x(x1,…,xn)和y(y1,…,yn)之间的切比雪夫距离d(x,y)=max(|xi-yi |),两点各坐标数值差的最大值
④、是一种用于度量多维空间中两点间距离的通用方法,点x(x1,…,xn)和y(y1,…,yn)之间的闵可夫斯基距离
- 其参数p越小,对多个维度的差异更敏感;p越大,更关注最大维度的差异。
- 通过调整参数p,闵可夫斯基距离可以退化为以下经典距离:曼哈顿距离:p=1;欧氏距离:p=2;切比雪夫距离:p=∞

API应用
分类
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=2) #KNN分类模型,K值为2
X = np.array([[2,1],[3,1],[1,4],[2,6]]) #特征
y = np.array([0,0,1,1])#标签
knn.fit(X,y) #模型训练
X = np.array([[4,9]])
X_class = knn.predict(X)#预测
print(X_class)
#画图
fig,ax = plt.subplots()
ax.axis('equal')
#使用布尔索引将两类点分开
X1 = X[y==0]
X2 = X[y==1]
#定义不同的颜色,画两组点
colors = ["C0","C1"]
plt.scatter(X1[:,0],X1[:,1],c=colors[0])
plt.scatter(X2[:,0],X2[:,1],c=colors[1])
#新点的颜色
x_color = colors[0] if x_class == 0 else colors[1]
plt.scatter(X[:,0],X[:,1],c=x_color)
plt.show()

"""
鸢尾花分类案例
- 特征值:花萼长度 花萼宽度 花瓣长度 花瓣宽度
- 目标值:setosa山鸢尾 versicolor杂色鸢尾 virginica弗吉尼亚鸢尾
"""
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
X,y = datasets.load_iris()
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_State=1024)
model = KNeighborsClassifier(n_neighbors=5)
model.fit(X_train,y_train)
y_ = model.predict(X_test) # 预测值
print((y_ == y_test).mean) # 准确率 或者采用model.score(X_test,y_test)
回归
from sklearn.neighbors import KNeighborsRegressor
knn = KNeighborsRegressor(n_neighbors=2,weights='distance') #KNN回归模型,K为2
X = [[2,1],[3,1],[1,4],[2,6]]
y = [0.5,0.33,4,3]
knn.fig(X,y)
knn.predict([4,9])
""""
预测波士顿房价
- 特征:13个
- 目标:房屋的中位数价格,以千美元为单位
"""
import warings
warnings.filterwarnings('ignore') # 忽略一些API以后过期的警告
from sklearn.datasets import load_boston
from sklearn.neighbors import KNeighborsRegressor # 回归 平均值 计算房价中位数
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV # 交叉验证-超参数(网格搜索)
data = load_boston()
X = data.data
y = data.target
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=42)
# k值、weights权重、p表示距离度量:欧氏距离、曼哈顿距离
k = [1,3,5,7,9,15,17,23,30]
weights = ['uniform','distance']
p = [1,2]
params = dict(n_neighbors=k,weights=weights,p=p)
estimator = KNeighborsRegressor()
gCV = GridSearchCV(estimator,params,cv=5,scoring='neg_mean_squared_error')
gCV.fit(X_train,y_train)
print(gCV.best_params_) # 获取最好的参数
print(gCV.best_score_)
print(gCV.best_estimator_)
best_knn = gCV.best_estimator_ # 最好的模型进行预测
y_ = best_knn.predict(X_test).round(1)
print(y_[:20])
print(mean_squared_error(y_test,y_)) # 均方误差
常见距离度量方法




归一化与标准化
归一化:
from sklearn.preprocessing import MinMaxScaler
X = [[2,1],[3,1],[1,4],[2,6]]
#定义归一化类的对象
scaler = MinMaxScaler(feature_range=(-1,1))
#将缩放器应用到特征上
X_scaled = scaler.fit_transform(X)
print(X_scaled)

标准化:
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
print(X_scaled)
#均值和方差
print(np.mean(X,axis=0))
print(np.std(X,axis=0))

超参调优

import numpy as np
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
X,y = datasets.load_iris(return_X_y=True)
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=42)
# 超参数-交叉验证
params_k = np.arange(1,31)
scores = []
for k in params_k:
knn = KNeighborsClassifier(n_neighbors=k)
# cv=5 表示5折,使用accuracy进行评估分类问题
score = cross_val_score(knn,X_train,y_train,cv=5,scoring='accuracy').mean()
scores.append(score)
k_best = np.argmax(scores) + 1
print("得分最高的k的值是:",k_best)
# 选择最佳超参进行建模和预测
estimator = KNeighborsClassifier(n_neighbors=k_best)
estimator.fit(X_train,y_train)
y_ = estimator.predict(X_test)
print(estimator.score(X_test,y_test))

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn metrics import accuracy_score
# 1.加载鸢尾花数据集
iris_data = load_iris()
# 2.数据预处理,切分训练集和测试集 比例8:2
x_train,x_test,y_train,y_test = train_test_split(iris_data.data,iris_data.target,test_size=0.2,random_state=22)
# 3.特征工程标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 模型训练
estimator = KNeighborsClassifier()
# 定义字典记录超参可能出现的值
param_dict = {'n_neighbors':[i for i in range(1,11)]}
# 4次交叉验证,4 * 10 = 40次,返回处理后的模型对象
estimator = GridSearchCV(estimator,param_dict,cv=4)
estimator.fit(x_train,y_train)
print(f'最优评分:{estimator.best_score_}'})
print(f'最优超参组合:{estimator.best_params_}')
print(f'最优的估计器对象:{estimator.best_estimator_}')
print(f'具体的交叉验证结果:{estimator.cv_results_}')
# 模型评估
# estimator = estimator.best_estimator_
estimator = KNeighborsClassifier(n_neighbors=3)
# 模型训练
estimator.fit(x_train,y_train)
y_pre = estimator.predict(x_test)
print(f'准确率:{accuracy_score(y_test,y_pre)}')
案例:心脏病预测

import pandas as pd
import sklearn.model_selection import train_test_split
#加载数据集
heart_disease_data = pd.read_csv("heart_disease.csv")
#处理缺失值
heart_disease_data.dropna(inplace=True)
heart_disease_data.info()
print(heart_disease_data.head())
#数据集划分
X = heart_disease_data.drop("是否患有心脏病",axis=1)
y = heart_disease_data["是否患有心脏病"]
X_tain,X_test,y_train,y_test = train_test_split(X,y,test_size=0.3,random_state=42)
#如何处理13中特征?

from sklearn.preprocessing import StandardScaler,OneHotEncoder
from sklearn.compose import ColumnTransformer
#数值特征
numerical_features = ["年龄","静息血压","胆固醇","最大心率","运动后的ST下降","主血管数量"]
#类别型特征
categorical_features = ["胸痛类型","静息心电图结果","峰值ST段的斜率","地中黑贫血"]
#二元特征
binary_features = ["性别","空腹血糖","运动性心绞痛"]
#创建列转换器
preprocessor = ColumnTransformer(
transformers=[
#对数值型特征进行标准化
("num",StandardScaler(),numerical_features),
#对类别型特征进行独热编码,使用drop="first"避免多重共线性
("cat",OneHotEncoder(drop="first"),categorical_features),
#二元特征不进行处理
("binary","passthrouth",binary_features),
]
)
#执行特征转换
x_train = preprocessor.fit_trainsform(X_train)#计算训练集的统计信息并进行转换
x_test = preprocessor.transform(X_test) #使用训练集计算的信息对测试集进行转换
print(x_train)
print(x_test)
from sklearn.neighbors import KNeighborsClassifier
import joblib
#创建模型
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train,y_train)
#模型评估,计算预测准确率
score = knn.score(X_test,y_test)
print(score)
#保存模型
joblib.dump(value=knn,filename="knn_model")
#加载保存好的模型做预测
knn_loaded = joblib.load("knn_model")
y_pred = knn_loaded.predict(X_test[10:11])
print(f"预测类别:{y_pred},真实类别:{y_test[10]}")
交叉验证
from sklearn.model_selection import GridSearchCV
#创建KNN分类器
knn = KNeighborsClassifier()
#定义网络搜索参数列表
param_grid = {"n_neigobors":list(range(1,11))}
grid_search_cv = GridSearchCV(estimator=knn,param_grid=param_grid,dv=10)
#模型训练
grid_search_cv.fit(X_train,y_train)
#打印模型评估结果
# results = grid_search_cv.cv_results_
# results = pd.DataFrame(grid_search_cv.cv_results_)
results = pd.DataFrame(grid_search_cv.cv_results_).toString()
print(results)

#获取最佳模型、参数和最佳得分
print(grid_search_cv.test_estimator_)
print(grid_search_cv.test_params_)
print(grid_search_cv.best_score_)
#使用最佳模型进行测试评估
knn = grid_search_cv.test_estimater_
print(knn.score(X_test,y_test))
除了上述K值决定的模型优化,此外还有权重影响
#定义网络搜索参数列表
pram_grid = {"n_neighbors":list(range(1,11)),"weights":["uniform","distance"]}
图像识别

①、数据加载
import numpy as np
import matplotlib.pyplot as plt
data = np.load('./digit.npy')
print(data)
print(data.shape) # (5000,28,28)
# 图片是500个一组,依次是0,1,2……
plt.imshow(data[0],cmap='gray')
# 构建目标值
y = list(np.arange(0,10)) * 500
y.score()
print(y)
# 将列表转换为张量
y = np.array(y)
②、数据拆分与处理
from sklearn.model_selection import train_test_split
X = data.reshape(5000,-1)
X.shape # 进行降维
X_trian,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=1024)
print(X_train.shape,y_train.shape)
③、建模
from sklearn.neighbors import KNeighborsClassifier
model = KNeighborsClassifier(n_neighbors=5)
model.fit(X_train,y_train)
model.score(X_test,y_test)
超参数优化算法
# 魔法指令,计算时间
%%tima
from sklearn.model_selection import GridSearchCV
params = dict(
n_neighbors=[3,5,10,15,17,23,30],
weights=['uniform','distance'],
p=[1,2]# 1 曼哈顿距离 2 欧式距离
)
estimator = KNeighborsClassifier()
gCV = GridSearchCV(estimator,params,cv=5,scoring='accuracy')
gCV.fit(X_train,y_train)
print(gCV.best_score_)
print(gCV.best_params_)
best_model = gCV.best_estimator_
y_pred = best_model.predict(X_test)
print(y_pred[:30])
print(y_test[:30])
print(best_model.score(X_test,y_test))
④、可视化
plt.figure(figsize=(5*2,10*3))
for i in range(50):
plt.subplot(10,5,i+1)
plt.imshow(X_test[i].reshape(28,28)) # 对数组进行增维,恢复成图片
true = y_test[i]
pred = y_pred[i]
plt.title(f'True:{true}\n Predict:{pred}')

健康医疗
①、数据加载
import numpy as np
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
data = pd.read_csv('./cancer.csv',sep='\t') # 源数据是以tap键进行分割的
print(data.head())
y = data['Diagnosis']
X = data.iloc[:,2:]
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=100)

②、网格搜索超参数
%%time
estimator = KNeighborsClassifier()
params = dict(
n_neighbors=np.arange(1,30),
weights=['uniform','distance'],
p=[1,2]
)
gCV = GridSearchCV(estimator,params,cv=6,scoring='accuracy')
gCV.fit(X_train,y_train)
print(gCV.best_score_)
print(gCV.best_params_)
model = gCV.best_estimator_
y_pred = model.predict(X_test)
print('算法预测值:',y_pred[:20])
③、评估
from sklearn.metircs import accuracy_score
accuracy_score(y_test,y_pred)
# 或者直接采用
model.score(X_test,y_test)
gCV.score(X_test,y_test)
数据进行归一化处理

from sklearn.preprocessing import MinMaxScaler
mms = MinMaxScaler()
X_norml = mms.fit_transform(X)
X_train,X_test,y_train,y_test = train_test_split(X_norml,y,test_size=0.2,random_state=100)
estimator = KNeighborsClassifier()
params = dict(n_eighbors=np.arange(1,30),weights=['uniform','distance'],p=[1,2])
gCV = GridSearchCV(estimator,params,cv=6,scoring='accuracy')
gCV.fit(X_train,y_train)
score = gCV.score(X_test,y_test)
print('Min-Max归一化数据,模型得分是:',score)

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_norm2 = scaler.fit_transform(X)
X_train,X_test,y_train,y_test = train_test_split(X_norm2,y,test_size=0.2,random_state=100)
estimator = KNeighborsClassifier()
params = dict(n_neighbors=np.arange(1,30),weights=['uniform','distance'],p=[1,2])
gCV = GridSearchCV(estimator,params,cv=6,scoring='accuracy')
gCV.fit(X_train,y_train)
print('超参数:',gCV.best_params_)
score = gCV.score(X_test,y_test)
print('Z-Score标准化数据:',score)
人力资源
①、数据加载
import numpy as np
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.model_selection import GridSearchCV
from sklearn.processing import MinMaxScaler,LabelEncoder
data = pd.read_csv('./adules.txt')
print(data.head(),data.shape)
data.isna().sum() # 统计空数据
data['workclass'].unique() # 出现?符号
data.replace("?",np.nan).dropna().reset_index(drop=True) # 删除空数据
data['capital_gain'].sort_values(asecnding=False).unique() # 异常值 过滤掉收益特别大的
data['capital_loss'].sort_values(ascending=False).unique() # 过滤掉损失特别大
cond = (data['capital_gain']!=99999) & (data['capital_loss']!=4356)
data = data[cond]
data.shape
# 字符串->数值型数据
le = LabelEncoder()
le.fit(["paris","paris","tokyo","amsterdam"])
le.transform(["paris","paris","tokyo","amsterdam"])
columns = ['workclass','education','marital_status','occupation','relationship','race','sex','native_country']
le = LabelEncoder()
for col in columns:
data[col] = le.fit_transform(data[col])
data.head()
# 归一化
scaler = MinMaxScaler()
col_norm = ['age','final_weight','workclass','education_num','education','marital_status','occupation','relationship','race','capital_gain','capital_loss','hours_per_week','native_country']
data[col_norm] = scaler.fit_transform(data[col_norm])

②、数据拆分
y = data['salary']
X = data.drop(labels='salary',axis=1)
print(X.shape)
③、建模预测
knn = KNeighborsClassifier()
knn.fit(X_train,y_train)
y_pred = knn.predict(X_test)
print('真实值:',y_test[:20].values)
print('预测值:',y_pred[:20])
accuracy_score(y_test,y_pred)
④、模型优化
%%time
knn = KNeighborsClassifier()
params = dict(n_neighbors=[3,5,9,15,23,31,39],weights=['uniform','distance'],p=[1,2])
gCV = GridSearchCV(knn,params,cv=5)
gCV.fit(X_train,y_train)
print(gCV.best_params_)
knn_best = gCV.best_estimator_
knn_best.score(X_test,y_test) # gCV.score(X_test,y_test)
更多推荐


所有评论(0)