無監督學習筆記
無監督學習
1、簡介
無監督學習是一種對不含標記的數據建立模型的機器學習範式。最常見的無監督學習方法是聚類,就是講無標記的數據分成幾種集群,這些集群通常是根據某種相似度指標進行的,如歐氏距離(Euclidean distance),常用領域有:數據挖掘、醫學影像、股票市場分析、計算機視覺、市場細分等。
2、用k-means算法聚類數據
k-means算法常用數據的不同屬性將輸入數據劃分成k組。分組是使用最優化的技術實現的,即讓各組的數據點與該組中心點的距離平方和最小化。例子如下:
import matplotlib.pyplot as plt import numpy as np from sklearn.cluster import KMeans def load_data(input_file): X = [] with open(input_file, ‘r‘) as f: for line in f.readlines(): data = [float(x) for x in line.split(‘,‘)] X.append(data) return np.array(X) # 1、獲取數據並可視化 input_file = ‘data_multivar.txt‘ data = load_data(input_file) x_min,x_max=min(data[:,0])-1,max(data[:,0])+1 y_min,y_max=min(data[:,1])-1,max(data[:,1])+1 ‘‘‘ plt.figure() plt.scatter(data[:,0], data[:,1], facecolors=‘none‘, edgecolors=‘k‘) plt.xlim(x_min,x_max) plt.ylim(y_min,y_max) plt.show() ‘‘‘ # 2、獲取k-means對象,並訓練 kmeans=KMeans(n_clusters=4,init=‘k-means++‘,n_init=10) kmeans.fit(data) # 3、獲取邊界 step_size=0.01 x_values,y_values=np.meshgrid(np.arange(x_min,x_max,step_size),np.arange(y_min,y_max,step_size)) predict_labels=kmeans.predict(np.c_[x_values.ravel(),y_values.ravel()]) predict_labels=predict_labels.reshape(x_values.shape) # 4、畫出邊界 plt.figure() plt.clf() plt.imshow(predict_labels, interpolation=‘nearest‘, extent=(x_values.min(), x_values.max(), y_values.min(), y_values.max()), cmap=plt.cm.Paired, aspect=‘auto‘, origin=‘lower‘) plt.scatter(data[:,0], data[:,1], facecolors=‘none‘, edgecolors=‘k‘) centero=kmeans.cluster_centers_ plt.scatter(centero[:,0],centero[:,1],linewidths=5,facecolor=‘black‘) plt.xlim(x_min,x_max) plt.ylim(y_min,y_max) plt.show()
圖片顯示如下:
3、用矢量量化壓縮圖片
k-means聚類的主要應用之一就是矢量量化。矢量量化就是“四舍五入”(rounding off)的N維版本。在處理數字等一維數據時,會用四舍五入技術減少存儲空間。矢量量化被廣泛應用於圖片壓縮,用比原始圖像更少的比特數來存儲每個像素,從而實現圖像圖片。
import argparse
# 1、創建一個函數,用來解析輸入參數,輸入參數為圖片和每個像素被壓縮的比特數。 def build_arg_parser(): parser = argparse.ArgumentParser(description=‘輸入圖片‘) parser.add_argument(‘--input-file‘, dest=‘input_file‘, required=True, help=‘輸入圖片‘) parser.add_argument(‘--num-bits‘, dest=‘num_bits‘, type=int, required=False, help=‘比特數‘) return parser # 2、壓縮輸入圖片 def compress_img(img, num_cluster): print(img) X = img.reshape(-1, 1) print(X) kmeans = KMeans(n_clusters=num_cluster, n_init=4, random_state=5) kmeans.fit(X) contrid = kmeans.cluster_centers_.squeeze() labels = kmeans.labels_ input_compress = np.choose(labels, contrid).reshape(img.shape) return input_compress # 3、查看壓縮算法對圖片質量的影響 def plot_image(img,title): vmin=img.min() vmax=img.max() plt.figure() plt.title(title) plt.imshow(img,cmap=plt.cm.gray,vmin=vmin,vmax=vmax) if __name__ == ‘__main__‘: args = build_arg_parser().parse_args() input_file=args.input_file num_bits=args.num_bits if not 1<=num_bits<=8: raise TypeError(‘比特數應該在1和8之間‘) num_clusters=np.power(2,num_bits) compression_rate=round(100*(8.0-args.num_bits)/8.0,2) input_image=misc.imread(input_file,True).astype(np.uint8) plot_image(input_image,‘image‘) input_compress=compress_img(input_image,num_clusters) plot_image(input_compress,‘rate=‘+str(compression_rate)+‘%‘) plt.show()
4、建立均值漂移聚類模型
均值漂移是一種非常強大的無監督學習算法,用於集群數據點。該算法把數據點的分布看成是概率密度函數(probability-density function),希望在特征空間中根據函數分布特征找出數據點的“模式”(mode),這些“模式”就對應於一群群局部最密集(local maxima)分布的點。該算法的優點在於它無需事先確定集群的數量。例子如下:
# 均值漂移聚類模型 from sklearn.cluster import MeanShift,estimate_bandwidth # 1、獲取數據 X=load_data(‘data_multivar.txt‘) # 2、通過指定輸入參數創建均值漂移模型 bandwidth=estimate_bandwidth(X,quantile=0.1,n_samples=len(X)) meanshift=MeanShift(bandwidth=bandwidth,bin_seeding=True) # 3、訓練模型 meanshift.fit(X) # 4、提取標記 labels=meanshift.labels_ # 5、獲取集群中心點,並打印數量 centroids=meanshift.cluster_centers_ num_clusters=len(np.unique(labels)) print(labels) print(centroids) print(num_clusters,len(centroids)) # 6、可視化 markers=‘.*xv‘ plt.figure() for i,marker in zip(range(len(markers)),markers): plt.scatter(X[labels==i,0],X[labels==i,1],marker=marker,color=‘k‘) centroid=centroids[i] plt.plot(centroid[0],centroid[1],marker=‘o‘,markersize=15,markeredgecolor=‘k‘,markerfacecolor=‘k‘) plt.title(‘顯示‘) plt.show()
5、用凝聚層次聚類進行分組
層次聚類:一組聚類算法,通過不斷的分解或合並集群來構建樹狀集群(tree-like clusters),其結構可用一棵樹表示。該算法可自上而下,也可自下而上。
凝聚層次聚類:即自下而上的算法,每一個數據點被看做一個單獨的子集,而讓這些子集不斷的合並,直到所有集合合並為一個巨型集群。相反,自上而下則是分解。直到所有集群變為一個單獨的數據點。
def get_spiral(t,noise_amplitude=0.5):# 獲取呈螺旋狀的數據
r=t
x=r*np.cos(t)
y=r*np.sin(t)
return add_noise(x,y,noise_amplitude)
def get_rose(t,noise_amplitude=0.02):# 獲取呈螺旋狀的數據
k=5
r=np.cos(k*t)+0.25
x=r*np.cos(t)
y=r*np.sin(t)
return add_noise(x,y,noise_amplitude)
def get_hypotrochoid(t, noise_amplitude=0):
a, b, h = 10.0, 2.0, 4.0
x = (a - b) * np.cos(t) + h * np.cos((a - b) / b * t)
y = (a - b) * np.sin(t) - h * np.sin((a - b) / b * t)
return add_noise(x, y, 0)
def add_noise(x,y,amplitude):# 添加噪音
X=np.concatenate((x,y))
X+=amplitude*np.random.randn(2,X.shape[1])
return X.T
from sklearn.cluster import AgglomerativeClustering
def perform_clustering(X,connectivity,title,num_clusters=3,linkage=‘ward‘):# 設置層次凝聚模型
plt.figure()
model=AgglomerativeClustering(linkage=linkage,n_clusters=num_clusters,connectivity=connectivity)
model.fit(X)
labels=model.labels_
markers=‘.vx‘
for i,marker in zip(range(num_clusters),markers):
plt.scatter(X[labels==i,0],X[labels==i,1],s=50,facecolor=‘none‘,marker=marker,color=‘k‘)
plt.title(title)
from sklearn.neighbors import kneighbors_graph
if __name__==‘__main__‘:
# 生成樣本數據
n_samples=500
np.random.seed(2)
t=2.5*np.pi*(1+2*np.random.rand(1,n_samples))
X=get_spiral(t)
# X = get_rose(t)
# X = get_hypotrochoid(t)
connectivity=None
perform_clustering(X,connectivity,‘沒有連接‘)
connectivity=kneighbors_graph(X,10,include_self=False)
perform_clustering(X,connectivity,‘knei連接‘)# 可讓連接在一起的數據組合在一起
plt.show()
6、評價聚類算法的聚類效果
輪廓系數(Sihouette Coefficient)系數:得分=(x-y)/max(x,y),其中x表示在同一個集群中某個數據點與其他數據點的平均距離,y表示某個數據點與最近的另一個集群的所有點的平均距離,使用例子如下:
from sklearn import metrics
data=load_data(‘data_perf.txt‘)# 加載數據
scores=[]
range_values=np.arange(2,10)
for i in range_values:# 分別分i個集群
kmean=KMeans(n_clusters=i,n_init=10,init=‘k-means++‘)
kmean.fit(data)
score=metrics.silhouette_score(data,kmean.labels_,metric=‘euclidean‘,sample_size=len(data))
scores.append(score)
plt.figure()
plt.bar(range_values,scores,width=0.6,color=‘k‘,align=‘center‘)
plt.show()
plt.figure()
plt.scatter(data[:,0],data[:,1],color=‘k‘)
xmin,xmax=min(data[:,0])-1,max(data[:,0])+1
ymin,ymax=min(data[:,1])-1,max(data[:,1])+1
plt.xlim(xmin,xmax)
plt.ylim(ymin,ymax)
plt.show()
7、用DBSCAN算法自動估算集群數量
DBSCAN(Density-Based Spatial Clustering of Applications with Noise):帶噪聲的基於密度的聚類方法,將數據點看成是緊密集群的若幹組,若某個點屬於一個集群,那會有許多點也屬於同一個集群,該方法裏面有一個epsilon參數,可控制該點到其他點的最大距離。若兩點間距離超過epsilon,則他們不可能在一個集群中。該方法主要有點是它可以處理異常值,若某些點位於數據稀疏距離,則將其作為異常點,而不會強制將他們放入一個集群中。例子如下:
# 1、獲取數據
X=load_data(‘data_perf.txt‘)
# 2、初始化參數
eps_grid=np.linspace(0.3,1.2,num=10)
silhouette_scores=[]
eps_best=eps_grid[0]
silhouette_scores_max=-1
model_best=None
labels_best=None
# 3、以此執行所有參數
from sklearn.cluster import DBSCAN
from sklearn import metrics
for eps in eps_grid:
model=DBSCAN(eps=eps,min_samples=5).fit(X)
labels=model.labels_
silhouette_score=round(metrics.silhouette_score(X,labels),4)
silhouette_scores.append(silhouette_score)
# 獲取指標的最佳得分
if silhouette_score>silhouette_scores_max:
silhouette_scores_max=silhouette_score
eps_best=eps
model_best=model
labels_best=labels
# 4、畫出條形圖
plt.figure()
plt.bar(eps_grid,silhouette_scores,width=0.05,color=‘k‘,align=‘center‘)
plt.show()
# 5、由於可能會有某些點還沒有分配集群,所以這裏刪除未分配而獲取集群的數量
offset=0
if -1 in labels:
offset=1
num_clusters=len(set(labels))-offset
# 6、提取核心樣本
model = model_best
labels = labels_best
mask_core=np.zeros(labels.shape,dtype=np.bool)# 初始化全部點的分配
mask_core[model.core_sample_indices_]=True# model.core_sample_indices_表示分配後的數據位置為True
# 7、數據可視化
from itertools import cycle
plt.figure()
labels_uniq=set(labels)
markers=cycle(‘vo^s<>‘)
for cur_label,marker in zip(labels_uniq,markers):
if cur_label==-1:
marker=‘.‘
cur_mask=(labels==cur_label)# 獲取當前某個數據集的集合的索引
cur_data=X[cur_mask&mask_core]# 當前數據集中正常的數據
plt.scatter(cur_data[:,0],cur_data[:,1],marker=marker,edgecolors=‘black‘,s=96,facecolors=‘none‘)
cur_data=X[cur_mask&-mask_core]# 當前數據集中異常數據
plt.scatter(cur_data[:,0],cur_data[:,1],marker=marker,edgecolors=‘black‘,s=32)
plt.show()
8、近鄰傳播聚類
近鄰傳播聚類(Affinity Propagation):找出數據中每個集群的代表性數據點,找到數據點間的相似性度量值,並把所有數據點看成潛在的代表性數據點,也稱取樣器(exemplar)。具體查看如下鏈接:http://blog.csdn.net/u010161379/article/details/51636926
9、建立客戶細分模型
市場細分對廣告投放、庫存管理、配送策略的實施、大眾傳媒等市場行為都非常有用。在不同類型商品的銷售數據中,為客戶提供最優的銷售和分銷策略,例子如下:
# 1、獲取數據
import csv
input_file=‘wholesale.csv‘
file_reader=csv.reader(open(input_file,‘r‘),delimiter=‘,‘)
X=[]
for count,row in enumerate(file_reader):
if not count:
names=row[2:]
continue
X.append([float(x) for x in row[2:]])
X=np.array(X)
# 2、使用均值漂移訓練數據
from sklearn.cluster import MeanShift,estimate_bandwidth
bandwidth=estimate_bandwidth(X,quantile=0.8,n_samples=len(X))
model=MeanShift(bandwidth=bandwidth,bin_seeding=True)
model.fit(X)
labels=model.labels_
clucenters=model.cluster_centers_
num_centers=len(clucenters)
# 3、打印集群中心
print(‘\t‘.join([name[:3] for name in names]))
print(‘\t‘.join([str(clucenter) for clucenter in clucenters]))
# 4、把milk與groceries的聚類結果可視化
centriods_milk_groceries=clucenters[:,1:3]
plt.figure()
plt.scatter(centriods_milk_groceries[:,0],centriods_milk_groceries[:,1],color=‘k‘,s=100,facecolor=‘none‘)
offset=0.2
plt.xlim(centriods_milk_groceries[:,0].min()-offset*centriods_milk_groceries[:,0].ptp(),centriods_milk_groceries[:,0].max()+offset*centriods_milk_groceries[:,0].ptp())
plt.xlim(centriods_milk_groceries[:,1].min()-offset*centriods_milk_groceries[:,1].ptp(),centriods_milk_groceries[:,1].max()+offset*centriods_milk_groceries[:,1].ptp())
plt.show()
無監督學習筆記