KNN:(内容来自百度百科)邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一。所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。
kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 kNN方法在类别决策时,只与极少量的相邻样本有关。由于kNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,kNN方法较其他方法更为适合。
右图中,绿色圆要被决定赋予哪个类,是红色三角形还是蓝色四方形?如果K=3,由于红色三角形所占比例为2/3,绿色圆将被赋予红色三角形那个类,如果K=5,由于蓝色四方形比例为3/5,因此绿色圆被赋予蓝色四方形类。
(KNN算法的决策过程)
K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 KNN方法虽然从原理上也依赖于极限定理,但在类别决策时,只与极少量的相邻样本有关。由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。
KNN算法不仅可以用于分类,还可以用于回归。通过找出一个样本的k个最近邻居,将这些邻居的属性的平均值赋给该样本,就可以得到该样本的属性。更有用的方法是将不同距离的邻居对该样本产生的影响给予不同的权值(weight),如权值与距离成反比。
首先进行切分
(红色点为黑线)
首先通过索引可以确定自己所在的区域,找到自己与同区域节点的最短距离,但是这个最短距离不一定是到所有点的最短距离,所以以最短路径为半径,寻找相交的线,计算相交线区域的点的距离,取最短距离。
例子:以k=5为例,选择五个最短距离的邻居,三个红色,两个白色,黑色点就更倾向于红色点,所以被认为成红色点
KNN算法的思想:在训练集中数据和标签已知的情况下,输入测试数据,将测试数据的特征与训练集中对应的特征进行相互比较,找到训练集中与之最为相似的前K个数据,则该测试数据对应的类别就是K个数据中出现次数最多的那个分类。
如下步骤:
1)计算测试数据与各个训练数据之间的距离;
2)按照距离的递增关系进行排序;
3)选取距离最小的K个点;
4)确定前K个点所在类别的出现频率;
5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。
参考别人的一段样例代码:
from numpy import *
def createDataSet():
group = array([[1.0, 2.0], [1.2, 0.1], [0.1, 1.4], [0.3, 3.5]])
labels = ['A', 'A', 'B', 'B']
return group, labels
dataSet,labels = createDataSet()
input = array([1.1,0.3])
k = 3
def classify(input, dataSet, label, k):
dataSize = dataSet.shape[0]
####计算欧式距离
diff = tile(input, (dataSize, 1)) - dataSet
sqdiff = diff ** 2
squareDist = sum(sqdiff, axis=1) ###行向量分别相加,从而得到新的一个行向量
dist = squareDist ** 0.5
##对距离进行排序
sortedDistIndex = argsort(dist) ##argsort()根据元素的值从大到小对元素进行排序,返回下标
classCount = {}
for i in range(k):
voteLabel = label[sortedDistIndex[i]]
###对选取的K个样本所属的类别个数进行统计
classCount[voteLabel] = classCount.get(voteLabel, 0) + 1
###选取出现的类别次数最多的类别
maxCount = 0
for key, value in classCount.items():
if value > maxCount:
maxCount = value
classes = key
return classes
print("测试数据为:",createDataSet(),"分类结果为:",classify(input,dataSet,labels, k))
##给出训练数据以及对应的类别
HR数据集的代码:
#KNN 算法演示
import pandas as pd
from sklearn.preprocessing import MinMaxScaler,StandardScaler
from sklearn.preprocessing import LabelEncoder,OneHotEncoder
from sklearn.decomposition import PCA
#sl:satisfaction_level---False:MinMaxScaler;True:StandardScaler
#le:last_evaluation---False:MinMaxScaler;True:StandardScaler
#npr:number_project---False:MinMaxScaler;True:StandardScaler
#amh:average_monthly_hours--False:MinMaxScaler;True:StandardScaler
#tsc:time_spend_company--False:MinMaxScaler;True:StandardScaler
#wa:Work_accident--False:MinMaxScaler;True:StandardScaler
#pl5:promotion_last_5years--False:MinMaxScaler;True:StandardScaler
#dp:department--False:LabelEncoding;True:OneHotEncoding
#slr:salary--False:LabelEncoding;True:OneHotEncoding
def hr_preprocessing(sl=False,le=False,npr=False,amh=False,tsc=False,wa=False,pl5=False,dp=False,slr=False,lower_d=False,ld_n=1):
df=pd.read_csv("./data/HR.csv")
#1、清洗数据
df=df.dropna(subset=["satisfaction_level","last_evaluation"])
df=df[df["satisfaction_level"]<=1][df["salary"]!="nme"]
#2、得到标注
label = df["left"]
df = df.drop("left", axis=1)
#3、特征选择
#4、特征处理
scaler_lst=[sl,le,npr,amh,tsc,wa,pl5]
column_lst=["satisfaction_level","last_evaluation","number_project",\
"average_monthly_hours","time_spend_company","Work_accident",\
"promotion_last_5years"]
for i in range(len(scaler_lst)):
if not scaler_lst[i]:
df[column_lst[i]]=\
MinMaxScaler().fit_transform(df[column_lst[i]].values.reshape(-1,1)).reshape(1,-1)[0]
else:
df[column_lst[i]]=\
StandardScaler().fit_transform(df[column_lst[i]].values.reshape(-1,1)).reshape(1,-1)[0]
scaler_lst=[slr,dp]
column_lst=["salary","department"]
for i in range(len(scaler_lst)):
if not scaler_lst[i]:
if column_lst[i]=="salary":
df[column_lst[i]]=[map_salary(s) for s in df["salary"].values]
else:
df[column_lst[i]]=LabelEncoder().fit_transform(df[column_lst[i]])
df[column_lst[i]]=MinMaxScaler().fit_transform(df[column_lst[i]].values.reshape(-1,1)).reshape(1,-1)[0]
else:
df=pd.get_dummies(df,columns=[column_lst[i]])
if lower_d:
return PCA(n_components=ld_n).fit_transform(df.values),label
return df,label
d=dict([("low",0),("medium",1),("high",2)])
def map_salary(s):
return d.get(s,0)
def hr_modeling(features,label):
# 用train_test_split划分训练集、测试集、验证集
from sklearn.model_selection import train_test_split
f_v=features.values
l_v=label.values
#验证集占20%
X_tt,X_validation,Y_tt,Y_validation=train_test_split(f_v,l_v,test_size=0.2)
#训练集占60%,测试集占20%
X_train,X_test,Y_train,Y_test=train_test_split(X_tt,Y_tt,test_size=0.25)
#KNN
#KNeighborsClassifier可以直接查看最近的点
from sklearn.neighbors import NearestNeighbors,KNeighborsClassifier
# 设置k=3个邻居
knn_clf = KNeighborsClassifier(n_neighbors=3)
# 拟合,训练集
knn_clf.fit(X_train,Y_train)
# 验证验证集
Y_pred = knn_clf.predict(X_validation)
#衡量指标 准确率、召回率、F值
from sklearn.metrics import accuracy_score, recall_score, f1_score
print("验证集:")
print("ACC:",accuracy_score(Y_validation,Y_pred))
print("REC:",recall_score(Y_validation,Y_pred))
print("F-Score",f1_score(Y_validation,Y_pred))
# 验证测试集
Y_pred_test = knn_clf.predict(X_test)
print("测试集:")
# 衡量指标 准确率、召回率、F值
from sklearn.metrics import accuracy_score, recall_score, f1_score
print("ACC:", accuracy_score(Y_test, Y_pred_test))
print("REC:", recall_score(Y_test, Y_pred_test))
print("F-Score", f1_score(Y_test, Y_pred_test))
#存储模型
from sklearn.externals import joblib
#填入模型+取个名字
joblib.dump(knn_clf,"knn_clf")
#使用模型
knn_clf = joblib.load("knn_clf")
Y_pred = knn_clf.predict(X_validation)
print("存储:")
print("ACC:", accuracy_score(Y_validation, Y_pred))
print("REC:", recall_score(Y_validation, Y_pred))
print("F-Score", f1_score(Y_validation, Y_pred))
def main():
features,label=hr_preprocessing()
hr_modeling(features,label)
if __name__=="__main__":
main()