TensorFlow的基本操作
- 向前传播(张量)–实战
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import datasets
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
(x, y), (test_x, test_y) = datasets.mnist.load_data()
x = tf.convert_to_tensor(x, dtype=tf.float32) / 255.
y = tf.convert_to_tensor(y, dtype=tf.int32)
print(x.shape, tf.reduce_max(x), tf.reduce_min(x))
print(y.shape, tf.reduce_max(y), tf.reduce_min(y))
train_db = tf.data.Dataset.from_tensor_slices((x, y)).batch(128) // 分batch
train_iter = iter(train_db)
sample = next(train_iter)
print(sample[0].shape)
print(sample[1].shape)
# [b, 784] -> [b, 256] -> [b, 10]
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]))
lr = 1e-3
for epoch in range(10):
# h1 = x@w1 + b1
for step, (x, y) in enumerate(train_db):
x = tf.reshape(x, [-1, 28*28])
with tf.GradientTape() as tape:
# 784->256
h1 = x@w1 + b1
h1 = tf.nn.relu(h1)
# 256->128
h2 = h1@w2 + b2
h2 = tf.nn.relu(h2)
# 128->10
out = h2@w3 + b3
# compute loss
# out = [b, 10]
# y[b] -> y[b,10]
y_onehot = tf.one_hot(y, depth=10)
loss = tf.square(y_onehot - out)
loss = tf.reduce_mean(loss) # 这个是求均值
grads = tape.gradient(loss, [w1, b1, w2, b2, w3, b3])
# w1 = w1 - lr*w1_grad
w1.assign_sub(lr * grads[0])
b1.assign_sub(lr * grads[1])
w2.assign_sub(lr * grads[2])
b2.assign_sub(lr * grads[3])
w3.assign_sub(lr * grads[4])
b3.assign_sub(lr * grads[5])
if step % 100 == 0:
print("step:", step, "loss = ", loss)
-
Tensor拼接
# tf.concat([tensor1, tensor2], axis=x) a = tf.fill([2,3,4], 5) b = tf.fill([3,3,4], 6) c = tf.concat([a, b], axis=0) # c.shape=[5,3,4] # tf.stack([tensor1,tensor2],axis=x) 与tf.concat的区别在于,stack会创建新的维度 d = tf.fill([2,3,4], 5) e = tf.fill([2,3,4], 6) f = tf.stack([d, e], axis=0) # f.shape = [2,2,3,4] dd, ee = tf.unstack(f,axis=0) # 拆分,拆分之后dd和ee与d,e一样 # tf.split(tensor, axis=x, num_or_size_splits=xxx) xxx为数字,就是均分,为列表就是分割大小 g = tf.fill([4,8,10], 10) h = tf.split(g,axis=0,num_or_size_splits=2) # h包含两个[2,8,10] i = tf.split(g,axis=0,num_or_size_splits=[1,1,2]) # i包含三个
-
数据统计
# 向量的范数 # tf.norm(tensor, ord = x, axis = xx) ->x=1(一范数) x=2(二范数) # 一范数:所有元素绝对值之和 # 二范数:所有元素平方和开根号 # 默认是二范数 a = tf.ones([2,2]) tf.norm(a) # 为2 tf.norm(a, ord = 1, axis = 0) # [2., 2.] # tf.reduce_min/max/mean(tensor, axis=xxx) # 不给定axis,默认全部 # tf.argmax(tensor, axis=xxx) 不指定选第一个 # tf.argmin(tensor, axis=xxx) b = tf.random.normal([4,10]) d = tf.argmax(b) # d.shape = [1, 10] # tf.equal(tensor1, tensor2) ->return [True, False, ...] e = tf.range(5) # [0,1,2,3,4] f = tf.constant([1,2,3,4,5]) g = tf.equal(e.f) # g = [False, False, False, False, False] # tf.unique(a) 去重
-
张量排序
# tf.sort(tensor, direction='DESCENDING') 按元素降序 # tf.argsort(tensor, direction = 'DESCENDING') 降序的索引 # tf.math.top_k(tensor, k) ->返回一个tuple # tuple.indices ->返回top k的索引 # tuple.values ->返回top k的数值 a = tf.constant([[1, 2, 3], [4, 5, 6], [4, 5, 7], [7, 8, 9]]) b = tf.math.top_k(a, 2) print(b.indices) print(b.values)
-
填充与复制
# 扩张tf.pad(tensor, [[上下],[左右]]) a = tf.reshape(tf.range(9), [3,3]) b = tf.pad(a, [[1,0], [0,0]]) # 上面加一行 # tf.tile(tensor, [xxx]) xxx:代表哪个维度扩大几倍 c = tf.constant([[0,1,2], [3,4,5], [6,7,8]]) d = tf.tile(c, [1,2]) # d.shape=[3,6] d -> [[0, 1, 2, 0, 1, 2], [3, 4, 5, 3, 4, 5], [6, 7, 8, 6, 7, 8]]
-
张量限幅
# tf.maximum(tensor, xx) : 所有都大于xx # tf,minimum(tensor, xx) : 所有都小于xx # tf.clip_by_value(tensor, xx, xxx) : 所有都在xx - xxx之间 # tf.nn.relu(a) : relu函数其实就是使用tf.maximum(tensor, 0) # tf.clip_by_norm(tensor, 15) : 把tensor的二范数限制在15左右,做一个放缩。只改变模,不改变方向 # new_grads, total_norm = tf.clip_by_global_norm(grads, xxx) 保持整体缩放方向不变,缩小到xxx
-
高阶操作
# tf.where(tensor) : tensor只能是一个bool类型的。会将True位置的坐标返回 # tf.where(tensor, A, B) : tensor只能是一个bool类型的。如果为True,在A上采样,如果为False在B上采样 # tf.scatter_nd(indices, updates, shape) : 更新操作。但是只能在底板上更新,也就是初始化为0。根绝indices的坐标指示,把updates的数据跟新到shape这个底板上面去。 # y = tf.linspace(start, end, nums) : 分割 # x = tf.linspace(start, end, nums) # point_x, point_y = tf.meshgrid(x, y) : 切分表格