聚类(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}))
  • 3
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值