TensorFlow學習(二) 資料聚類分析
本文通過K均值演算法作為例子研究資料聚類分析
一、無監督學習概念
無監督學習可以從給定的資料集中找到感興趣的模式。
無監督學習,一般不給出模式的相關資訊。所以,無監督學習演算法需要自動探索資訊是怎樣組成的,並識別資料中的不同結構。
二、什麼是聚類
聚類就是對大量未知標註的資料集,按資料的內在相似性將資料集劃分為多個類別,使類別內的資料相似度較大而類別間的資料相似度較小。
聚類中沒有任何指導資訊,完全按照資料的分佈進行類別劃分。
聚類的大小和結構都沒有事先假定。
聚類屬於無監督學習。
三、K均值演算法
1.基本原理
k均值演算法試圖將給定的資料分割為k個不相交的組(group)或者簇(cluster),每個簇的指標就是該組所有成員的均值。這個點通常稱為質心,指具有相同名稱的算術實體,並且可以被表示為任意維度中的向量。
判據和目標是最小化簇成員到包含該成員的簇的實際質心的平方距離的總和。這也稱為慣性最小化,k均值的損失函式如下:
2.具體流程
(1)設定初始類別數K,人為設定K個類別中心;
(2)根據樣本和類別中心的距離進行類別劃分,樣本劃分到距離最近的類別;
(3)重新計算當前類別劃分下每類的中心(類別樣本平均值);
(4)在得到類別中心下繼續進行類別劃分;
(5)如果連續兩次的類別劃分結果不變則停止演算法;否則迴圈2~5 ;
3.如何確定資料之間的相似度
可以採用歐式距離、曼哈頓距離、餘弦相似度等等。這裡就不對具體的相似度計算進行探討。
四、使用TensorFlow進行資料聚類分析。
首先匯入資料集,使用sklearn生成資料集
blobs資料集設定類別K為4
circle資料集設定類別K為2
import tensorflow as tf import numpy as np import time import matplotlib import matplotlib.pyplot as plt from sklearn.datasets.samples_generator import make_blobs from sklearn.datasets.samples_generator import make_circles DATA_TYPE = 'blobs' N=200 # Number of clusters, if we choose circles, only 2 will be enough if (DATA_TYPE == 'circle'): K=2 else: K=4
centers為我們指定的初始質心
生成資料集並且使用matplotlib繪製資料集
centers = [(-2, -2), (-2, 1.5), (1.5, -2), (2, 1.5)]
if (DATA_TYPE == 'circle'):
data, features = make_circles(n_samples=200, shuffle=True, noise= 0.01, factor=0.4)
else:
data, features = make_blobs (n_samples=200, centers=centers, n_features = 2, cluster_std=0.8, shuffle=False, random_state=42)
fig, ax = plt.subplots()
ax.scatter(np.asarray(centers).transpose()[0], np.asarray(centers).transpose()[1], marker = 'o', s = 250)
plt.show()
fig, ax = plt.subplots()
if (DATA_TYPE == 'blobs'):
ax.scatter(np.asarray(centers).transpose()[0], np.asarray(centers).transpose()[1], marker = 'o', s = 250)
ax.scatter(data.transpose()[0], data.transpose()[1], marker = 'o', s = 100, c = features, cmap=plt.cm.coolwarm )
plt.show()
points用於存放資料集的座標
cluser_assignments用於存放每個資料的類別
centroids用於儲存每個組質心的座標
points=tf.Variable(data)
cluster_assignments = tf.Variable(tf.zeros([N], dtype=tf.int64)) # 樣本歸屬聚類中心……
centroids = tf.Variable(tf.slice(points.initialized_value(), [0,0], [K,2])) # 初始聚類中心……
初始化模型的引數
sess = tf.Session()
sess.run(tf.global_variables_initializer())
sess.run(centroids)
計算所有樣本與聚類中心的距離。
對所有的質心做N次複製,對每個 樣本做K次複製,這樣,樣本點和質心的形狀都是N*K*2。我們就可以計算每一個樣本到每一個質心點之間在所有維度上的距離
rep_centroids = tf.reshape(tf.tile(centroids, [N, 1]), [N, K, 2])
rep_points = tf.reshape(tf.tile(points, [1, K]), [N, K, 2])
對所有維度求和,得到“和最小”的那個索引(這個索引就是每個點所屬的新的類)Centroids也會在每個迭代之後由bucket_mean函式更新。
sum_squares = tf.reduce_sum(tf.square(rep_points - rep_centroids),
reduction_indices=2)
best_centroids = tf.argmin(sum_squares, 1) # 樣本對應的聚類中心索引
停止條件是所有的質心不再變化
did_assignments_change = tf.reduce_any(tf.not_equal(best_centroids, cluster_assignments))
def bucket_mean(data, bucket_ids, num_buckets):
total = tf.unsorted_segment_sum(data, bucket_ids, num_buckets)
count = tf.unsorted_segment_sum(tf.ones_like(data), bucket_ids, num_buckets)
return total / count
means = bucket_mean(points, best_centroids, K)
使用control_dependencies來控制是否更新質心
with tf.control_dependencies([did_assignments_change]):
do_updates = tf.group(
centroids.assign(means),
cluster_assignments.assign(best_centroids))
更新質心
changed = True
iters = 0
fig, ax = plt.subplots()
if (DATA_TYPE == 'blobs'):
colourindexes=[2,1,4,3]
else:
colourindexes=[2,1]
while changed and iters < MAX_ITERS:
fig, ax = plt.subplots()
iters += 1
[changed, _] = sess.run([did_assignments_change, do_updates])
[centers, assignments] = sess.run([centroids, cluster_assignments])
ax.scatter(sess.run(points).transpose()[0], sess.run(points).transpose()[1], marker = 'o', s = 200, c = assignments, cmap=plt.cm.coolwarm )
列印結果
ax.scatter(centers[:,0],centers[:,1], marker = '^', s = 550, c = colourindexes, cmap=plt.cm.plasma)
ax.set_title('Iteration ' + str(iters))
plt.savefig("kmeans" + str(iters) +".png")
ax.scatter(sess.run(points).transpose()[0], sess.run(points).transpose()[1], marker = 'o', s = 200, c = assignments, cmap=plt.cm.coolwarm )
plt.show()
end = time.time()
print(("Found in %.2f seconds" % (end-start)), iters, "iterations")
print("Centroids:")
print(centers)
print("Cluster assignments:", assignments)
執行結果