1. 程式人生 > 其它 >聚類(K-means)實現手寫數字識別-2

聚類(K-means)實現手寫數字識別-2

其他實現手寫數字識別的方法:
1.KNN實現手寫數字識別
2. 卷積神經網路(CNN)實現手寫數字識別
3. 全連線神經網路實現手寫數字識別
4. 聚類(K-means)實現手寫數字識別

  1. 實驗資料是老師收集了所有人的手寫數字圖片,且經過處理將影象生成了.txt檔案,如何生成點選這,如下圖
    在這裡插入圖片描述
  2. 程式碼實現
from __future__ import print_function
import numpy as np
import tensorflow as tf
from tensorflow.contrib.factorization import KMeans
from os import listdir
from
keras.utils import to_categorical """ 函式說明:將32x32的二進位制影象轉換為1x1024向量 """ def img2vector(filename): # 建立1x1024零向量 returnVect = np.zeros((1, 1024)) # 開啟檔案 fr = open(filename) # 按行讀取 for i in range(32): # 讀一行資料 lineStr = fr.readline() # 每一行的前32個元素依次新增到returnVect中
for j in range(32): returnVect[0, 32 * i + j] = float(lineStr[j]) # 返回轉換後的1x1024向量 return returnVect ''' 函式說明:獲取標籤 ''' def getLabel(Datapath): # 訓練集的Labels hwLabels = [] # 返回Datapath目錄下的檔名 trainingFileList = listdir(Datapath) # 返回資料夾下檔案的個數 m = len(
trainingFileList) # 從檔名中解析出訓練集的類別 for i in range(m): # 獲得檔案的名字 fileNameStr = trainingFileList[i] # 獲得分類的數字 classNumber = int(fileNameStr.split('_')[0]) # 將獲得的類別新增到hwLabels中 hwLabels.append(classNumber) return hwLabels ''' 函式說明:獲取資料 ''' def getData(Datapath): # 返回train目錄下的檔名 trainingFileList = listdir(Datapath) # 返回資料夾下檔案的個數 m = len(trainingFileList) # 初始化訓練的Mat矩陣,訓練集 trainingMat = np.zeros((m, 1024)) for i in range(m): # 獲得檔案的名字 fileNameStr = trainingFileList[i] # 將每一個檔案的1x1024資料儲存到trainingMat矩陣中 trainingMat[i, :] = img2vector(Datapath+'/%s' % (fileNameStr)) return trainingMat # 載入資料 train_images = getData('train') test_images = getData('testless') train_labels = getLabel('train') train_labels = to_categorical(train_labels) test_labels = getLabel('testless') test_labels = to_categorical(test_labels) full_data_x = train_images # 引數 num_steps = 1000 # 訓練次數 batch_size = 10 # 每一批的樣本數 k = 60 # clusters的數量 num_classes = 10 # 10分類 num_features = 1024 # 每張圖片是32*32 # 輸入圖片 X = tf.placeholder(tf.float32, shape=[None, num_features]) # Labels (將標籤分配給質心並用於測試) Y = tf.placeholder(tf.float32, shape=[None, num_classes]) # K-Means 的引數 # inputs:輸入張量或輸入張量列表。假設資料點先前已被隨機置換。 # num_clusters:一個整數張量,指定簇的數量。如果initial_clusters是張量或numpy陣列,則忽略此引數。 # distance_metric:用於群集的距離度量。支援的選項:“squared_euclidean”,“cosine”。 # use_mini_batch:如果為true,請使用小批量k-means演算法。 # mini_batch_steps_per_iteration:更新的叢集中心同步回主副本的步驟數。 kmeans = KMeans(inputs=X, num_clusters=k, distance_metric='cosine', use_mini_batch=True) # 建立 KMeans 模型 training_graph = kmeans.training_graph() # 返回值 # all_scores: 每個向量到每個簇的距離,是一個[樣本數, 簇數]的矩陣 # cluster_idx: 每個樣本被分到的簇的標記,為([樣本數], type)的元組 # scores: 每個樣本到其被分到的簇的距離,為[樣本數]大小的矩陣, # cluster_centers_initialized:返回bool值,cluster是否被初始化(不知道有什麼用) # init_op: 初始化操作,sess init的時候需要傳入樣本 # training_op: 訓練操作 if len(training_graph) > 6: (all_scores, cluster_idx, scores, cluster_centers_initialized, cluster_centers_var, init_op, train_op) = training_graph else: (all_scores, cluster_idx, scores, cluster_centers_initialized, init_op, train_op) = training_graph cluster_idx = cluster_idx[0] avg_distance = tf.reduce_mean(scores) # 用於計算張量tensor沿著指定的數軸(tensor的某一維度)上的的平均值 # 初始化變數 (用預設值) init_vars = tf.global_variables_initializer() sess = tf.Session() sess.run(init_vars, feed_dict={X: full_data_x}) sess.run(init_op, feed_dict={X: full_data_x}) # 使用之前 一定要使用資料初始化 KMeans # 訓練 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("Step %i, Avg Distance: %f" % (i, d)) # 為每個質心分配標籤 # 使用每次訓練的標籤計算每個質心的標籤總數 # 計算樣本到最近的質心 counts = np.zeros(shape=(k, num_classes)) # print(len(idx)) for i in range(len(idx)): counts[idx[i]] += train_labels[i] # 將最頻繁的標籤分配給質心 labels_map = [np.argmax(c) for c in counts] # print(labels_map) labels_map = tf.convert_to_tensor(labels_map) # 將給定值轉換為張量 # 評估 # 查詢:centroid_id 的標籤 cluster_label = tf.nn.embedding_lookup(labels_map, cluster_idx) # print(cluster_label) # 計算準確路 # tf.equal(x,y,name=None) # 判斷,x, y 是不是相等,它的判斷方法不是整體判斷, # 而是逐個元素進行判斷,如果相等就是True,不相等,就是False # 由於是逐個元素判斷,所以x,y 的維度要一致。 # tf.cast():用於改變某個張量的資料型別 # tf.argmax(input,axis)根據axis取值的不同返回每行或者每列最大值的索引。 # axis=0時比較每一列的元素,將每一列最大元素所在的索引記錄下來, # 最後輸出每一列最大元素所在的索引陣列。 # axis=1的時候,將每一行最大元素所在的索引記錄下來, # 最後返回每一行最大元素所在的索引陣列 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 = test_images, test_labels print("Test Accuracy:", sess.run(accuracy_op, feed_dict={X: test_x, Y: test_y}))