其他实现手写数字识别的方法:
1.KNN实现手写数字识别
2. 卷积神经网络(CNN)实现手写数字识别
3. 全连接神经网络实现手写数字识别
4. 聚类(K-means)实现手写数字识别
- 实验数据是老师收集了所有人的手写数字图片,且经过处理将图像生成了.txt文件,如何生成点击这,如下图
- 代码实现
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}))