1. 程式人生 > >K-means 影象聚類

K-means 影象聚類

import numpy as np
import tensorflow as tf
from tensorflow.contrib.factorization import KMeans

# 本程式碼演示K均值的用法, tensorflow版本必須大於等於V1.1.0
# 程式碼專案:Project: https://github.com/aymericdamien/TensorFlow-Examples/

# 由於tensorflow實現的K均值演算法無法從GPU中獲得額外好處,所以我們忽略GPU裝置
import os

os.environ['CUDA_VISIBLE_DEVICES'] = ''

# 匯入MNIST資料集
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets('../data', one_hot=True)
full_data_x = mnist.train.images # shape:(55000, 784),注意記住這個55000,理解後面會用到

# 模型超引數
num_steps = 50  # 訓練的總步數
batch_size = 1024  # 每個batch的樣本數
k = 25  # K的大小
num_classes = 10  # 十個數字,這也是模型最終分類的個數
num_features = 784  # 每個圖片都是28X28,共784個畫素

# 輸入圖片
X = tf.placeholder(tf.float32, shape=[None, num_features])
# 標註
Y = tf.placeholder(tf.float32, shape=[None, num_classes])

# K-Means的引數,其實是從庫裡使用提前封裝好的圖
kmeans = KMeans(inputs=X, num_clusters=k, distance_metric='cosine', use_mini_batch=True)

# 構建K-Means的計算圖
training_graph = kmeans.training_graph()

if len(training_graph) > 6:  # tensorflow 1.4及以上版本
    (all_scores, cluster_idx, scores, cluster_cnters_initialized,
     cluster_cnters_var, init_op, train_op) = training_graph
else:
    (all_scores, cluster_idx, scores, cluster_cnters_initialized,
     init_op, train_op) = training_graph

cluster_idx = cluster_idx[0] # 存放所有資料的圖心序號
avg_distance = tf.reduce_mean(scores) # 存放平均距離

# 初始化變數
init_vars = tf.global_variables_initializer()

# 建立一個tensorflow會話
sess = tf.Session()

# 執行初始化操作
sess.run(init_vars, feed_dict={X: full_data_x})
sess.run(init_op, feed_dict={X: full_data_x})

# 訓練
for i in range(1, num_steps + 1):
    _, d, idx = sess.run([train_op, avg_distance, cluster_idx], feed_dict={X: full_data_x})

    if i % 10 == 0 or i == 1:
        print('步驟 %i, 平均距離是:%f' % (i, d))

# 給每個圖心分配一個標籤
# 計算每個圖心的樣本個數,把樣本歸入離它最近的圖心(使用idx)
counts = np.zeros(shape=(k, num_classes))  # counts的shape是(25, 10),用於存放25個圖心分類的頻率計數
for i in range(len(idx)):
    # idx的shape是(55000,),每個成員都是0~24之間的值,對應所屬圖心的編號
    counts[idx[i]] += mnist.train.labels[i]
    # mnist.train.labels的shape是(55000, 10), 每個成員都是獨熱編碼,用來標註屬於哪個數字

# 將最高頻的標註分配給圖心。 len(labels_map)是25,也就是每個圖心一個成員,記錄每個圖心所屬的數字分類
labels_map = [np.argmax(c) for c in counts]
# 轉換前,labels_map的shape為(25,)
labels_map = tf.convert_to_tensor(labels_map)
# 此時labels_map變成了一個const op,輸出就是上面(25,)包含的值

# 評估模型。下面開始構建評估計算圖
# 注意:centroid_id就是對應label
cluster_label = tf.nn.embedding_lookup(labels_map, cluster_idx)
# cluster_idx輸出的tensor,每個成員都對映到labels_map的一個值。
# cluster_label的輸出就是對映的label值,後面用來跟標註比較計算準確度

# 計算準確率
correct_prediction = tf.equal(cluster_label, tf.cast(tf.argmax(Y, 1), tf.int32))
accuracy_op = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

# 測試模型
test_x, test_y = mnist.test.images, mnist.test.labels
print("測試準確率:", sess.run(accuracy_op, feed_dict={X: test_x, Y: test_y}))