一、Tensorflow使用
1、Tensorflow简介
TensorFlow是一个软件库,封装了建构神经网络的API,类似于MatLab的神经网络工具箱,是Google于2015年推出的深度学习框架(目前最流行的深度学习框架)

计算图

①计算图(Graph),如上图,表述了一个计算任务(也可以说是训练任务)。
②张量(Tensor),是对矢量和矩阵向潜在的更高维度的泛化。TensorFlow在内部将张量表示为基本数据类型的 n 维数组。
例:线性代数中用秩来表示矩阵的维度,同样在TensorFlow中也可以用秩来表示张量的维度

0阶张量(标量Scalar) 5
1阶张量(向量Vector) [1,2]
2阶张量(矩阵Matrix)[[1,2],[2,3]]
3阶张量 [[ [1,2,3],[4,5,6],[7,8,9]] [[1,3,5],[2,4,6],[5,7,9]] [[7,8,9],[2,4,6],[1,3,5]]]
③节点(Operation),是定义数据操作方法,上图中,流过节点的张量会被进行加减乘除取模运算。
④会话(Session),将计算图的节点(Op)分发到诸如CPU或GPU之类的设备上, 同时提供执行Op的方法。会话就是与后端连接高效C++库来进行计算,通俗理解是前期构建好计算图,启动会话就是按下开始按键,让数据流向每个节点。

现实世界中的数据张量
1)向量数据
2D张量,形状为 (samples, features)。
2)时间序列数据或序列数据
3D张量,形状为 (samples, timesteps, features)。
3)图像
4D张量,形状为 (samples, height, width, channels) 或 (samples, channels, height, width)。
4)视频
5D张量,形状为 (samples, frames, height, width, channels) 或 (samples, frames, channels, height, width)。

2、张量使用 常量与变量
张量形式有变量(tf.Variable),常量(tf.constant),占位符(tf.placeholder),稀疏张量(tf.SparseTensor),除了变量(tf.Variable),其它张量的值是不能改变的。变量是用在神经网络(NN)的权重和偏值的修正上,上图中每训练一次都可能需要更改网络权重W和偏值

import tensorflow as tf#导入tensorflow

a=tf.constant('Hello World!')#常数张量
b=tf.zeros([1,3,3])#生成3阶0张量
c=tf.ones([1,3,3])#生成3阶单位1张量
d=tf.fill([1,3,3],2.0)#生成3阶张量,并用2.0填充
print(a)
print(b)
print(c)
print(d)

张量属性:rank阶,也就是张量的维度,也是上表中形状示例中的‘[’的个数
也是张量的轴的数量
可以用ndim属性来查看一个Numpy张量的轴的个数
例:

import numpy as np 
x = np.array(12) 
y = np.array([1, 2, 3, 4, 5]) 
print(x.ndim) 
print(y.ndim)

shape是形状,他是指明每一层有多少个元素。比如[2,3,4]是指第一层2个元素,第二层3个元素,第三层4个元素,通过这个我们就可以知道这个张量一共有2 × 3 × 4=24 个元素。
整数元组,表示张量沿每个轴的维度大小(元素个数)。例如,矩阵的形状可以为(3,5),3D张量的形状可以为(3,3,5)。向量的形状只包含一个元素,比如(5,),而标量的形状为空,即()。

import tensorflow as tf
# 定义了一个张量,有6个元素,设置他的形状是[2, 3]
a = tf.constant([1, 2, 3, 4, 5, 6], shape=[2,3])
with tf.Session() as session:
print(session.run(a))

type元素的类型

会话 Session 执行计算图当中的运算,计算图的计算和执行必须放在session当中
使用print函数打印张量时,返回了张量的类型和形状,并未给出具体的数据
启动会话使Tensor流过节点,才会有输出。这里使用默认的计算图(默认存在一张计算图),使用Session.run函数启动会话,得到输出结果,我们这边并没有让Tensor作计算,只是让Tensor流过节点。
with tf.Session() as sess:
print(sess.run(y))
或者sess=tf.Session()

例:

import tensorflow as tf#导入tensorflow

a=tf.constant('Hello tensorflow!')#常数张量
b=tf.zeros([1,3,3])#生成3阶0张量
c=tf.ones([1,3,3])#生成3阶单位1张量
d=tf.fill([1,3,3],2.0)#生成3阶张量,并用2.0填充
print(a)
print(b)
print(c)
print(d)
sess=tf.Session()
print(sess.run(a))
print(sess.run(b))
print(sess.run(c))
print(sess.run(d))

变量与占位符
变量是张量值可变的量,主要用来调整这些变量的值来生成网络模型。例如设置某神经网络中的参数(权重和偏值),另外需要初始化变量才能使用变量:
例:

w=tf.Variable(tf.zeros([784,10])
b=tf.Variable(tf.zeros[10])
init_op=tf.global_variables_initializer()

占位符通常作为输入输出的声明,提前占位,例如某神经网络中输入数据,每训练完一组数据,需读取磁盘其它批次数据到占位符这个坑等待数据流向节点计算,更新操作用feed_dict传入数据

随机给予初始值
random_normal:生成正太分布随机数
truncated_normal:生成去掉过大偏离点的正太分布随机数
random_uniform:生成均匀分布随机数

tf.zeros生成全0的数组tf.zeros([3,2], int32)[[0,0], [0,0], [0,0]]
tf.ones生成全1的数组tf.ones([3,2], int32)[[1,1], [1,1], [1,1]]
tf.fill全部定值的数组tf.fill([3,2], 6)[[6,6], [6,6], [6,6]]
tf.constant直接进行赋值tf.constant([3,2,1])

例:

import tensorflow as tf

W = tf.Variable(tf.random_normal([2, 3], stddev=2, mean=0,  seed=1))
              #正态分布         #2*3矩阵 #标准差为2 #均值为0 #随机种子
init = tf.global_variables_initializer()

with tf.Session() as sess: 
sess.run(init)
    for _ in range(2):
        print(sess.run(W))

获取MNIST数据集 测试数据集test 训练数据集train
训练集(training set)由来自250个不同人手写的数字构成,其中50%是高中学生,50%来自人口普查局(the Census Bureau)的工作人员,主要用于训练工作

mnist = input_data.read_data_sets('data',one_hot=True)

if not os.path.exists('train'):
    os.mkdir('train')
if not os.path.exists('test'):
    os.mkdir('test')

for (idx, img) in enumerate(mnist.train.images):
    img_arr = np.reshape(img, [28,28])
    misc.imsave('train/train_' + str(idx) + '.png',img_arr)

for (idx, img) in enumerate(mnist.test.images):
    img_arr = np.reshape(img, [28,28])
misc.imsave('test/test_' + str(idx) + '.png',img_arr)

二、利用tensorflow搭建两层全连接神经网络
1、激活函数的使用 sigmoid,ReLu,tansh,softsign,ELU等
例:

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers,Sequential

tf.keras.layers.Dense(512,activation=tf.nn.relu)#构建一层由512个神经元,激活函数为relu神经网络
tf.keras.layers.Dense(256,activation=tf.nn.sigmoid)#构建一层由256个神经元,激活函数为sigmoid神经网络
tf.keras.layers.Dense(128,activation=tf.nn.tanh)#构建一层由128个神经元,激活函数为tanh神经网络

2、损失函数的使用 提供非线性,这是神经网络可以逼近任意函数的关键
交叉熵(cross-entropy)、平方损失函数、均方误差函数等
#y_为样本目标结果,y为样本训练结果

loss = tf.nn.softmax_cross_entropy_with_logits(y, y_)
loss = tf.reduce_mean(tf.square(y_ - y))

3、学习率Learning_rate 每次参数更新的幅度
学习率:调整参数的幅度
使神经网络模型在训练数据上的损值函数最小
使得正确率不断的提高
损值函数(loss):预测值(y)和已知答案(y_)的差距

学习率 大 学习速度快 使用在刚开始训练时 副作用1.易损失值爆炸2.易震荡
学习率 小 学习速度慢 使用在一定轮数过后 副作用1.易过拟合2.收敛速度慢

理想情况下曲线应该是滑梯式下降[绿线]
曲线初始时上扬[红线]:Solution:初始学习率过大导致振荡,应减小学习率,并从头开始训练 。
曲线初始时强势下降没多久归于水平[紫线]:Solution:后期学习率过大导致无法拟合,应减小学习率,并重新训练后几轮 。
曲线全程缓慢[黄线]:Solution:初始学习率过小导致收敛慢,应增大学习率,并从头开始训练
例:

import tensorflow as tf

learning_rate = 0.2
w = tf.Variable(tf.constant(5, dtype = tf.float32))
loss = tf.square(w + 1)
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)

with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    for i in range(101):
        sess.run(train_step)
        w_val = sess.run(w)
        loss_val = sess.run(loss)
        if i % 10 == 0:
            print('After %s steps: w is %f, loss is %f' % (i, w_val, loss_val))

4、梯度下降的使用

#0.01表示学习率η,cross_entropy是前面定义的损失函数:

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

前向传播:计算过程,神经网络的训练过程
反向传播:不断的调整训练模型的参数
在循环中完成:指训练一轮
1、前向传播:从第一层到输出层,逐层计算网络输出;
2、计算代价函数
3、反向传播:从输出层到第一层,逐层计算各层的梯度
4、更新参数:

搭建步骤
1、 下载数据集
2、 定义x输入张量和y目标张量
3、 定义第一层权重w1张量、b1偏置、连接神经元、a激活函数
4、 定义第二层权重w2张量和b2偏置、连接神经元、y_激活函数
5、 定义损失函数和梯度下降法
6、 初始化张量
7、 训练

例:
#导入需要用到的库

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

#下载MNIST手写数字集,将手写数字集28*28图像变成1维的784个数据,
mnist = input_data.read_data_sets('MNIST_data/', one_hot=True)

#定义占位符,MNIST手写数字集有60000张手写数字图片作训练样本,有10000张手写数字图片                                                       
#作测试样本
#张量x的None表示MNIST手写数字集中的图片编号,784表示降维后图片中每一个像素点
#张量y的None表示MNIST手写数字集中的图片编号,10表示0~9共10个数字概率,y为样本的目                  
#标结果(也称标签,导入手写数字集已经捆绑了对应的数字)
x = tf.placeholder(tf.float32, [None,784])
y = tf.placeholder(tf.float32, [None,10])
 
#定义权重张量w1,偏置张量b1,784个输入层神经元连接1024个隐藏层神经元
#定义隐藏层输出张量a,使用tf.nn.relu激活函数,tf.matmul(x,w1)+b1表示神经元的连接
w1 = tf.Variable(tf.truncated_normal([784,1024]), dtype = tf.float32)
b1 = tf.Variable(tf.zeros([1,1024]), dtype = tf.float32)
a = tf.nn.relu(tf.matmul(x,w1) + b1) 
 
#定义权重张量w2,偏置张量b2,1024个隐藏层神经元连接10个输出层神经元
#定义输出层张量y_,使用tf.nn.softmax激活函数,tf.matmul(a,w2)+b2表示神经元的连接
w2 = tf.Variable(tf.ones([1024,10]))
b2 = tf.Variable(tf.zeros([1,10]))
y_= tf.nn.softmax(tf.matmul(a,w2) + b2) 

#定义损失函数和梯度下降法
loss = tf.reduce_mean(-tf.reduce_sum(y*tf.log(y_), axis = 1)) 
train_step = tf.train.AdamOptimizer(0.0001).minimize(loss)

#初始化特殊张量
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

#每训练一个批次样本数据后后获得识别正确率
correct_prediction = tf.equal(tf.argmax(y_, axis = 1),tf.argmax(y, axis = 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

#定义好上面所有的运行方式后,使用sess.run启动tensorflow
#在1000轮训练中,mnist.train.next_batch(100)表示每轮训练取出100张样本图片,用feed_dict   
#方法把100张样本图片扔进占位符x,y进行训练,train_step参数是上面定义好的网络权重和偏  
#置的调整方法
#每训练100轮就检验一次MNIST手写数据集中的10000张测试图片
for i in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict = {x:batch_xs,y:batch_ys})
    if i % 100 == 0:
        print(sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels}))

加入推理识别
通过PS生成的0~9共10个数字的28*28像素图片进行测

from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf  
#导入图片处理相关库
from PIL import Image
import numpy as np
from itertools import chain 

#读取0~9其中一张图片进行测试,可以尝试修改数字进行其它图片测试
image_tem = Image.open('./test_7.png')
image_array = np.array(image_tem)
image_array=np.asarray(image_array,dtype="float32") 
image_array = list(chain.from_iterable(image_array))
image_array = [image_array]

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

x = tf.placeholder(tf.float32,[None,784])
y = tf.placeholder(tf.float32, [None,10])
 
w1 = tf.Variable(tf.truncated_normal([784,1024]),dtype=tf.float32)
b1 = tf.Variable(tf.zeros([1,1024]),dtype=tf.float32)
a = tf.nn.relu(tf.matmul(x,w1) + b1) 

w2 = tf.Variable(tf.ones([1024,10]))
b2 = tf.Variable(tf.zeros([1,10]))
y_= tf.nn.softmax(tf.matmul(a,w2) + b2) 

#将图片输入到神经网络中去
b = tf.nn.relu(tf.matmul(image_array,w1)+b1)
y_image = tf.nn.softmax(tf.matmul(b,w2)+b2)
 
loss= tf.reduce_mean(-tf.reduce_sum(y*tf.log(y_),axis=1))
train_step = tf.train.AdamOptimizer(0.0001).minimize(loss)
 
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
correct_prediction = tf.equal(tf.argmax(y_,axis=1), tf.argmax(y,axis=1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

for i in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys})

#待神经网络权重偏置调整完成后,直接运行待测试的图片
print(sess.run(y_image))

自己尝试
将提供的mnist做完前向传播、后向传播训练、推理验证