# tensorflow：tensorflow进阶

2020/10/20 11:38

## 一.合并与分割

import  matplotlib
from    matplotlib import pyplot as plt
# Default parameters for plots
matplotlib.rcParams['font.size'] = 20
matplotlib.rcParams['figure.titlesize'] = 20
matplotlib.rcParams['figure.figsize'] = [9, 7]
matplotlib.rcParams['font.family'] = ['STKaiTi']
matplotlib.rcParams['axes.unicode_minus']=False
import numpy as np
import  tensorflow as tf
from    tensorflow import keras
from    tensorflow.keras import datasets, layers, optimizers
import  os
from mpl_toolkits.mplot3d import Axes3D


### 1.1 合并

a = tf.random.normal([2,4]) # 模拟成绩册 A
b = tf.random.normal([2,4]) # 模拟成绩册 B
tf.concat([a,b],axis=0)

<tf.Tensor: shape=(4, 4), dtype=float32, numpy=
array([[ 0.16198424, -0.7170487 , -0.20940438, -0.46842927],
[ 0.48012358,  0.82777774, -0.37541786, -0.6629169 ],
[-0.15179256, -0.41726607, -1.9034436 ,  0.72443116],
[-0.48332193,  0.23101914,  0.87393326, -1.2042308 ]],
dtype=float32)>

tf.concat([a,b],axis=1)

<tf.Tensor: shape=(2, 8), dtype=float32, numpy=
array([[ 0.16198424, -0.7170487 , -0.20940438, -0.46842927, -0.15179256,
-0.41726607, -1.9034436 ,  0.72443116],
[ 0.48012358,  0.82777774, -0.37541786, -0.6629169 , -0.48332193,
0.23101914,  0.87393326, -1.2042308 ]], dtype=float32)>


a = tf.random.normal([2,2])
b = tf.random.normal([2,2])
tf.stack([a,b],axis=0) #

<tf.Tensor: shape=(2, 2, 2), dtype=float32, numpy=
array([[[-2.1611633 ,  0.4318549 ],
[-1.7556009 ,  0.6960343 ]],

[[-0.84239227,  0.9800302 ],
[ 0.5497298 ,  0.0607984 ]]], dtype=float32)>


a = tf.random.normal([2,2])
b = tf.random.normal([2,2])
tf.stack([a,b],axis=-1)

<tf.Tensor: shape=(2, 2, 2), dtype=float32, numpy=
array([[[-2.09798   ,  0.5505884 ],
[-1.1372471 ,  0.08376882]],

[[-1.0453051 ,  0.47830236],
[-1.1234645 , -0.97358865]]], dtype=float32)>


### 1.2 分割

-x：待分割张量
-axis：分割的维度索引号
-num_or_size_splits：切割方案。当 num_or_size_splits 为单个数值时，如 10，表示切割为 10 份；当 num_or_size_splits 为 List 时，每个元素表示每份的长度, 如[2,4,2,2]表示切割为 4 份，每份的长度分别为 2,4,2,2

x = tf.random.normal([4,2])
print(x)
result = tf.split(x, axis = 0, num_or_size_splits=2)
result


tf.Tensor(
[[ 0.77127916  0.62768835]
[-0.76758057  1.3676474 ]
[-0.10122015 -0.917917  ]
[-0.1592799  -0.33670765]], shape=(4, 2), dtype=float32)

[<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[ 0.77127916,  0.62768835],
[-0.76758057,  1.3676474 ]], dtype=float32)>,
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[-0.10122015, -0.917917  ],
[-0.1592799 , -0.33670765]], dtype=float32)>]

tf.split(x, axis = 0, num_or_size_splits=[1,2,1])


[<tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[0.77127916, 0.62768835]], dtype=float32)>,
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[-0.76758057,  1.3676474 ],
[-0.10122015, -0.917917  ]], dtype=float32)>,
<tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[-0.1592799 , -0.33670765]], dtype=float32)>]


x = tf.random.normal([4,2])
tf.unstack(x, axis = 0)


[<tf.Tensor: shape=(2,), dtype=float32, numpy=array([-0.69661826,  0.42463547], dtype=float32)>,
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([ 0.40786335, -0.9408407 ], dtype=float32)>,
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([-0.71312106, -0.33494622], dtype=float32)>,
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([0.9833806, 0.7918092], dtype=float32)>]


## 2.数据统计

### 2.1 向量范数

L1 范数，定义为向量 𝒙 的所有元素绝对值之和

x = tf.ones([2,2])
tf.norm(x, ord = 1)


<tf.Tensor: shape=(), dtype=float32, numpy=4.0>


L2 范数，定义为向量 𝒙 的所有元素的平方和，再开根号

tf.norm(x, ord = 2)


<tf.Tensor: shape=(), dtype=float32, numpy=2.0>


∞ −范数，定义为向量 𝒙 的所有元素绝对值的最大值

tf.norm(x, ord = np.inf)


<tf.Tensor: shape=(), dtype=float32, numpy=1.0>


### 2.2 最大最小值、均值、和

x = tf.random.normal([2,3])
tf.reduce_max(x, axis = 1)


<tf.Tensor: shape=(2,), dtype=float32, numpy=array([1.1455595, 0.8110037], dtype=float32)>

tf.reduce_min(x, axis = 1)


<tf.Tensor: shape=(2,), dtype=float32, numpy=array([-0.8374149, -1.2768023], dtype=float32)>

tf.reduce_mean(x, axis = 1)


<tf.Tensor: shape=(2,), dtype=float32, numpy=array([ 0.21712641, -0.16247804], dtype=float32)>

tf.reduce_sum(x, axis = 1)


<tf.Tensor: shape=(2,), dtype=float32, numpy=array([ 0.6513792 , -0.48743412], dtype=float32)>


out = tf.random.normal([4,10]) # 网络预测输出
y = tf.constant([1,2,2,0]) # 真实标签
y = tf.one_hot(y,depth=10) # one-hot 编码
loss = keras.losses.mse(y,out) # 计算每个样本的误差
loss = tf.reduce_mean(loss) # 平均误差
loss


<tf.Tensor: shape=(), dtype=float32, numpy=1.0784723>


out = tf.random.normal([2,10])
out = tf.nn.softmax(out, axis=1) # 通过 softmax 转换为概率值
out


<tf.Tensor: shape=(2, 10), dtype=float32, numpy=
array([[0.03961995, 0.26136935, 0.01498432, 0.03388612, 0.03053044,
0.05304638, 0.05151249, 0.0134019 , 0.17832054, 0.3233286 ],
[0.06895317, 0.13860522, 0.14075696, 0.02185706, 0.04494175,
0.21044637, 0.20726745, 0.04014605, 0.01419329, 0.11283264]],
dtype=float32)>


pred = tf.argmax(out, axis=1)
pred


<tf.Tensor: shape=(2,), dtype=int64, numpy=array([9, 5], dtype=int64)>


### 2.3 张量比较

out = tf.random.normal([10,10])
out = tf.nn.softmax(out, axis=1)
pred = tf.argmax(out, axis=1)
pred


<tf.Tensor: shape=(10,), dtype=int64, numpy=array([3, 2, 4, 3, 0, 4, 5, 0, 2, 6], dtype=int64)>


y = tf.random.uniform([10],dtype=tf.int64,maxval=10)
y


<tf.Tensor: shape=(10,), dtype=int64, numpy=array([7, 3, 9, 2, 7, 4, 3, 1, 4, 5], dtype=int64)>


out = tf.equal(pred,y)
out


<tf.Tensor: shape=(10,), dtype=bool, numpy=
array([False, False, False, False, False,  True, False, False, False,
False])>


tf.equal() 函数返回布尔型的张量比较结果，只需要统计张量中 True 元素的个数，即可知道

out = tf.cast(out, dtype=tf.float32) # 布尔型转 int 型
correct = tf.reduce_sum(out) # 统计 True 的个数
correct


<tf.Tensor: shape=(), dtype=float32, numpy=1.0>


### 2.4 填充与复制

[𝐿𝑒𝑓𝑡 𝑃𝑎𝑑𝑑𝑖𝑛𝑔, 𝑅𝑖𝑔ℎ𝑡 𝑃𝑎𝑑𝑑𝑖𝑛𝑔]的嵌套方案 List，如 [[0,0],[2,1],[1,2]] 表示第一个维度不填

b = tf.constant([1,2,3,4])


<tf.Tensor: shape=(6,), dtype=int32, numpy=array([1, 2, 3, 4, 0, 0])>

tf.pad(b, [[2,2]])#第一维，左边填充俩个，右边填充俩个


<tf.Tensor: shape=(8,), dtype=int32, numpy=array([0, 0, 1, 2, 3, 4, 0, 0])>


x = tf.random.normal([2,2])
tf.tile(x, [1,2])


<tf.Tensor: shape=(2, 4), dtype=float32, numpy=
array([[ 1.462598  ,  1.7452018 ,  1.462598  ,  1.7452018 ],
[-1.4659724 , -0.47004214, -1.4659724 , -0.47004214]],
dtype=float32)>


## 3.数据限幅

x = tf.range(9)
tf.maximum(x, 3) # 下限幅3


<tf.Tensor: shape=(9,), dtype=int32, numpy=array([3, 3, 3, 3, 4, 5, 6, 7, 8])>

tf.minimum(x, 5) # 上限幅5


<tf.Tensor: shape=(9,), dtype=int32, numpy=array([0, 1, 2, 3, 4, 5, 5, 5, 5])>


ReLU 函数可以实现为：

def relu(x):
return tf.minimum(x,0.) # 下限幅为 0 即可



𝑥 ∈ [𝑎, 𝑏]:

x = tf.range(9)
tf.minimum(tf.maximum(x, 2), 7)


<tf.Tensor: shape=(9,), dtype=int32, numpy=array([2, 2, 2, 3, 4, 5, 6, 7, 7])>


tf.clip_by_value(x,2,7) # 限幅为 2~7


<tf.Tensor: shape=(9,), dtype=int32, numpy=array([2, 2, 2, 3, 4, 5, 6, 7, 7])>


## 4.高级操作

### 4.1 tf.gather

x = tf.random.uniform([4,3,2],maxval=100,dtype=tf.int32)
tf.gather(x,[0,1],axis=0)


<tf.Tensor: shape=(2, 3, 2), dtype=int32, numpy=
array([[[51, 45],
[36, 18],
[56, 57]],

[[18, 16],
[64, 82],
[13,  4]]])>


x[0:2]


<tf.Tensor: shape=(2, 3, 2), dtype=int32, numpy=
array([[[51, 45],
[36, 18],
[56, 57]],

[[18, 16],
[64, 82],
[13,  4]]])>


x = tf.random.uniform([10,3,2],maxval=100,dtype=tf.int32)
tf.gather(x,[0,3,8],axis=0)


<tf.Tensor: shape=(3, 3, 2), dtype=int32, numpy=
array([[[86, 82],
[32, 80],
[35, 71]],

[[97, 16],
[22, 83],
[20, 82]],

[[79, 86],
[13, 46],
[68, 23]]])>


### 4.2 tf.gather_nd

x = tf.random.normal([3,4,4])
tf.gather_nd(x, [[1,2], [2,3]])


<tf.Tensor: shape=(2, 4), dtype=float32, numpy=
array([[-0.5388145 ,  0.00821999,  0.41113982,  1.0409608 ],
[-0.42242923, -0.29552126,  0.6467382 , -1.7555269 ]],
dtype=float32)>

tf.gather_nd(x, [[1,1,3], [2,3,3]])


<tf.Tensor: shape=(2,), dtype=float32, numpy=array([ 0.07165062, -1.7555269 ], dtype=float32)>


x = tf.random.normal([3,4,4])


<tf.Tensor: shape=(2, 4, 4), dtype=float32, numpy=
array([[[ 1.0542077 , -0.48954943, -0.7491975 , -0.43464097],
[-0.46667233, -1.2484705 , -1.7732694 , -1.2128644 ],
[ 1.7540843 ,  0.48327965,  0.95591843, -1.5143739 ],
[ 1.3619318 ,  1.168045  , -0.351565  ,  0.1630519 ]],

[[-0.13046652, -2.2438517 , -2.3416731 ,  1.4573859 ],
[ 0.3127366 ,  1.4858567 ,  0.24127336, -1.2466795 ],
[-0.05732883, -0.75874144,  0.6504554 ,  0.756288  ],
[-2.8709486 ,  0.11397363, -0.15979192, -0.07177942]]],
dtype=float32)>


x = tf.random.uniform([2,3,4],maxval=100,dtype=tf.int32)
print(x)


tf.Tensor(
[[[63 32 59 60]
[56 92 36 63]
[53 66 69 30]]

[[75 96 67 15]
[17 11 64 38]
[17 81 53 21]]], shape=(2, 3, 4), dtype=int32)

<tf.Tensor: shape=(3, 4), dtype=int32, numpy=
array([[63, 32, 59, 60],
[56, 92, 36, 63],
[17, 81, 53, 21]])>


### 4.4 tf.where

a = tf.ones([3,3])
b = tf.zeros([3,3])
cond = tf.constant([[True,False,False],[False,True,False],[True,True,False]])
tf.where(cond,a,b)


<tf.Tensor: shape=(3, 3), dtype=float32, numpy=
array([[1., 0., 0.],
[0., 1., 0.],
[1., 1., 0.]], dtype=float32)>


tf.where(cond)


<tf.Tensor: shape=(4, 2), dtype=int64, numpy=
array([[0, 0],
[1, 1],
[2, 0],
[2, 1]], dtype=int64)>


x = tf.random.normal([3,3])


<tf.Tensor: shape=(3, 3), dtype=bool, numpy=
array([[False,  True, False],
[ True, False, False],
[ True,  True, False]])>


indices=tf.where(mask) # 提取为True 的元素索引
indices


<tf.Tensor: shape=(4, 2), dtype=int64, numpy=
array([[0, 1],
[1, 0],
[2, 0],
[2, 1]], dtype=int64)>


tf.gather_nd(x,indices) # 提取正数的元素值


<tf.Tensor: shape=(4,), dtype=float32, numpy=array([0.8857748 , 0.5748998 , 1.3066388 , 0.82504845], dtype=float32)>


tf.boolean_mask(x,x > 0)


<tf.Tensor: shape=(4,), dtype=float32, numpy=array([0.8857748 , 0.5748998 , 1.3066388 , 0.82504845], dtype=float32)>

x[x>0]


<tf.Tensor: shape=(4,), dtype=float32, numpy=array([0.8857748 , 0.5748998 , 1.3066388 , 0.82504845], dtype=float32)>


### 4.5 scatter_nd

scatter_nd方法的更新示意图如下：

# 构造需要刷新数据的位置
indices = tf.constant([[4], [3],[1],[7]])
# 构造需要写入的数据
# 在长度为 8 的全 0 向量上根据 indices 写入 updates


<tf.Tensor: shape=(8,), dtype=float32, numpy=array([0. , 1.1, 0. , 3.3, 4.4, 0. , 0. , 7.7], dtype=float32)>


 # 构造写入位置
indices = tf.constant([[1],[3]])
# 构造写入数据
[[1,1,1,1],[2,2,2,2]]])
# 在 shape 为[4,4,4]白板上根据 indices 写入 updates


<tf.Tensor: shape=(4, 2, 4), dtype=int32, numpy=
array([[[0, 0, 0, 0],
[0, 0, 0, 0]],

[[5, 5, 5, 5],
[6, 6, 6, 6]],

[[0, 0, 0, 0],
[0, 0, 0, 0]],

[[1, 1, 1, 1],
[2, 2, 2, 2]]])>


### 4.6 meshgrid

x = tf.linspace(-8.,8,100) # 设置 x 坐标的间隔
y = tf.linspace(-8.,8,100) # 设置 y 坐标的间隔
x,y = tf.meshgrid(x,y) # 生成网格点，并拆分后返回
x.shape,y.shape # 打印拆分后的所有点的 x,y 坐标张量 shape


(TensorShape([100, 100]), TensorShape([100, 100]))


Sinc 函数在 TensorFlow 中实现如下：

z = tf.sqrt(x**2+y**2)
z = tf.sin(z)/z # sinc 函数实现


fig = plt.figure()
ax = Axes3D(fig)
ax.contour3D(x.numpy(), y.numpy(), z.numpy(), 50)
plt.show()


<Figure size 648x504 with 0 Axes>

<Figure size 648x504 with 0 Axes>



## 5.数据集加载

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import datasets # 导入经典数据集加载模块
(x, y), (x_test, y_test) = datasets.mnist.load_data()
print('x:', x.shape, 'y:', y.shape, 'x test:', x_test.shape, 'y test:', y_test)


x: (60000, 28, 28) y: (60000,) x test: (10000, 28, 28) y test: [7 2 1 ... 4 5 6]


train_db = tf.data.Dataset.from_tensor_slices((x, y))



### 5.2 批训练

train_db = train_db.batch(128)



### 5.3预处理

keras.datasets 中加载的数据集的格式大部分情况都不能满足模型的输入要求，因此需要根据用户的逻辑自己实现预处理函数。Dataset 对象通过提供 map(func)工具函数可以非常方便地调用用户自定义的预处理逻辑，它实现在 func 函数里:

#预处理函数实现在 preprocess 函数中，传入函数引用即可
train_db = train_db.map(preprocess)


def preprocess(x, y): # 自定义的预处理函数
# 调用此函数时会自动传入 x,y 对象，shape 为[b, 28, 28], [b]
# 标准化到 0~1
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 编码
# 返回的 x,y 将替换传入的 x,y 参数，从而实现数据的预处理功能
return x,y


train_db = train_db.map(preprocess)



### 5.4 循环训练

for step, (x,y) in enumerate(train_db): # 迭代数据集对象，带 step 参数



for x,y in train_db: # 迭代数据集对象



train_db = train_db.repeat(20) # 数据集跌打 20 遍才终止



## 6.MNIST手写数字识别实战

# 导入要使用的库
import  matplotlib
from    matplotlib import pyplot as plt
# Default parameters for plots
matplotlib.rcParams['font.size'] = 20
matplotlib.rcParams['figure.titlesize'] = 20
matplotlib.rcParams['figure.figsize'] = [9, 7]
matplotlib.rcParams['font.family'] = ['STKaiTi']
matplotlib.rcParams['axes.unicode_minus']=False
import  tensorflow as tf
from    tensorflow import keras
from    tensorflow.keras import datasets, layers, optimizers
import  os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
print(tf.__version__)

def preprocess(x, y):
# [b, 28, 28], [b]
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)
return x,y
(x, y), (x_test, y_test) = datasets.mnist.load_data()
print('x:', x.shape, 'y:', y.shape, 'x test:', x_test.shape, 'y test:', y_test)

# 数据预处理
batchsz = 512
train_db = tf.data.Dataset.from_tensor_slices((x, y))
train_db = train_db.shuffle(1000).batch(batchsz).map(preprocess).repeat(20)

test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_db = test_db.shuffle(1000).batch(batchsz).map(preprocess)

x,y = next(iter(train_db))
print('train sample:', x.shape, y.shape)
# print(x[0], y[0])

def main():
# learning rate
lr = 1e-2
accs,losses = [], []
# 784 => 512

#得到参数
w1, b1 = tf.Variable(tf.random.normal([784, 256], stddev=0.1)), tf.Variable(tf.zeros([256]))
# 512 => 256
w2, b2 = tf.Variable(tf.random.normal([256, 128], stddev=0.1)), tf.Variable(tf.zeros([128]))
# 256 => 10
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):
# [b, 28, 28] => [b, 784]
x = tf.reshape(x, (-1, 784))
# layer1.
h1 = x @ w1 + b1
h1 = tf.nn.relu(h1)
# layer2
h2 = h1 @ w2 + b2
h2 = tf.nn.relu(h2)
# output
out = h2 @ w3 + b3
# out = tf.nn.relu(out)
# compute loss
# [b, 10] - [b, 10]
loss = tf.square(y-out)
# [b, 10] => scalar
loss = tf.reduce_mean(loss)
for p, g in zip([w1, b1, w2, b2, w3, b3], grads): # 更新参数
p.assign_sub(lr * g)
# print
if step % 80 == 0:
print(step, 'loss:', float(loss))
losses.append(float(loss))
if step %80 == 0:
# evaluate/test
total, total_correct = 0., 0

for x, y in test_db:
# layer1.
h1 = x @ w1 + b1
h1 = tf.nn.relu(h1)
# layer2
h2 = h1 @ w2 + b2
h2 = tf.nn.relu(h2)
# output
out = h2 @ w3 + b3
# [b, 10] => [b]
pred = tf.argmax(out, axis=1)
# convert one_hot y to number y
y = tf.argmax(y, axis=1)
# bool type
correct = tf.equal(pred, y)
# bool tensor => int tensor => numpy
total_correct += tf.reduce_sum(tf.cast(correct, dtype=tf.int32)).numpy()
total += x.shape[0]

print(step, 'Evaluate Acc:', total_correct/total)

accs.append(total_correct/total)

plt.figure()
x = [i*80 for i in range(len(losses))]
plt.plot(x, losses, color='C0', marker='s', label='训练')
plt.ylabel('MSE')
plt.xlabel('Step')
plt.legend()
plt.savefig('train.svg')

plt.figure()
plt.plot(x, accs, color='C1', marker='s', label='测试')
plt.ylabel('准确率')
plt.xlabel('Step')
plt.legend()
plt.savefig('test.svg')
plt.show()

if __name__ == '__main__':
main()

`

0
1 收藏

0 评论
1 收藏
0