4.9数学运算
4.9.1 加、减、乘、除运算
加减乘除分别通过tf.add,tf.subtract, tf.multiply, tf.divide函数来实现,一般推荐使用+-*/来代替。
整除和余除也是常见的运算之一,通过//和%来实现。
import tensorflow as tf
a = tf.range(5)
b = tf.constant(2)
#整除运算
print(a//b)
# 余除运算
print(a%b)
4.9.2 乘方运算
通过tf.pow(x,a),可以方便的计算x的a次方,也可以通过**实现x**a,常见的平方和平方根运算,使用tf.square(x),tf.sqrt(x)
import tensorflow as tf
x = tf.range(4)
# 实现乘方
print(tf.pow(x,3))
print(x**2)
# 通过使用1/a的形式能够实现开根号运算,注意需要使用tf的数字格式
x = tf.constant([1.,4.,9.])
# 平方根
print(x**(0.5))
# 常见的平方和平方根运算,使用tf.square(x),tf.sqrt(x)
x = tf.range(5)
x = tf.cast(x, dtype=tf.float32)
print(tf.square(x))
print(tf.sqrt(x))
4.9.3 指数和对数运算
1)通过tf.pow(a,x)或者**能够实现,
2)对于自然指数可以通过tf.exp(x)来实现,
3)在对数可以通过tf.math.log(x),其中tf.math.log代表着
4)根据,可以间接的通过tf.math.log(x),计算
import tensorflow as tf
x = tf.constant([1.,2.,3.])
# 1)指数运算
print(2**x)
# 2)自然指数运算
print(tf.exp(3.))
# 3)对数运算
x = tf.exp(3.)
print(tf.math.log(x))
# 4)换底公式
x = tf.constant([1.,2.])
x = 10**x
print(tf.math.log(x)/tf.math.log(10.))
实现起来相对麻烦,希望以后会推出任意底数的log函数吧。
4.9.4 矩阵相乘运算
矩阵相乘可以使用@符号,也能使用tf.matmul(a,b)来实现。需要了解一下当张量a和张量b的维度都大于2的时候,tensorflow会根据最后的两个维度进行矩阵相乘,前面所有的维度都是为batch维度。
矩阵能够相乘的条件是:a的倒数第一个维度的长度必须和b的倒数第二个维度的长度相等
import tensorflow as tf
a = tf.random.normal([4,3,28,32])
b = tf.random.normal([4,3,32,2])
print((a@b).shape)
# 同样的,也支持自动Broadcasting
a = tf.random.normal([4,28,32])
b = tf.random.normal([4,32,16])
print((a@b).shape)
4.10 前向传播实战
简单总结一下前面的知识点,完成一个三成的神经网络
out = 𝑅𝑒𝐿𝑈{𝑅𝑒𝐿𝑈{𝑅𝑒𝐿𝑈[𝑿@𝑾1 + 𝒃1]@𝑾2 + 𝒃2}@𝑾3 + 𝒃3 }
使用的数据集市MNIST手写数字图片集,输入节点784,第一层输出是256, 第二层输出是128,第三层输出是10,也就是当前样本属于10个类别的概率。
# 每层的张量都需要被优化,故使用 Variable 类型,并使用截断的正太分布初始化权值张量
# 偏置向量初始化为 0 即可
# 第一层的参数
w1 = tf.Variable(tf.random.truncated_normal([784,256], stddev=0.1))
b1 = tf.Variable(tf.zeros([256]))
# 第一层的参数
w2 = tf.Variable(tf.random.truncated_normal([256,128], stddev=0.1))
b2 = tf.Variable(tf.zeros([128]))
# 第一层的参数
w3 = tf.Variable(tf.random.truncated_normal([128,10], stddev=0.1))
b3 = tf.Variable(tf.zeros([10]))
首先将shape为[b,28,28]的输入张量调整为[b, 784]
x = tf.reshape(x, [-1, 28*28])\
# 完成第一层计算
# 第一层计算,[b, 784]@[784, 256] + [256] => [b, 256] + [256] => [b, 256] + [b, 256]
h1 = x @ w1 + tf.broadcast_to(b1, [x.shape[0], 256])
h1 = tf.nn.relu(h1)
# 第二层计算,[b, 256] => [b, 128]
h2 = h1 @ w2 + b2
h2 = tf.nn.relu(h2)
# 输出层计算,[b, 128] => [b, 10]
h3 = h2 @ w3 + b3
# 将真实的张量y转变为one-hot编码
# 计算网络输出与标签之间的均方差,mse = mean(sum(y-out)^2)
loss = tf.square(y_onehot-out)
loss = tf.reduce_mean(loss)
# 通过 tape.gradient()函数更新网络参数
最终展示效果
具体代码先放着,到后面统一整理。