坐标KNN聚类python实例

来源:互联网 发布:淘宝网毛呢长裙 编辑:程序博客网 时间:2024/06/07 12:23

最近爬取搜房网上海新房的2000个小区和行政区,对其小区爬了坐标,去掉一些可见的异常点,结果分布如下,需要原数据的在这,可能会有噪声,只是自己拿来做做实验而已。链接:http://pan.baidu.com/s/1dFOiG5F 密码:cty5

首先尝试了一下K均值,结果如下

在这里K均值的缺点就暴露了,因为是无监督学习,所以仅仅依靠统计距离计算的准确率是不高的。

具体说来,K均值先通过人工选择K个样本作为K个初始均值向量,但是一般的操作是随机选择一些点作为初始聚类中心,而这些聚类中心需要尽可能的远。这便是Kmeans++。计算其他向量与K这个初始向量的距离,考察一遍之后再更新均值向量,迭代直到稳定。因此需要事先人工选择样本和中心个数,意味着需要一定的先验知识。同时K均值又对噪声和样本量比较敏感,比如上面两个图中最上面的样本和右上的样本其实是属于崇明区的,然而由于中间样本缺失,导致左右两头划分到不同的聚类中心去了。

使用了Kmeans无监督之后,接下来用有监督的KNN方法试试。

import pandas as pdimport numpy as npfrom sklearn.cross_validation import train_test_split from sklearn import neighbors    #导入K-means算法包  new_dff = pd.read_excel(u'C:/Users/user/Desktop/zuobiao.xlsx')#将dataframe转为向量x=pd.concat([new_dff['XLongitude'],new_dff['YLatitude']],axis=1)X=x.astype('float')X=X.as_matrix()y=new_dff["District"]print y.shapeY=y.astype('int')Y=np.array(Y)x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size = 0.2)  clf = neighbors.KNeighborsClassifier(algorithm='kd_tree')  clf.fit(x_train, y_train)from sklearn import metrics#准确度y_pred = clf.predict(x_test)scores =[]scores.append(metrics.accuracy_score(y_pred, y_test))print scores

然后计算了训练集和测试集的准确度为0.93702和0.89779,默认参数n_neighbors=5.整个过程其实是这样的,训练集和测试集的比例为8:2.抽取出训练集,即这80%的数据是已经打好了label。它没有明显的训练过程,在程序开始运行时,把数据集加载到内存后,不需要进行训练,就可以针对测试集开始分类。对于测试集的一个样本,选取在它周围的5的距离最近的点,观察它们属于哪个分类,将该样本投给分类占比最大的那个类别,以此类推。

说到有监督,还是要拿分类器做一下试试,于是我就拿了决策树和SVM进行交叉验证,发现两个的准确度为0.8837和0.8304,不如KNN的效果更好。想想本来坐标分类就是基于距离测算,决策树的切割为横纵切割,而坐标在地图上是更加不规则的。以下为决策树的效果显示,从缺点来看,决策树将最上面的右上的样本隔开,中间多了两个类别,其实是不对的,样本量的缺失同样会对决策树造成不小的影响。

from sklearn.tree import DecisionTreeClassifierfrom sklearn import treeclf = DecisionTreeClassifier(criterion='entropy', max_depth=100, min_samples_leaf=3)scores = cross_validation.cross_val_score(clf, X, Y, cv=10)print scores.mean()import matplotlibclf = DecisionTreeClassifier(criterion='entropy', max_depth=100, min_samples_leaf=3)dt_clf = clf.fit(X, Y)N, M = 500, 500  # 横纵各采样多少个值x1_min, x1_max = X[:, 0].min(), X[:, 0].max()  # 第0列的范围x2_min, x2_max = X[:, 1].min(), X[:, 1].max()  # 第1列的范围t1 = np.linspace(x1_min, x1_max, N)t2 = np.linspace(x2_min, x2_max, M)x1, x2 = np.meshgrid(t1, t2)  # 生成网格采样点x_test = np.stack((x1.flat, x2.flat), axis=1)  # 测试点y_hat = dt_clf.predict(x_test)  # 预测值y_hat = y_hat.reshape(x1.shape)  # 使之与输入的形状相同plt.pcolormesh(x1, x2, y_hat, cmap=plt.cm.Spectral, alpha=0.5)  # 预测值的显示Paired/Spectral/coolwarm/summer/spring/OrRd/Orangesplt.scatter(X[:, 0], X[:, 1], c=Y, edgecolors='k',cmap=plt.cm.prism)     # 样本的显示plt.xlabel(X[:, 0])plt.ylabel(X[:, 1])plt.xlim(x1_min, x1_max)plt.ylim(x2_min, x2_max)plt.grid()plt.show()
来看看SVM怎么处理的,SVM的处理更为平滑一点,看上去效果应该也要好于决策树,但是准确度却不是。这里的SVM采用了OVR的方式对多分类数据进行分类,核函数采用了rbf高斯核,不过左上角和右上角都被分为和右下角一样的类别,我想它在切分的时候应该是把左上角和右下角和右上一整块切成同一类别,之后再从中区别了其他类别才造成这样的错误了。总的来说,模型没有好坏,只有适不适用。由于样本数据有限而且对于KNN来说例子比较典型,所以目前看来还是KNN的效果最佳。



from sklearn import svmfrom sklearn import metrics#准确度x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size = 0.2) clf = svm.SVC(C=0.8, kernel='poly', gamma=20, decision_function_shape='ovr')clf.fit(x_train, y_train)x1_min, x1_max = X[:, 0].min(), X[:, 0].max()  # 第0列的范围x2_min, x2_max = X[:, 1].min(), X[:, 1].max()  # 第1列的范围x1, x2 = np.mgrid[x1_min:x1_max:500j, x2_min:x2_max:500j]  # 生成网格采样点grid_test = np.stack((x1.flat, x2.flat), axis=1)  # 测试点grid_hat = clf.predict(grid_test)       # 预测分类值grid_hat = grid_hat.reshape(x1.shape)  # 使之与输入的形状相同matplotlib.rcParams['font.sans-serif'] = [u'SimHei']matplotlib.rcParams['axes.unicode_minus'] = Falseplt.pcolormesh(x1, x2, grid_hat, cmap=plt.cm.Spectral, alpha=0.8)   # Paired/coolwarm/summer/spring/OrRd/Orangesplt.scatter(X[:, 0], X[:, 1], c=Y, edgecolors='k', s=50, cmap=plt.cm.prism)      # 样本的显示plt.scatter(x_test[:, 0], x_test[:, 1], s=120, facecolors='none', zorder=10)     # 圈中测试集样本plt.xlabel(X[:, 0], fontsize=13)plt.ylabel(X[:, 1], fontsize=13)plt.xlim(x1_min, x1_max)plt.ylim(x2_min, x2_max)plt.title(u'SVM二特征分类', fontsize=15)plt.grid()plt.show()


0 0
原创粉丝点击