本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.
KNN算法(K-Nearest Neighbors)
看完这篇博客你将学会:
用KNN算法来对数据进行分类
在这里,我们将用knn对一个顾客数据集进行分类。不过什幺是knn呢,什幺是 K-Nearest Neighbors ,直观翻译就是k个最近的邻居。
K-Nearest Neighbors是一种监督学习算法,为了预测未知数据的类别,它考虑了k个最近数据点的类别,并选择k个最近数据点中的大多数属于的那个类别作为预测类别。
这是KNN的直观表示
在这种情况下,我们有 A 类和 B 类的数据点。我们想预测星(测试数据点)是什幺。 如果我们考虑 k 值为 3(3 个最近的数据点),我们将获得 B 类的预测。然而,如果我们考虑 k 值为 6,我们将获得 A 类的预测。
从这个意义上说,重要的是要考虑 k 的值。 希望从这张图中,您应该了解什幺是 K-Nearest Neighbors 算法。 它在预测测试点的分类时会考虑“K”个最近邻(数据点)。
安装sklearn以及导入包
!pip install scikit-learn==0.23.1
导入需要的包
import numpy as np import matplotlib.pyplot as plt import pandas as pd import numpy as np from sklearn import preprocessing %matplotlib inline
关于数据集
想象一下,一家电信供应商已经按照服务使用模式对其客户群进行了细分,将客户分为四组。 如果人口统计数据可用于预测团体成员,公司可以为个别潜在客户定制优惠。 这是一个分类问题。 也就是说,给定具有预定义标签的数据集,我们需要建立一个模型来预测新案例或未知案例的类别。
这个例子侧重于使用人口统计数据(例如地区、年龄和婚姻)来预测。
名为 custcat 的目标字段有四个可能的值,对应于四个客户组,如下所示:
1- Basic Service
2- E-Service
3- Plus Service
4- Total Service
我们的目标是建立一个分类器,来预测未知案例的类别。 我们就将使用这次的knn来分类。
下载数据
https://cf-courses-data.s3.us.cloud-object-storage.appdomain.cloud/IBMDeveloperSkillsNetwork-ML0101EN-SkillsNetwork/labs/Module%203/data/teleCust1000t.csv
df = pd.read_csv('teleCust1000t.csv') df.head()
region | tenure | age | marital | address | income | ed | employ | retire | gender | reside | custcat | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2 | 13 | 44 | 1 | 9 | 64.0 | 4 | 5 | 0.0 | 0 | 2 | 1 |
1 | 3 | 11 | 33 | 1 | 7 | 136.0 | 5 | 5 | 0.0 | 0 | 6 | 4 |
2 | 3 | 68 | 52 | 1 | 24 | 116.0 | 1 | 29 | 0.0 | 1 | 2 | 3 |
3 | 2 | 33 | 33 | 0 | 12 | 33.0 | 2 | 0 | 0.0 | 1 | 1 | 1 |
4 | 2 | 23 | 30 | 1 | 9 | 30.0 | 1 | 2 | 0.0 | 0 | 4 | 3 |
数据可视化及分析
让我们看看数据集中每个类别有多少
df['custcat'].value_counts()
3 281 1 266 4 236 2 217 Name: custcat, dtype: int64
281 Plus Service, 266 Basic-service, 236 Total Service, and 217 E-Service customers
我们也可以画一个分布直方图来可视化一下
df.hist(column='income', bins=50)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NMbqQmvn-1660611613546)(output_20_1.png)]
特征集合
我们来定义特征集合, X:
df.columns
Index(['region', 'tenure', 'age', 'marital', 'address', 'income', 'ed', 'employ', 'retire', 'gender', 'reside', 'custcat'], dtype='object')
要使用 scikit-learn 库,我们必须将 Pandas 数据框转换为 Numpy 数组:
X = df[['region', 'tenure','age', 'marital', 'address', 'income', 'ed', 'employ','retire', 'gender', 'reside']] .values #.astype(float) X[0:5]
array([[ 2., 13., 44., 1., 9., 64., 4., 5., 0., 0., 2.], [ 3., 11., 33., 1., 7., 136., 5., 5., 0., 0., 6.], [ 3., 68., 52., 1., 24., 116., 1., 29., 0., 1., 2.], [ 2., 33., 33., 0., 12., 33., 2., 0., 0., 1., 1.], [ 2., 23., 30., 1., 9., 30., 1., 2., 0., 0., 4.]])
再来看看我们的标签
y = df['custcat'].values y[0:5]
array([1, 4, 3, 1, 3], dtype=int64)
标准化数据
数据标准化,就是让数据变成均值为0,方差为1。这个做法很好,特别是对于基于数据点距离的knn算法。
X = preprocessing.StandardScaler().fit(X).transform(X.astype(float)) X[0:5]
array([[-0.02696767, -1.055125 , 0.18450456, 1.0100505 , -0.25303431, -0.12650641, 1.0877526 , -0.5941226 , -0.22207644, -1.03459817, -0.23065004], [ 1.19883553, -1.14880563, -0.69181243, 1.0100505 , -0.4514148 , 0.54644972, 1.9062271 , -0.5941226 , -0.22207644, -1.03459817, 2.55666158], [ 1.19883553, 1.52109247, 0.82182601, 1.0100505 , 1.23481934, 0.35951747, -1.36767088, 1.78752803, -0.22207644, 0.96655883, -0.23065004], [-0.02696767, -0.11831864, -0.69181243, -0.9900495 , 0.04453642, -0.41625141, -0.54919639, -1.09029981, -0.22207644, 0.96655883, -0.92747794], [-0.02696767, -0.58672182, -0.93080797, 1.0100505 , -0.25303431, -0.44429125, -1.36767088, -0.89182893, -0.22207644, -1.03459817, 1.16300577]])
训练/测试集分割
Out of Sample Accuracy
是模型对模型未经过训练的数据做出的正确预测的百分比。 由于我们的模型过度拟合的可能性,在同一数据集上进行训练和测试很可能具有较低的样本外准确度。
重要的是,我们的模型具有较高的样本外准确度,因为任何模型的目的当然是对未知数据做出正确的预测。 那幺我们如何提高样本外的准确性呢? 一种方法是使用一种称为训练/测试拆分的评估方法。
训练/测试拆分涉及将数据集分别拆分为互斥的训练集和测试集。 之后,您使用训练集进行训练并使用测试集进行测试。
这将对样本外准确性提供更准确的评估,因为测试数据集不是用于训练模型的数据集的一部分。 对于现实世界的问题,它更精准一些。
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=4) print ('Train set:', X_train.shape, y_train.shape) print ('Test set:', X_test.shape, y_test.shape)
Train set: (800, 11) (800,) Test set: (200, 11) (200,)
分类
K nearest neighbor (KNN)
分类器实现 k 近邻投票。
from sklearn.neighbors import KNeighborsClassifier
我们首先看看 k
的4的时候的情形:
k = 4 #Train Model and Predict neigh = KNeighborsClassifier(n_neighbors = k).fit(X_train,y_train) neigh
KNeighborsClassifier(n_neighbors=4)
我们可以用训练出来的模型在测试集上进行预测:
yhat = neigh.predict(X_test) yhat[0:5]
array([1, 1, 3, 2, 4], dtype=int64)
准确性评估
在多标签分类中, accuracy classification score ( 准确度分类得分 )是计算子集准确度的函数。 此函数等同于 jaccard_score 函数。 本质上,它计算测试集中实际标签和预测标签的匹配程度。
from sklearn import metrics print("Train set Accuracy: ", metrics.accuracy_score(y_train, neigh.predict(X_train))) print("Test set Accuracy: ", metrics.accuracy_score(y_test, yhat))
Train set Accuracy: 0.5475 Test set Accuracy: 0.32
进一步练习
这次我们把k改成10。
# write your code here k = 10 neigh10 = KNeighborsClassifier(n_neighbors = k).fit(X_train,y_train) yhat10 = neigh10.predict(X_test) print("Train set Accuracy: ", metrics.accuracy_score(y_train, neigh10.predict(X_train))) print("Test set Accuracy: ", metrics.accuracy_score(y_test, yhat10))
Train set Accuracy: 0.4875 Test set Accuracy: 0.33
那其他的 k
呢?
KNN 中的 K 是要检查的最近邻的数量。 由用户指定,是最重要的参数。 那幺,我们如何才能为 K 选择正确的值呢?
一般的解决方案是保留一部分数据用于测试模型的准确性。 然后选择k = 1,使用训练部分进行建模,并使用测试集中的所有样本计算预测的准确性。 重复这个过程,增加 k,看看哪个 k 最适合我们的模型。
我们可以计算 KNN 对不同 k 值的准确度。
Ks = 10 mean_acc = np.zeros((Ks-1)) std_acc = np.zeros((Ks-1)) for n in range(1,Ks): #Train Model and Predict neigh = KNeighborsClassifier(n_neighbors = n).fit(X_train,y_train) yhat=neigh.predict(X_test) mean_acc[n-1] = metrics.accuracy_score(y_test, yhat) std_acc[n-1]=np.std(yhat==y_test)/np.sqrt(yhat.shape[0]) mean_acc
array([0.3 , 0.29 , 0.315, 0.32 , 0.315, 0.31 , 0.335, 0.325, 0.34 ])
绘制不同k的knn模型的准确性的图.
plt.plot(range(1,Ks),mean_acc,'g') plt.fill_between(range(1,Ks),mean_acc - 1 * std_acc,mean_acc + 1 * std_acc, alpha=0.10) plt.fill_between(range(1,Ks),mean_acc - 3 * std_acc,mean_acc + 3 * std_acc, alpha=0.10,color="green") plt.legend(('Accuracy ', '+/- 1xstd','+/- 3xstd')) plt.ylabel('Accuracy ') plt.xlabel('Number of Neighbors (K)') plt.tight_layout() plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-juwWjGc7-1660611613548)(output_50_0.png)]
print( "The best accuracy was with", mean_acc.max(), "with k=", mean_acc.argmax()+1)
The best accuracy was with 0.34 with k= 9
谢谢大家的观看。
Be First to Comment