k均值:
import numpy as np
In [2]:
def loadDataSet(filename): """ 读取数据集 Args: filename: 文件名 Returns: dataMat: 数据样本矩阵 """ dataMat = [] with open(filename, 'rb') as f: for line in f: eles = map(float,line.strip().split('\t')) dataMat.append(eles) return dataMat
In [3]:
def distEclud(vecA, vecB): """ 计算两向量的欧氏距离 Args: vecA: 向量A vecB: 向量B Returns: 欧式距离 """ return np.sqrt(np.sum(np.power(vecA - vecB, 2)))
In [4]:
def randCent(dataSet, k): """ 随机生成k个聚类中心 Args: dataSet: 数据集 k: 簇数目 Returns: centroids: 聚类中心矩阵 """ m, _ = dataSet.shape # 随机从数据集中选几个作为初始聚类中心 centroids = dataSet.take(np.random.choice(80,k), axis=0) return centroids
In [5]:
def kMeans(dataSet, k, maxIter = 5): """ K-Means Args: dataSet: 数据集 k: 聚类数 Returns: centroids: 聚类中心 clusterAssment: 点分配结果 """ # 随机初始化聚类中心 centroids = randCent(dataSet, k) init_centroids = centroids.copy() m, n = np.shape(dataSet) # 点分配结果: 第一列指明样本所在的簇,第二列指明该样本到聚类中心的距离 clusterAssment = np.mat(np.zeros((m, 2))) # 标识聚类中心是否仍在改变 clusterChanged = True # 直至聚类中心不再变化 iterCount = 0 while clusterChanged and iterCount < maxIter: iterCount += 1 clusterChanged = False # 分配样本到簇 for i in range(m): # 计算第i个样本到各个聚类中心的距离 minIndex = 0 minDist = np.inf for j in range(k): dist = distEclud(dataSet[i, :], centroids[j, :]) if(dist < minDist): minIndex = j minDist = dist # 任何一个样本的类簇分配发生变化则认为变化 if(clusterAssment[i, 0] != minIndex): clusterChanged = True clusterAssment[i, :] = minIndex, minDist**2 # 刷新聚类中心: 移动聚类中心到所在簇的均值位置 for cent in range(k): # 通过数组过滤获得簇中的点 ptsInCluster = dataSet[np.nonzero( clusterAssment[:, 0].A == cent)[0]] if ptsInCluster.shape[0] > 0: # 计算均值并移动 centroids[cent, :] = np.mean(ptsInCluster, axis=0) return centroids, clusterAssment, init_centroids
In [6]:
import matplotlib.pyplot as plt
In [7]:
%matplotlib inline
In [8]:
dataMat = np.mat(loadDataSet('data/testSet.txt')) m,n = np.shape(dataMat)
In [9]:
set_k = 2 centroids, clusterAssment, init_centroids = kMeans(dataMat, set_k) clusterCount = np.shape(centroids)[0] clusterCount
Out[9]:
2
In [10]:
# 注意,我们这里只设定了最多四个簇的样式,所以前面如果set_k设置超过了4,后面就会出现index error patterns = ['o', 'D', '^', 's'] colors = ['b', 'g', 'y', 'black']
In [11]:
fig = plt.figure() title = 'kmeans with k={}'.format(set_k) ax = fig.add_subplot(111, title=title) for k in range(clusterCount): # 绘制聚类中心 ax.scatter(centroids[k, 0], centroids[k, 1], color='r', marker='+', linewidth=20) # 绘制初始聚类中心 ax.scatter(init_centroids[k,0], init_centroids[k,1], color='purple', marker='*', linewidths=10) for i in range(m): # 绘制属于该聚类中心的样本 ptsInCluster = dataMat[np.nonzero(clusterAssment[:, 0].A==k)[0]] ax.scatter(ptsInCluster[:, 0].flatten().A[0], ptsInCluster[:, 1].flatten().A[0], marker=patterns[k], color=colors[k])
In [ ]:
PCA:
from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.decomposition import PCA from sklearn.linear_model import LogisticRegression from sklearn import metrics import matplotlib.pyplot as plt from sklearn.datasets import load_wine from sklearn.pipeline import make_pipeline
In [2]:
plt.rcParams['font.sans-serif']=['SimHei'] plt.rcParams['axes.unicode_minus']=False
In [3]:
%matplotlib inline
In [4]:
features, target = load_wine(return_X_y=True) # 三分类的酒数据集 features.shape, target.shape
Out[4]:
((178, 13), (178,))
In [5]:
RANDOM_STATE = 42 # 将数据切分成7:3分别作为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.30, random_state=RANDOM_STATE)
In [6]:
# 不使用PCA raw_clf = make_pipeline(StandardScaler(), LogisticRegression()) raw_clf.fit(X_train, y_train) pred_test_raw = raw_clf.predict(X_test)
In [7]:
# 使用PCA但不做数据预处理 unscaled_clf = make_pipeline(PCA(n_components=2), LogisticRegression()) unscaled_clf.fit(X_train, y_train) pred_test = unscaled_clf.predict(X_test)
In [8]:
# 使用PCA,同时做数据预处理 std_clf = make_pipeline(StandardScaler(), PCA(n_components=2), LogisticRegression()) std_clf.fit(X_train, y_train) pred_test_std = std_clf.predict(X_test)
In [9]:
# 查看各情况下的分类准确率 print u'\n不使用PCA,预测准确率:', '{:.2%}'.format(metrics.accuracy_score(y_test, pred_test_raw)) print u'\n使用PCA但不预处理,预测准确率:', '{:.2%}'.format(metrics.accuracy_score(y_test, pred_test)) print u'\n使用PCA且预处理,预测准确率:', '{:.2%}'.format(metrics.accuracy_score(y_test, pred_test_std))
不使用PCA,预测准确率: 98.15% 使用PCA但不预处理,预测准确率: 74.07% 使用PCA且预处理,预测准确率: 98.15%
In [10]:
# 将pca信息抽取出来 pca = unscaled_clf.named_steps['pca'] pca_std = std_clf.named_steps['pca']
In [11]:
# 打印最主要的主成分。注意,它是特征空间中的主成分轴,表达了数据中具有最大方差的方向 print u'\n未预处理第一主成分:\n', pca.components_[0] print u'\n预处理第一主成分:\n', pca_std.components_[0]
未预处理第一主成分: [ 1.76342917e-03 -8.35544737e-04 1.54623496e-04 -5.31136096e-03 2.01663336e-02 1.02440667e-03 1.53155502e-03 -1.11663562e-04 6.31071580e-04 2.32645551e-03 1.53606718e-04 7.43176482e-04 9.99775716e-01] 预处理第一主成分: [ 0.13443023 -0.25680248 -0.0113463 -0.23405337 0.15840049 0.39194918 0.41607649 -0.27871336 0.33129255 -0.11383282 0.29726413 0.38054255 0.27507157]
In [12]:
# 对训练数据进行PCA降维以备绘图 X_train_nostd = pca.transform(X_train) scaler = std_clf.named_steps['standardscaler'] X_train_std = pca_std.transform(scaler.transform(X_train)) FIG_SIZE = (10, 7) fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=FIG_SIZE) # 不预处理的PCA for l, c, m in zip(range(0, 3), ('blue', 'red', 'green'), ('^', 's', 'o')): ax1.scatter(X_train_nostd[y_train == l, 0], X_train_nostd[y_train == l, 1], color=c, label='class %s' % l, alpha=0.5, marker=m ) # 预处理后的PCA for l, c, m in zip(range(0, 3), ('blue', 'red', 'green'), ('^', 's', 'o')): ax2.scatter(X_train_std[y_train == l, 0], X_train_std[y_train == l, 1], color=c, label='class %s' % l, alpha=0.5, marker=m ) ax1.set_title(u'PCA降维后的训练集') ax2.set_title(u'特征放缩+PCA降维后的训练集') for ax in (ax1, ax2): ax.set_xlabel(u'第一主成分') ax.set_ylabel(u'第二主成分') ax.legend(loc='upper right') ax.grid() plt.tight_layout()
/Users/sunkepeng/anaconda2/lib/python2.7/site-packages/matplotlib/font_manager.py:1331: UserWarning: findfont: Font family [u'sans-serif'] not found. Falling back to DejaVu Sans (prop.get_family(), self.defaultFamily[fontext]))
In [ ]: