TensorFlow2.0 的张量类型有:
在TensorFlow2.0中一般把标量、向量、矩阵也统称为张量,不做区分
TensorFlow2.0中创建数值必须用其规定方法,不能用Python语言的标准变量创建方式。
比如
a = tf.constant(1.2,dtype=tf.float32) #创建一个精度为32bit、值为1.2的标量
此外TF2也支持字符串、布尔类型的数据.
可以利用tf.cast函数进行数据类型转换
tf.Variable 用以创建待优化张量,也就是所谓的变量
在卷积神经网络中,卷积核初始化可以通过创建已知分布的张量来进行,下面是两种常见的分布
利用tf.random.normal([n,m],mean=1,stddev=2)创建一个二维矩阵,其中的数值从均值为1,标准差为2的正态分布中随机取出
以 a = tf.random.normal([2,3],mean=1,stddev=2)为例
a的值为
[0.8452484, 2.7406826, 1.1655676]], dtype=float32)>
其中id为内部索引对象的编号
利用tf.random.uniform([n,m],minval=a,maxval=b,dtype=tf.int32)可以创建二维矩阵,其中的元素为区间[a,b]内的整数
在循环计算或者索引张量时需要创建一段连续的整型序列(类似于Python中 for i in range(100) 循环中的range)可以通过tf.range函数实现,函数原型
tf.range(a,b,delta=k) [a,b)步长为2的序列
张量的存储和视图概念,比如shape为[2,4,4,3]的张量A,可以理解为两张4行4列,每个位置有RGB3个通道的数据的图像。TF在进行矩阵运算的时候会自动调用Broadcasting使得矩阵的维数对应。这在神经网络中非常常见,调用tf.reshape()函数也能改变张量的维数。
例如
#[1,28,28]->[1,28*28] 三维降二维
x = tf.zeros([1,28,28])
x = tf.reshape(x,[1,28*28])
TF重载了±*/运算符,所以可以不利用函数直接使用运算符运算,乘方也与Python一致,指数用tf.exp(),对数tf.math.log()只能计算以10为底的函数值,可以配合换底公式使用改变底数
而TensorFlow 2.0相比于1.X改进还是非常多的,很多“反人类”的操作都被移除了。
比如:not sessions 下面是实现 计算3*5的TF代码对比
#TF1.x
a = tf.constant(5)
b = tf.constant(3)
c = a*b
with tf.Session() as sess:
print(sess.run(c))
#TF2
a = tf.constant(5)
b = tf.constant(3)
c = a*b
print(c)
可以看出TensorFlow2.0更加贴近Python
此外TensorFlow 2.0推荐使用Keras构建和训练深度学习模型,它更加方便使用,模块化易组合的特点也更易于扩展
了解了张量的常用操作之后,最后用一个完整的张量方式实现的分类网络模型收尾。
TF中的keras.datasets模块提供了常用的经典数据集的自动下载、管理、加载并提供了tf.data.Dataset数据集对象,方便实现多线程,预处理和批训练等常用功能。这里以MNIST_data为例,MNIST_data的下载问题先到http://yann.lecun.com/exdb/mnist/下载mnist.npz然后解压放在python\Lib\site-packages\tensorflow_core\python\keras\datasets目录下再修改mnist.py中def load_data函数中path的路径并将下载的相应代码去掉即可
def load_data(path='D:\\python\\Lib\\site-packages\\tensorflow_core\\python\\keras\\datasets\\mnist.npz'):##主要是这里
"""Loads the MNIST dataset.
Arguments:
path: path where to cache the dataset locally
(relative to ~/.keras/datasets).
Returns:
Tuple of Numpy arrays: `(x_train, y_train), (x_test, y_test)`.
License:
Yann LeCun and Corinna Cortes hold the copyright of MNIST dataset,
which is a derivative work from original NIST datasets.
MNIST dataset is made available under the terms of the
[Creative Commons Attribution-Share Alike 3.0 license.](
https://creativecommons.org/licenses/by-sa/3.0/)
origin_folder = 'https://storage.googleapis.com/tensorflow/tf-keras-datasets/'
path = get_file(
path,
origin=origin_folder + 'mnist.npz',
file_hash=
'731c5ac602752760c8e48fbffcf8c3b850d9dc2a2aedcf2cc48468fc17b673d1')
""" #防止其尝试下载
with np.load(path) as f:
x_train, y_train = f['x_train'], f['y_train']
x_test, y_test = f['x_test'], f['y_test']
return (x_train, y_train), (x_test, y_test)
张量分类网络相应代码
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import datasets
def preprocess(x,y):
#归一化
x = tf.cast(x, dtype=tf.float32) / 255.
x = tf.reshape(x, [-1,28*28])#变成二维从而能够进入网络层
y = tf.cast(y, dtype=tf.int32)
y = tf.one_hot(y, depth=10)#变成one-hot编码
return x,y
(x, y),(x_test, y_test) = datasets.mnist.load_data()# x为图像,shape为[b,28,28],y为标签,shape为[b]
train_db = tf.data.Dataset.from_tensor_slices((x, y))#将训练图片和标签转换为Dataset对象
train_db = train_db.shuffle(1000)#随机打乱
train_db = train_db.batch(512)#批训练,利用显卡并行计算能力缩短训练时间
train_db = train_db.map(preprocess)#预处理函数为preprocess,map函数可以自动传入参数
train_db = train_db.repeat(20)
test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_db = test_db.shuffle(1000).batch(512).map(preprocess)
x,y = next(iter(train_db))
def main():
lr = 4e-2
accs,losses = [], []
w1, b1 = tf.Variable(tf.random.normal([784,256], stddev=0.1)),tf.Variable(tf.zeros([256]))
w2, b2 = tf.Variable(tf.random.normal([256,128], stddev=0.1)),tf.Variable(tf.zeros([128]))
w3, b3 = tf.Variable(tf.random.normal([128,10], stddev=0.1)),tf.Variable(tf.zeros([10]))
for step,(x,y) in enumerate(train_db):#迭代数据集对象
x = tf.reshape(x,(-1, 784))
with tf.GradientTape() as tape:
h1 = x @ w1 + b1
h1 = tf.nn.relu(h1)
h2 = h1 @ w2 + b2
h2 = tf.nn.relu(h2)
out = h2 @ w3 + b3
loss = tf.square(y - out)
loss = tf.reduce_mean(loss)
grads = tape.gradient(loss, [w1,b1,w2,b2,w3,b3])
for p,g in zip([w1,b1,w2,b2,w3,b3],grads):
p.assign_sub(lr * g)
if step%80 == 0:
print(step,"loss:",float(loss))#每100次输出一次模型的性能
losses.append(float(loss))
total,total_correct = 0.,0
for x, y in test_db:
h1 = x @ w1 + b1
h1 = tf.nn.relu(h1)
h2 = h1 @ w2 + b2
h2 = tf.nn.relu(h2)
out = h2 @ w3 + b3
pred = tf.argmax(out, axis=1)
y = tf.argmax(y, axis=1)
correct = tf.equal(pred, y)
total_correct += tf.reduce_sum(tf.cast(correct, dtype=tf.int32)).numpy()
total += x.shape[0]
print(total_correct,total)
print(step, 'Evaluate Acc:',total_correct/total)
accs.append(total_correct/total)
if __name__ == '__main__':
main()
最后的准确率只能达到 86.98%,均方误差为0.034,对于一个简单的模型来说,这个结果已经不错了。