CNN卷积神经网络识别sklearn包中的数数据手写数字

# -*- coding: utf-8 -*-
"""
Created on Fri Mar 30 10:32:41 2018
学习CNN卷积神经网络程序
学习网址:https://blog.csdn.net/cxmscb/article/details/71023576
@author: admin

整体思路:输入层 -> 卷积层(激活层)-> 池化层 -> 卷积层 ->BN归一化层+激活层 -> 池化层 -> 全连接层 ->输出层

"""
import tensorflow as tf
#调用sklearn中的数据(手写字体识别)
from sklearn.datasets import load_digits
import numpy as np
from sklearn.preprocessing import MinMaxScaler

digits = load_digits()
X_data = digits.data.astype(np.float32)
Y_data = digits.target.astype(np.float32).reshape(-1,1)
#X_data.shape = (1797,64);Y_data.shape = (1797,1)
#最小最大值标准化
#公式:X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0)) ;
#     X_scaler = X_std/ (max - min) + min;
scaler = MinMaxScaler()
X_data = scaler.fit_transform(X_data)

from sklearn.preprocessing import OneHotEncoder
#对Y值(0,9)进行one-hot编码(eg:0:1000000000)
Y = OneHotEncoder().fit_transform(Y_data).todense()
#转换为图片格式(batch,height,width,channels)
X = X_data.reshape(-1,8,8,1)  #-1:1797
batch_size = 8    #使用MBGD算法,设定batch_size为 8

def generatebatch(X,Y,n_examples, batch_size):
    for batch_i in range(n_examples // batch_size):
        start = batch_i*batch_size
        end = start + batch_size
        batch_xs = X[start:end]
        batch_ys = Y[start:end]
        yield batch_xs, batch_ys # 生成每一个batch


tf.reset_default_graph()

#输入层

#[None,8,8,1]:对图片的个数不确定故None,前面生成图片是8*8,深度为1;
tf_X = tf.placeholder(tf.float32,[None,8,8,1]) #placeholder 为占位符,可以理解为形参;
tf_Y = tf.placeholder(tf.float32,[None,10])  #one-hot编码为10位数

#卷基层+激活层
#权重,也是设置卷积核;height:3,weight:3,depth:1,卷积核个数:10(一个卷积核映射出一个值)
conv_filter_w1 = tf.Variable(tf.random_normal([3,3,1,10])) #Variable:变量;random_normal:符合正态分布取值
conv_filter_b1 = tf.Variable(tf.random_normal([10])) #偏移值,ont-hot输出10个值,所以【10】
#strides=[batch,in_height,in_width,in_channel];batch 和 in_channels 要求一定为1,即只能在一个样本的一个通道上的特征图上进行移动
#padding = 'SAME':“SAME”表示采用填充的方式,简单地理解为以0填充边缘;“VALID”表示采用不填充的方式,多余地进行丢弃;
relu_feature_maps1 = tf.nn.relu(tf.nn.conv2d(tf_X,conv_filter_w1,strides = [1,1,1,1],padding = 'SAME') + conv_filter_b1) 

#池化层
#ksize:池化窗口(类似卷积核的设置)一般为[1,height,width,1]
max_pool1 = tf.nn.max_pool(relu_feature_maps1,ksize = [1,3,3,1],strides = [1,2,2,1],padding = 'SAME')

#卷基层
#[height,weight,depth,channel]:上一个池化层输出10个值(one-hot)故为10,形成5个卷积核,最后生成5个值输出
conv_filter_w2 = tf.Variable(tf.random_normal([3,3,10,5])) 
conv_filter_b2 = tf.Variable(tf.random_normal([5]))
#'SAME':采用填充的方式,简单地理解为以0填充边缘,当stride为1时,输入和输出的维度相同;“VALID”表示采用不填充的方式,多余地进行丢弃。
conv_out2 = tf.nn.conv2d(relu_feature_maps1,conv_filter_w2,strides=[1,2,2,1],padding = 'SAME')+conv_filter_b2
 
#BN归一化层——激活层
batch_mean,batch_var = tf.nn.moments(conv_out2,[0,1,2],keep_dims = True)
shift = tf.Variable(tf.zeros([5])) #初始化 0 ,卷积核5个,故数量为5
scale = tf.Variable(tf.ones([5])) #初始化 1
epsilon = 0.001
BN_out = tf.nn.batch_normalization(conv_out2, batch_mean,batch_var,shift,scale,epsilon)
relu_BN_maps2 = tf.nn.relu(BN_out)
                      
#池化层
max_pool2 = tf.nn.max_pool(relu_BN_maps2,ksize = [1,3,3,1],strides = [1,2,2,1],padding = 'SAME')
print (max_pool2) #结果:Tensor('MaxPool_1:0',shape = (?,2,2,5),dtype = float32)
#将特征图进行展开
max_pool2_flat = tf.reshape(max_pool2,[-1,2*2*5])   #max_pool2的shape是【?,2,2,5】所以转换成列为:2*2*5,行数:1797

#全连接
#全连接试讲各个部分的特征进行;链接,减少特征的损失
fc_w1 = tf.Variable(tf.random_normal([2*2*5,50]))
fc_b1 = tf.Variable(tf.random_normal([50]))
fc_out1 = tf.nn.relu(tf.matmul(max_pool2_flat,fc_w1)+fc_b1)

#输出层
out_w1 = tf.Variable(tf.random_normal([50,10]))
out_b1 = tf.Variable(tf.random_normal([10]))
pred = tf.nn.softmax(tf.matmul(fc_out1,out_w1)+out_b1) #softmax与relu一样属于激活函数
#tf.clip_by_value(A, min, max):输入一个张量A,把A中的每一个元素的值都压缩在min和max之间。小于min的让它等于min,大于max的元素的值等于max
loss = -tf.reduce_mean(tf_Y * tf.log(tf.clip_by_value(pred,1e-11,1.0)))
train_step = tf.train.AdamOptimizer(1e-3).minimize(loss)  #AdamOptimizer:基于Adam算法的优化器
#tf.argmax就是返回最大的那个数值所在的下标。axis -0:所有的数组按照数组相同位置进行比较,返回值最大的下标;axis = 1:在每个数组内的数比较,返回最大值的下标;
'''
axis =0                            axis = 1
test[0] = array([1, 2, 3])         test[0] = array([1, 2, 3])  #2
test[1] = array([2, 3, 4])         test[1] = array([2, 3, 4])  #2
test[2] = array([5, 4, 3])         test[2] = array([5, 4, 3])  #0
test[3] = array([8, 7, 2])         test[3] = array([8, 7, 2])  #0

# output   :    [3, 3, 1]
'''
y_pred = tf.arg_max(pred,1) #1:axis
bool_pred = tf.equal(tf.arg_max(tf_Y,1),y_pred)
#准确率
accuracy = tf.reduce_mean(tf.cast(bool_pred,tf.float32))  #cast(bool_pred,tf.flaot32):将bool_pred转换成float格式
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for epoch in range(1000): #迭代1000个周期
        for batch_xs,batch_ys in generatebatch(X,Y,Y.shape[0],batch_size):   # 每个周期进行MBGD
            sess.run(train_step,feed_dict = {tf_X:batch_xs,tf_Y:batch_ys})
        if (epoch %100 == 0):
            res = sess.run(accuracy,feed_dict={tf_X:X,tf_Y:Y})
            print (epoch,res)
    res_ypred = y_pred.eval(feed_dict={tf_X:X,tf_Y:Y}).flatten()  # 只能预测一批样本,不能预测一个样本
    print (res_ypred)
    
 '''--------------------------------结果------------------------------------'''   
 '''
 0 0.269894
100 0.956038
200 0.994435
300 0.997774
400 0.997218
500 0.998331
600 0.998331
700 0.998887
800 0.999444
900 0.998331
[0 1 2 ..., 8 9 8]
'''




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值