【Tensorflow学习笔记】

目录

1 环境配置

2. 回归问题

2.1 连续值的预测

2.2 回归问题的例子:

2.3 分类问题--手写数字识别问题

3. tensorflow的基本操作

3.1 tensorflow的数据类型

3.2 索引与切片

3.3 维度变换

3.4 broadingcast:

3.5 数学运算

3.6 前向传播

3.7 张量的合并与分割

3.8 张量的数据统计

3.9 张量的排序

3.10 填充与复制

3.11 张量的限幅

3.12 高阶操作

4. 数据集的加载 

5.全连接层 

  6. 输出方式             

​编辑 sigmoid:

7. 误差计算 

7.1 损失函数

7.1.1 交叉熵 

8. 梯度下降

8.1 一阶梯度下降

8.2 二阶梯度下降

 9. 激活函数及梯度

9.1 Sigmoid / Logistic 激活函数   

 9.2 Tanh 激活函数

9.3 Relu 激活函数

 10 Loss及其梯度

 10.1 均方差 MSE

10.2 Cross Entropy Loss (主要用于分类问题中)


1 环境配置

2. 回归问题

目标:决定

  1.  向左/右走---这种离散问题
  2. 连续值的增减预测问题

2.1 连续值的预测

f\Theta:   x--->y

x:输入的数据

f(x):预测值

y:真实值

 

f(x)--->逼近y那么预测值和真实值的误差将会变小 

- 连续值预测例子

y=w*x+b

1.567=w*1+b

3.043=w*2+b

类似于上面的这组方程是二元一次方程  很容易进行求解,但是往往在实际问题中,要用方程进行求解,大部分必须加入噪声值

噪声值 :

y=w*x+b+\epsilon   [\epsilon--N(0,1)] 

1.567 = w* 1 +b + eps

3.043 = w* 2 +b + eps

4.519 = w* 3 +b + eps

 如果加入\epsilon这个高斯噪声  那么上面的式子就会符合上图的函数图像

所以要用到梯度下降法:lr:衰减因子  加入衰减因子的原因:担心loss函数下降太快,然后跨越了最小值

将w和b多次进行更新后,就可以得到一个loss函数的最小值 

 

2.2 回归问题的例子:

 使用numpy进行举例

计算下式的loss最小值

 

import numpy as np


# y = wx + b
def compute_error_for_line_given_points(b, w, points):
    totalError = 0
    for i in range(0, len(points)):
        x = points[i, 0]
        y = points[i, 1]
        # computer mean-squared-error
        totalError += (y - (w * x + b)) ** 2
    # average loss for each point
    return totalError / float(len(points))


def step_gradient(b_current, w_current, points, learningRate):
    b_gradient = 0
    w_gradient = 0
    N = float(len(points))
    for i in range(0, len(points)):
        x = points[i, 0]
        y = points[i, 1]
        # grad_b = 2(wx+b-y)
        b_gradient += (2 / N) * ((w_current * x + b_current) - y)
        # grad_w = 2(wx+b-y)*x
        w_gradient += (2 / N) * x * ((w_current * x + b_current) - y)
    # update w'
    new_b = b_current - (learningRate * b_gradient)
    new_w = w_current - (learningRate * w_gradient)
    return [new_b, new_w]


def gradient_descent_runner(points, starting_b, starting_w, learning_rate, num_iterations):
    b = starting_b
    w = starting_w
    # update for several times
    for i in range(num_iterations):
        b, w = step_gradient(b, w, np.array(points), learning_rate)
    return [b, w]


def run():
    points = np.genfromtxt("./data/data.csv", delimiter=",")
    learning_rate = 0.0001
    initial_b = 0  # initial y-intercept guess
    initial_w = 0  # initial slope guess
    num_iterations = 1000
    print("Starting gradient descent at b = {0}, w = {1}, error = {2}"
          .format(initial_b, initial_w,
                  compute_error_for_line_given_points(initial_b, initial_w, points))
          )
    print("Running...")
    [b, w] = gradient_descent_runner(points, initial_b, initial_w, learning_rate, num_iterations)
    print("After {0} iterations b = {1}, w = {2}, error = {3}".
          format(num_iterations, b, w,
                 compute_error_for_line_given_points(b, w, points))
          )


if __name__ == '__main__':
    run()

 

可以看出来  当w和b进行了一千次更新 error缩小了50倍 

2.3 分类问题--手写数字识别问题

 

 

 

 

 但是我们可以看到上图中的表达式是线性的表达式,是不可以处理非线性的问题:分类

所以我们需要将上式变为非线性的  rule:激活函数   

 

 但是上面的式子还是太简单,因为分类问题太过复杂

 

import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, optimizers, datasets
# 训练集    # 测试集
(x, y), (x_val, y_val) = datasets.mnist.load_data()
# 将数据转换为tensor
x = tf.convert_to_tensor(x, dtype=tf.float32) / 255.
y = tf.convert_to_tensor(y, dtype=tf.int32)
y = tf.one_hot(y, depth=10)
print(x.shape, y.shape)
# Dataset 转换为Dataset 是为了默认抽取一张图片
train_dataset = tf.data.Dataset.from_tensor_slices((x, y))
train_dataset = train_dataset.batch(200) # batch 前200张图片

model = keras.Sequential([
    layers.Dense(512, activation='relu'),  # Dense 全连接 因为rule了3层
    layers.Dense(256, activation='relu'),
    layers.Dense(10)])
             # w=w-lr*(l的倒数/w的导数)
optimizer = optimizers.SGD(learning_rate=0.001)


def train_epoch(epoch):
    # Step4.loop
    for step, (x, y) in enumerate(train_dataset):   # x[64,28,28]  y[64]
        with tf.GradientTape() as tape:
            # [b, 28, 28] => [b, 784]
            x = tf.reshape(x, (-1, 28 * 28))
            # Step1. compute output
            # [b, 784] => [b, 10]
            out = model(x)
            # Step2. compute loss  
            loss = tf.reduce_sum(tf.square(out - y)) / x.shape[0]

        # Step3. optimize and update w1, w2, w3, b1, b2, b3
        grads = tape.gradient(loss, model.trainable_variables)
        # w' = w - lr * grad
        optimizer.apply_gradients(zip(grads, model.trainable_variables))

        if step % 100 == 0:
            print(epoch, step, 'loss:', loss.numpy())


def train():
    for epoch in range(30):
        train_epoch(epoch)


if __name__ == '__main__':
    train()

 运行结果:

(60000, 28, 28) (60000, 10)
0 0 loss: 1.8806361
0 100 loss: 0.91417557
0 200 loss: 0.7643411
1 0 loss: 0.67336375
1 100 loss: 0.6687319
1 200 loss: 0.59360564
2 0 loss: 0.54961735
2 100 loss: 0.57993674
2 200 loss: 0.518426
3 0 loss: 0.4885314
3 100 loss: 0.5281107
3 200 loss: 0.47221303
4 0 loss: 0.4494177
4 100 loss: 0.4927804
4 200 loss: 0.43966162
5 0 loss: 0.421928
5 100 loss: 0.46658465
5 200 loss: 0.41507694
6 0 loss: 0.40076798
6 100 loss: 0.4455361
6 200 loss: 0.39548245
7 0 loss: 0.383581
7 100 loss: 0.4279397
7 200 loss: 0.37927315
8 0 loss: 0.36923844
8 100 loss: 0.41299605
8 200 loss: 0.36541012
9 0 loss: 0.3570761
9 100 loss: 0.40010476
9 200 loss: 0.35327214
10 0 loss: 0.34639445
10 100 loss: 0.38882846
10 200 loss: 0.3425215
11 0 loss: 0.3368655
11 100 loss: 0.37876624
11 200 loss: 0.33289525
12 0 loss: 0.32833594
12 100 loss: 0.36986205
12 200 loss: 0.32432818
13 0 loss: 0.32051194
13 100 loss: 0.36177525
13 200 loss: 0.3165398
14 0 loss: 0.3132586
14 100 loss: 0.35428786
14 200 loss: 0.3093531
15 0 loss: 0.30649897
15 100 loss: 0.34743267
15 200 loss: 0.30274618
16 0 loss: 0.3002452
16 100 loss: 0.34107658
16 200 loss: 0.29668802
17 0 loss: 0.29445076
17 100 loss: 0.33514968
17 200 loss: 0.2910626
18 0 loss: 0.28897542
18 100 loss: 0.3296007
18 200 loss: 0.28584978
19 0 loss: 0.28381217
19 100 loss: 0.32438904
19 200 loss: 0.2809379
20 0 loss: 0.27895096
20 100 loss: 0.31947154
20 200 loss: 0.27635878
21 0 loss: 0.27437901
21 100 loss: 0.31478703
21 200 loss: 0.2719757
22 0 loss: 0.27010947
22 100 loss: 0.31033486
22 200 loss: 0.26777804
23 0 loss: 0.26604235
23 100 loss: 0.30606544
23 200 loss: 0.263791
24 0 loss: 0.26221764
24 100 loss: 0.3019774
24 200 loss: 0.2600085
25 0 loss: 0.25858325
25 100 loss: 0.29807678
25 200 loss: 0.25640425
26 0 loss: 0.25512514
26 100 loss: 0.29433423
26 200 loss: 0.25296706
27 0 loss: 0.25179663
27 100 loss: 0.29071003
27 200 loss: 0.2497348
28 0 loss: 0.24858408
28 100 loss: 0.28728238
28 200 loss: 0.2466451
29 0 loss: 0.24549729
29 100 loss: 0.283989
29 200 loss: 0.24368972

3. tensorflow的基本操作

3.1 tensorflow的数据类型

▪  scalar: 1.1   常数
vector: [1.1],  [1.1, 2.2, … ]   1维
matrix: [[1.1, 2.2],  [3.3, 4.4],  [5.5, 6.6]]   二维
tensor: 𝑟𝑎𝑛𝑘 > 2  维度大于2
tensorflow支持的数据类型:
- int  float double
- bool
- string
tf.constant(1):创建一个整形的数据   也就是  单个常量 1
tf.constant(1.):创建一个浮点类型的数据
tf.device("cpu"):调用设备
tf.range(4):[0,1,2,3]
b.numpy()  # 将tensor转换为numpy
tf.convert_to_tensor(a,dtype=tf.int64):将numpy数据转换为tensor
b.ndim  # tensor的形状   常量的ndim是0  【1,1】是1
tf.rank(b):返回张量的秩
判断数据是否为tensor:isinstance(a,tf.Tensor)  tf.is_tensor(b) 直接用第二种就可以  第一种有时候有误
tf.cast(b,dtype=tf.bool) 整型和bool类型的转换
tf.Variable(a):转换为variable是因为后期可以进行求导等操作  比较方便
import tensorflow as tf
import  os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
import numpy as np
# 练习tensorflow的数据类型
"""
tf.Tensor(1, shape=(), dtype=int32)
tf.Tensor(1.0, shape=(), dtype=float32)
tf.Tensor(2.0, shape=(), dtype=float64)
tf.Tensor([ True False], shape=(2,), dtype=bool)
tf.Tensor(b'hello world', shape=(), dtype=string)
"""
# 1. 创建一个整形的数据   也就是  单个常量 1
a=tf.constant(1)
print(a)  # tf.Tensor(1, shape=(), dtype=int32)
# 2. 创建一个浮点类型的数据
a1=tf.constant(1.)
print(a1)  # tf.Tensor(1.0, shape=(), dtype=float32)
# 3. 浮点类型的数据规定整型类型数据接收报错
# a3=tf.constant(2.2,dtype=tf.int32)
# print(a3) # Cannot convert 2.2 to EagerTensor of dtype int32

# 4.
a4=tf.constant(2.,dtype=tf.double)
print(a4) # tf.Tensor(2.0, shape=(), dtype=float64)
# 5. bool类型
a5=tf.constant([True,False])
print(a5) # tf.Tensor([ True False], shape=(2,), dtype=bool)
# 6. 字符串类型
a6=tf.constant("hello world")
print(a6) # tf.Tensor(b'hello world', shape=(), dtype=string)

print("-----------------------------------------------------------------------------")
with tf.device("cpu"):
    a=tf.constant([1])  #/job:localhost/replica:0/task:0/device:CPU:0
with tf.device("GPU"):
    b=tf.range(4)   # /job:localhost/replica:0/task:0/device:GPU:0
aa=a.gpu() # 将cpu的操作转移到gpu上  不转之前的操作位置一般是默认的 不需要进行特定的规定
#print(aa.device)
bb=b.cpu()
#print(bb.device)
b1=b.numpy()  # 将tensor转换为numpy
# print(b1)  # [0 1 2 3]
b_shape=b.ndim  # tensor的形状   常量的ndim是0  【1,1】是1
# print(b_shape) # 1
b2=tf.rank(b)
# print(b2)  #tf.Tensor(1, shape=(), dtype=int32)
b3=tf.rank(tf.ones([3,4,2]))
# print(b3)  # tf.Tensor(3, shape=(), dtype=int32)
print("----------------------------------------------------------------------")
# 判断数据是否为tensor
a=tf.constant([1,1])
b=tf.constant([True,False])
c=tf.constant("hello world")
d=np.arange(4)

a_is=isinstance(a,tf.Tensor)
b_is=tf.is_tensor(b)
d_is=tf.is_tensor(d)
print("结果是:")
"""
True
True
False
"""
print(a_is)
print(b_is)
print(d_is)

print("a,b,c的数据类型是:",a.dtype,b.dtype,c.dtype)

print("---------------------------------------------------------------")
"""
[0 1 2 3 4]
int32
<dtype: 'int32'>
<dtype: 'int64'>
tf.Tensor([0 1 2 3 4], shape=(5,), dtype=int64)
tf.Tensor([0. 1. 2. 3. 4.], shape=(5,), dtype=float64)
tf.Tensor([0 1 2 3 4], shape=(5,), dtype=int32)
"""
print("类型的相互转换")
a=np.arange(5)
print(a)
print(a.dtype)
# 将numpy数据转换为tensor
aa=tf.convert_to_tensor(a)
print(aa.dtype)
aa=tf.convert_to_tensor(a,dtype=tf.int64)
print(aa.dtype)
# 将tensor中的 int64 转换为float类型
aa_1=tf.cast(aa,dtype=tf.float32)
print(aa)

aaa=tf.cast(aa,dtype=tf.double)
print(aaa)

aaaa=tf.cast(aaa,dtype=tf.int32)
print(aaaa)

print("---------------------------------------------------------------------------------")
print("整型和bool类型的转换")
b=tf.constant([0,1])
b_bool=tf.cast(b,dtype=tf.bool)
print(b_bool)

b_int=tf.cast(b_bool,dtype=tf.int32)
print(b_int)
print("---------------------------------------------------------------------------------")
print("variable 数据类型")
a=tf.range(5)
print(a)
b=tf.Variable(a)   # 转换为variable是因为后期可以进行求导等操作  比较方便
print(b)
print(b.name)
print(b.trainable)

# 判断是否为Tensor  注意第一个 为flase  所以以后进行直接用is_tensor()
"""
False
True
True
"""
print(isinstance(b,tf.Tensor))
print(isinstance(b,tf.Variable))
print(tf.is_tensor(b))


print("---------------------------------------------------------------------------------")
# 将numpy转换为tensor
a=tf.ones([])
aa=a.numpy()
print(a)
print(aa)
print(int(a))
print(float(a))
print("---------------------------------------------------------------------------------")




按照要求生成tensor
#数据为0 的初始化
z1=tf.zeros([1,2]) # [1,2] 代表 二维   一行  两列 (shape)
print("z1:",z1)
z2=tf.zeros([2,3,3])  #【2,3,3】  代表的是   shape
print("z2:",z2)

z3=tf.zeros_like(z2) #创建一个类似于z2 值为0的tensor
print("z3:",z3)
print("---------------------------------------------------------------------------------")
# 数据为1的初始化
o1=tf.ones(1)
print("o1:",o1)

o2=tf.ones([])
print("o2:",o2)

o3=tf.ones([2])
print("o3:",o3)

o4=tf.ones([2,3])
print("o4:",o4)

o5=tf.ones_like(o4)
print("o5:",o5)
print("---------------------------------------------------------------------------------")
# 规定数据的初始化
f1=tf.fill([2,2],3)
print("f1:",f1)
"""
o1: tf.Tensor([1.], shape=(1,), dtype=float32)
o2: tf.Tensor(1.0, shape=(), dtype=float32)
o3: tf.Tensor([1. 1.], shape=(2,), dtype=float32)
o4: tf.Tensor(
[[1. 1. 1.]
 [1. 1. 1.]], shape=(2, 3), dtype=float32)
o5: tf.Tensor(
[[1. 1. 1.]
 [1. 1. 1.]], shape=(2, 3), dtype=float32)

f1: tf.Tensor(
[[3 3]
 [3 3]], shape=(2, 2), dtype=int32)
"""
随机化的初始化
# 1.随机正态分部
# 两行两列   均值为  方差为1
s1=tf.random.normal([2,2],mean=1,stddev=1)
print("s1:",s1)

# 2. 截断的正态分布  截断部分不符合的正态分布的数据  然后从符合的数据中再次选取
s2=tf.random.truncated_normal([2,2],mean=0,stddev=1)
print("s2:",s2)

# 3. 均匀分布   两行两列   最小值为0   最大值为1
s3=tf.random.uniform([2,2],minval=0,maxval=1)
print("s3:",s3)

"""
s1: tf.Tensor(
[[1.2427497 2.1810374]
 [1.1267862 2.3465338]], shape=(2, 2), dtype=float32)
s2: tf.Tensor(
[[-0.6811669   0.05215301]
 [ 0.65320575  0.4712163 ]], shape=(2, 2), dtype=float32)
s3: tf.Tensor(
[[0.69793344 0.7319168 ]
 [0.34593427 0.24361467]], shape=(2, 2), dtype=float32)

"""

3.2 索引与切片

第一种方式的索引

import tensorflow as tf
import numpy as np
a=tf.ones([1,5,5,3])
print(a[0][0])
"""
tf.Tensor(
[[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]], shape=(5, 3), dtype=float32)
"""
print("--------------")

print(a[0][0][0])
"""
tf.Tensor([1. 1. 1.], shape=(3,), dtype=float32)
"""
第二种方式的索引
# 第二种方式的索引
b=tf.random.normal([4,28,28,3])
print(b[1].shape)
print(b[1,2].shape)
print(b[1,2,3].shape)
print(b[1,2,3,1].shape)
"""
(28, 28, 3)
(28, 3)
(3,)
()
"""
c=tf.range(10)
print(c)
# 从左往右的index是0 1 2 3 4 5...
# 从右往左的index是 -1 -2 -3 -4...
print(c[-1:])
print(c[-2:])
print(c[:2]) #包左不包右
print(c[:-1])
"""
tf.Tensor([0 1 2 3 4 5 6 7 8 9], shape=(10,), dtype=int32)
tf.Tensor([9], shape=(1,), dtype=int32)
tf.Tensor([8 9], shape=(2,), dtype=int32)
tf.Tensor([0 1], shape=(2,), dtype=int32)
tf.Tensor([0 1 2 3 4 5 6 7 8], shape=(9,), dtype=int32)
"""
d=b
print(d.shape)
print(d[0].shape)
print(d[0,:,:,:].shape)  # 和第一个是相同的 取所在维度的所有数据
print(d[0,1,:,:].shape)
print(d[:,:,:,0].shape) # 选取的是0 通道
print(d[:,:,:,2].shape)
print(d[:,0,:,:].shape)
"""
(4, 28, 28, 3)
(28, 28, 3)
(28, 28, 3)
(28, 3)
(4, 28, 28)
(4, 28, 28)
(4, 28, 3)
"""
想要隔几个的切片数据  左:右:隔几个
e=b
print(e.shape)
print(e[0:2,:,:,:].shape)
print(e[:,0:28:2,0:28:2,:].shape)
print(e[:,:14,:14,:].shape)
print(e[:,14:,14:,:].shape)
print(e[:,::2,::2,:].shape)
"""
(4, 28, 28, 3)
(2, 28, 28, 3)
(4, 14, 14, 3)
(4, 14, 14, 3)
(4, 14, 14, 3)
(4, 14, 14, 3)
"""
倒叙  最后的值需要是负数  就是倒序

# 倒叙
f=tf.range(4)
print(f)
print(f[::-1])
print(f[::-2])  # 从最后一位 然后每两个取一个值
print(f[2::-2]) # 从二号位置,倒序每隔两个取一个值
"""
tf.Tensor([0 1 2 3], shape=(4,), dtype=int32)
tf.Tensor([3 2 1 0], shape=(4,), dtype=int32)
tf.Tensor([3 1], shape=(2,), dtype=int32)
tf.Tensor([2 0], shape=(2,), dtype=int32)
"""
省略号  代表任意长度的冒号  (只要能推导出来)

#省略号
g=tf.random.normal([2,4,28,28,3])
print(g[0].shape)
print(g[0,:,:,:].shape)
print(g[0,...].shape)
print(g[:,:,:,:,0].shape)
print(g[...,0].shape)
print(g[0,...,2].shape)
print(g[1,0,...,0].shape)
"""
(4, 28, 28, 3)
(4, 28, 28, 3)
(2, 4, 28, 28)
(2, 4, 28, 28)
(4, 28, 28)
(28, 28)
"""
gather    收集任意维度  任意行取值

# tf.gather   任意维度  任意行取值
h=tf.random.normal([4,35,8])   #axis 维度  indices 为维度上的索引号
print(h.shape)
print(tf.gather(h,axis=0,indices=[2,3]).shape)
print(h[2:4].shape)
print(tf.gather(h,axis=0,indices=[2,1,3,0]).shape)
print(tf.gather(h,axis=1,indices=[2,3,7,9,16]).shape)
print(tf.gather(h,axis=2,indices=[2,3,7]).shape)
"""
(4, 35, 8)
(2, 35, 8)
(2, 35, 8)
(4, 35, 8)
(4, 5, 8)
(4, 35, 3)
"""
gather_nd :取固定索引的tensor,可以进行拼接
i=h
print(i.shape)
print(tf.gather_nd(i,[0]).shape)
print(tf.gather_nd(i,[0,1]).shape)
print(tf.gather_nd(i,[0,1,2]).shape)
print(tf.gather_nd(i,[[0,1,2]]).shape)  # 值  【【】】
"""
(4, 35, 8)
(35, 8)
(8,)
()
(1,)
"""



print(tf.gather_nd(i,[[0,0],[1,1]]).shape)
print(tf.gather_nd(i,[[0,0],[1,1],[2,2]]).shape)
print(tf.gather_nd(i,[[0,0,0],[1,1,1],[2,2,2]]).shape)
print(tf.gather_nd(i,[[[0,0,0],[1,1,1],[2,2,2]]]).shape)

"""
(2, 8)
(3, 8)
(3,)
(1, 3)
"""
boolean_mask
j=tf.random.normal([4,28,28,3])
print(j.shape)
print(tf.boolean_mask(j,mask=[True,True,False,False]).shape)
print(tf.boolean_mask(j,mask=[True,True,False],axis=3).shape)
k=tf.ones([2,3,4])
print(k.shape)
print(tf.boolean_mask(k,mask=[[True,False,False],[False,True,True]]))

3.3 维度变换

reshape:

a=tf.random.normal([4,28,28,3])
print(a.shape)
print(a.ndim)
print(tf.reshape(a,[4,784,3]).shape)
print(tf.reshape(a,[4,-1,3]).shape)
print(tf.reshape(a,[4,784*3]).shape)
print(tf.reshape(a,[4,-1]).shape)
"""

(4, 28, 28, 3)
4
(4, 784, 3)
(4, 784, 3)
(4, 2352)
(4, 2352)
"""
transpose:
b=tf.random.normal([4,3,2,1])
print(b.shape)
print(tf.transpose(b).shape)  #转置
print(tf.transpose(b,perm=[0,1,3,2]).shape) # 根据规定的维度进行变换
print(b.shape)
"""
(4, 3, 2, 1)
(1, 2, 3, 4)
(4, 3, 1, 2)
(4, 3, 2, 1)
"""


c=tf.random.normal([4,28,28,3])
print(c.shape)
print(tf.transpose(c,[0,2,1,3]).shape)
print(tf.transpose(c,[0,3,2,1]).shape)  # 转置后的数据集
# print(c.shape) # 这里是初始的数据集
print(tf.transpose(c,[0,3,1,2]).shape)

"""
(4, 28, 28, 3)
(4, 28, 28, 3)
(4, 3, 28, 28)
(4, 3, 28, 28)
"""
expand_dims:增加一个维度

# 增加一个维度
d=tf.random.normal([4,35,8])
print(d.shape)
print(tf.expand_dims(d,axis=0).shape)
print(tf.expand_dims(d,axis=3).shape)# 改变的是一个 视图   不是content
print(tf.expand_dims(d,axis=-1).shape)
print(tf.expand_dims(d,axis=-2).shape)
"""
(4, 35, 8)
(1, 4, 35, 8)
(4, 35, 8, 1)
(4, 35, 8, 1)
(4, 35, 1, 8)
"""
squeeze:减少一个维度
print(tf.squeeze(tf.zeros([1,2,1,1,3])).shape)  # 去掉所有维度为1
d1=tf.zeros([1,2,1,3])
print(tf.squeeze(d1,axis=0).shape)
print(tf.squeeze(d1,axis=2).shape)
print(tf.squeeze(d1,axis=-2).shape)
print(tf.squeeze(d1,axis=-4).shape)
"""
(2, 3)
(2, 1, 3)
(1, 2, 3)
(1, 2, 3)
(2, 1, 3)
"""

3.4 broadingcast:

broadingcast  的好处:
 写起来更加简洁
 所用的内存也更加少
是否能够broadingcast
  没有维度的可以进行扩展   
  有维度的 需要查看数据是否一致  
  如果不一致  那么就不行 
x=tf.random.normal([4,32,32,3])
print((x+tf.random.normal([3])).shape)
print((x+tf.random.normal([32,32,1])).shape)
print((x+tf.random.normal([4,1,1,1])).shape)
# print((x+tf.random.normal([1,4,1,1])).shape)  # 这个不行  因为扩展后之只能是4,4,32,3
b=tf.broadcast_to(tf.random.normal([4,1,1,1]),[4,32,32,3])
print(b.shape)

"""
(4, 32, 32, 3)
(4, 32, 32, 3)
(4, 32, 32, 3)
(4, 32, 32, 3)
"""

3.5 数学运算

1. +-*/
2. ** pow square(平方)
3. sqrt(平凡跟)
4. //(整除) %(取余)
5. exp log
6. @ matmul
7. linear layer
x=tf.fill([2,2],2.)  # 创建一个值为2.0的 2x2的tensor
y=tf.ones([2,2])
print(x+y) # +
print(x-y) # -
print(x*y) # *
print(x/y) # /

print(x//y) # 整除
print(x%y)  # 余除

"""

tf.Tensor(
[[3. 3.]
 [3. 3.]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[1. 1.]
 [1. 1.]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[2. 2.]
 [2. 2.]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[2. 2.]
 [2. 2.]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[2. 2.]
 [2. 2.]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[0. 0.]
 [0. 0.]], shape=(2, 2), dtype=float32)
"""
fill:创建一个值为2.0的 2x2的tensor
print(y)
print(tf.math.log(y))  # 对数  实现不了 直接log 2^3   需要用log3/log2
print(tf.exp(y)) # e的y次方

"""
tf.Tensor(
[[1. 1.]
 [1. 1.]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[0. 0.]
 [0. 0.]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[2.7182817 2.7182817]
 [2.7182817 2.7182817]], shape=(2, 2), dtype=float32)
"""
print(x)
print(tf.pow(x,3)) # x^3
print(x**3)   # x^3
print(tf.sqrt(x))  # x的开方

"""
tf.Tensor(
[[2. 2.]
 [2. 2.]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[8. 8.]
 [8. 8.]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[8. 8.]
 [8. 8.]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[1.4142135 1.4142135]
 [1.4142135 1.4142135]], shape=(2, 2), dtype=float32)
"""
print(x@y)
print(tf.matmul(x,y))
"""
tf.Tensor(
[[4. 4.]
 [4. 4.]], shape=(2, 2), dtype=float32)
tf.Tensor(
[[4. 4.]
 [4. 4.]], shape=(2, 2), dtype=float32)
"""

3.6 前向传播

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import datasets  # 管理数据集的包
import numpy as np
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"]='2'

# x:[60k,28,28]
# y:[60k]
# 这里的数据如果没有就会去谷歌下载
(x,y),_=datasets.mnist.load_data()
# 将数据转换为一个tensor
x=tf.convert_to_tensor(x,dtype=tf.float32)
y=tf.convert_to_tensor(y,dtype=tf.int32)

print(x.shape,y.shape,x.dtype,y.dtype)
print(tf.reduce_min(x),tf.reduce_max(x))
print(tf.reduce_min(y),tf.reduce_max(y))



tarin_db=tf.data.Dataset.from_tensor_slices((x,y)).batch(128)  # 取128组数据
train_iter=iter(tarin_db)# 迭代器
sample=next(train_iter)
print("batch:",sample[0].shape,sample[1].shape)

# [b.784]=>[b,256]=>[b,128]=>[b,10]
# [dim_in,dim_out],[dim_out]
w1=tf.Variable(tf.random.truncated_normal([784,256],stddev=0.01))
b1=tf.Variable(tf.zeros([256]))
w2=tf.Variable(tf.random.truncated_normal([256,128],stddev=0.01))
b2=tf.Variable(tf.zeros([128]))
w3=tf.Variable(tf.random.truncated_normal([128,10],stddev=0.01))
b3=tf.Variable(tf.zeros([10]))
lr=1e-3
for epoch in range(10):
    for step, (x,y) in enumerate(tarin_db):
        # x:[128,28*28]
        # y:[128]
        # [b,28,28]=>[b,28*28]
        x=tf.reshape(x,[-1,28*28])


        with tf.GradientTape() as tape:  # 记录梯度信息
            # x:[b,28*28]
            # h1=x@w1+b1
            #[b,784]@[784,256]+[256]=>[b,256]+[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]=>[10]
            h3=h2@w3+b3
            out=h3

            # computer loss   计算误差
            # out:[b,10]
            # y:[10]=>[b,10]
            y_onehot=tf.one_hot(y,depth=10)
            # 均方差 mse=mean(sun(y-out)^2)
            loss=tf.square(y_onehot-out)
            # mean:scalar
            loss=tf.reduce_mean(loss)

        grads=tape.gradient(loss,[w1,b1,w2,b2,w3,b3])
        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,"loss:",float(loss))
    print("第",epoch+1,"次完")

运行结果:

(60000, 28, 28) (60000,) <dtype: 'float32'> <dtype: 'int32'>
tf.Tensor(0.0, shape=(), dtype=float32) tf.Tensor(255.0, shape=(), dtype=float32)
tf.Tensor(0, shape=(), dtype=int32) tf.Tensor(9, shape=(), dtype=int32)
batch: (128, 28, 28) (128,)

0 loss: 0.1119844913482666
100 loss: 0.07780639082193375
200 loss: 0.0635501816868782
300 loss: 0.059217870235443115
400 loss: 0.056292545050382614
第 1 次完
........
........
........
0 loss: 0.02079847641289234
100 loss: 0.023575711995363235
200 loss: 0.020899346098303795
300 loss: 0.02443523332476616
400 loss: 0.026992296800017357
第 10 次完

3.7 张量的合并与分割

  • tf.concat() :增加 
    tf.split()  :分割- 
    tf.stack()  :增加
    tf.unstack() :拆分
a=tf.ones([4,35,8])
b=tf.ones([2,35,8])
c=tf.concat([a,b],axis=0) # 由0维度进行合并
print(c.shape)  #(6, 35, 8)

a=tf.ones([4,35,8])
b=tf.ones([4,35,8])
print(tf.concat([a,b],axis=-1).shape) # 由最后一个维度进行合并  只能有一个维度是相等的  # (4, 35, 16)


# stack: 增加一个维度   会创建一个新的维度  必须所有的维度相等
print(tf.stack([a,b],axis=0).shape)  #(2, 4, 35, 8)
print(tf.stack([a,b],axis=3).shape)  #(4, 35, 8, 2)

# unstack: 任意一个维度进行拆分   会将一个维度全部变成1  这项就有相应的n个其他维度一样的值
print(tf.unstack(c,axis=3))

#split: 任意一个维度进行拆分   该维度的数据分为num_or_size_splits等分
c=tf.stack([a,b],axis=0)
print(tf.split(c,axis=0,num_or_size_splits=2))
print(tf.split(c,axis=0,num_or_size_splits=[2,4,4]))

3.8 张量的数据统计

# 一范数:绝对值的和
# 二范数:平方和开根方
# 无穷范数:元素中间最大值的绝对值
# 二范数
a=tf.ones([2,2])
b=tf.norm(a)
print(b)  # tf.Tensor(2.0, shape=(), dtype=float32)

a1=tf.random.normal([4,28,28,3])
b1=tf.norm(a1)
print(b1) #tf.Tensor(97.064964, shape=(), dtype=float32)
print(tf.sqrt(tf.reduce_sum(tf.square(a1))))# tf.Tensor(97.064964, shape=(), dtype=float32)


#  ord=2 表示:二范数  axis=1:表示在第一维度
print(tf.norm(a,ord=2,axis=1))
"""
tf.Tensor([1.4142135 1.4142135], shape=(2,), dtype=float32)
"""
# tf.Tensor([2. 2.], shape=(2,), dtype=float32)   
print(tf.norm(a,ord=1,axis=0))  # 表示 一范数   在第0维度 仅在第0维度
  • tf.reduce_min():最小值
    tf.reduce_max():最大值
    tf.reduce_mean():均值
    a=tf.random.normal([4,10])
    print(tf.reduce_min(a))
    print(tf.reduce_max(a))
    print(tf.reduce_mean(a))
    print(tf.reduce_sum(a))
    """
    tf.Tensor(-2.5869026, shape=(), dtype=float32)
    tf.Tensor(1.8564309, shape=(), dtype=float32)
    tf.Tensor(0.038184844, shape=(), dtype=float32)
    tf.Tensor(1.5273938, shape=(), dtype=float32)
    """
    
    
    
    # 在特定维度上的统计
    print(tf.reduce_mean(a,axis=0))
    print(tf.reduce_min(a,axis=0))
    print(tf.reduce_max(a,axis=1))
    print(tf.reduce_sum(a,axis=1))
    """
    tf.Tensor(
    [ 0.10505169 -0.05886896  0.30664688  0.06526639  0.91417456 -0.18145403
     -0.053045   -0.2677212  -0.43354666 -0.01465534], shape=(10,), dtype=float32)
    tf.Tensor(
    [-0.41680923 -1.7630287  -0.589486   -0.6110966  -0.01158845 -0.8438747
     -1.6971208  -1.409077   -0.8982323  -2.5869026 ], shape=(10,), dtype=float32)
    tf.Tensor([1.8564309 1.3673233 1.3612837 1.6885011], shape=(4,), dtype=float32)
    tf.Tensor([ 1.5081751  -3.9327328  -0.47547024  4.4274216 ], shape=(4,), dtype=float32)
    """
    argmax、argmin:
  • 
    print(a.shape)
    print(tf.argmax(a,axis=0)) # 返回0维上的最大值
    print(tf.argmin(a,axis=1)) # 返回1维上的最小值
    """
    (4, 10)
    tf.Tensor([1 2 3 1 1 2 3 1 3 2], shape=(10,), dtype=int64)
    tf.Tensor([8 8 6 3], shape=(4,), dtype=int64)
    """
    equal:
a=tf.constant([1,2,3,2,5])
b=range(5)
result=tf.equal(a,b)
print(result)
c=tf.reduce_sum(tf.cast(result,dtype=tf.int32))
print(c)

"""
tf.Tensor([False False False False False], shape=(5,), dtype=bool)
tf.Tensor(0, shape=(), dtype=int32)
"""
a=tf.constant([[0.1,0.2,0.7],[0.9,0.05,0.05]])
pred=tf.cast(tf.argmax(a,axis=1),dtype=tf.int32)
print("pred:",pred)
y=tf.constant([2,1])
print("y:",y)
print(tf.equal(y,pred))
correct=tf.reduce_sum(tf.cast(tf.equal(y,pred),dtype=tf.int32))
print(correct)
print(correct/2)

"""
pred: tf.Tensor([2 0], shape=(2,), dtype=int32)
y: tf.Tensor([2 1], shape=(2,), dtype=int32)
tf.Tensor([ True False], shape=(2,), dtype=bool)
tf.Tensor(1, shape=(), dtype=int32)
tf.Tensor(0.5, shape=(), dtype=float64)
"""
去重

a=tf.constant([2,2,2,4,4,6])
b=tf.unique(a)
print(b)
"""
Unique(y=<tf.Tensor: id=79, shape=(3,), dtype=int32, numpy=array([2, 4, 6])>,
 idx=<tf.Tensor: id=80, shape=(6,), dtype=int32, numpy=array([0, 0, 0, 1, 1, 2])>)
"""

3.9 张量的排序

sort:进行排序

argsort:将值进行排序返回值的位置顺序

gather:获取张量的位置上的值

# 准备数据
a=tf.random.shuffle(tf.range(5))
print("准备的数据是:",a)
a1=tf.sort(a,direction="DESCENDING")
print("排序后的数据是:",a1)
a2=tf.argsort(a,direction="DESCENDING")
print("排序后的数据的位置是:",a2)
a3=tf.gather(a,a2)
print("根据排序后的坐标位置得到排序的值:",a3)

"""
准备的数据是: tf.Tensor([3 1 2 0 4], shape=(5,), dtype=int32)
排序后的数据是: tf.Tensor([4 3 2 1 0], shape=(5,), dtype=int32)
排序后的数据的位置是: tf.Tensor([4 0 2 1 3], shape=(5,), dtype=int32)
根据排序后的坐标位置得到排序的值: tf.Tensor([4 3 2 1 0], shape=(5,), dtype=int32)
"""


# 案例2:
a=tf.random.uniform([3,3],maxval=10,dtype=tf.int32)
print("排序之前:",a)
a1=tf.sort(a,axis=1)
print("排序之后:",a1)
idx=tf.argsort(a)  # 值排序后的下标
print(idx)
"""
排序之前: tf.Tensor(
[[9 5 3]
 [5 3 5]
 [7 2 3]], shape=(3, 3), dtype=int32)
排序之后: tf.Tensor(
[[3 5 9]
 [3 5 5]
 [2 3 7]], shape=(3, 3), dtype=int32)
tf.Tensor(
[[2 1 0]
 [1 0 2]
 [1 2 0]], shape=(3, 3), dtype=int32)
"""

top_k:返回最大的前几个数据

#返回最大的几个或者 最小的几个
a=tf.constant([[4,6,8],[9,4,7],[4,5,1]])
res=tf.math.top_k(a,2)
print("最大的前两个数据是:",res)
indices=res.indices # 最大的前两个数据的索引号
values=res.values  # 最大的前两个值
"""
最大的前两个数据是: TopKV2(values=<tf.Tensor: id=52, shape=(3, 2), dtype=int32, numpy=
array([[8, 6],
       [9, 7],
       [5, 4]])>, indices=<tf.Tensor: id=53, shape=(3, 2), dtype=int32, numpy=
array([[2, 1],
       [0, 2],
       [1, 0]])>)

"""


# Top-k accuracy
prob=tf.constant([[0.1,0.2,0.7],[0.2,0.7,0.1]])
target=tf.constant([2,0])
k_b=tf.math.top_k(prob,3).indices
print(k_b)
k_b=tf.transpose(k_b,[1,0])
print(k_b)
target=tf.broadcast_to(target,[3,2])
print(target)
"""
tf.Tensor(
[[2 1 0]
 [1 0 2]], shape=(2, 3), dtype=int32)
tf.Tensor(
[[2 1]
 [1 0]
 [0 2]], shape=(3, 2), dtype=int32)
tf.Tensor(
[[2 0]
 [2 0]
 [2 0]], shape=(3, 2), dtype=int32)
"""

例子:top_k

import  tensorflow as tf
import  os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
tf.random.set_seed(2467)

def accuracy(output, target, topk=(1,)):
    maxk = max(topk)  # 获取最大的top_k
    batch_size = target.shape[0] # 10

    pred = tf.math.top_k(output, maxk).indices # 按照顺序排序  每一组的前maxk的下标
    pred = tf.transpose(pred, perm=[1, 0]) # 进行转置
    target_ = tf.broadcast_to(target, pred.shape)
    # [10, b]
    correct = tf.equal(pred, target_)

    res = []
    for k in topk:
        correct_k = tf.cast(tf.reshape(correct[:k], [-1]), dtype=tf.float32)
        correct_k = tf.reduce_sum(correct_k)
        acc = float(correct_k* (100.0 / batch_size) )
        res.append(acc)

    return res



output = tf.random.normal([10, 6])
output = tf.math.softmax(output, axis=1)
target = tf.random.uniform([10], maxval=6, dtype=tf.int32)
print("target:",target)
print("target_shape:",target.shape[0])
print('prob:', output.numpy())
pred = tf.argmax(output, axis=1)
print('pred:', pred.numpy())
print('label:', target.numpy())

acc = accuracy(output, target, topk=(1,2,3,4,5,6))
print('top-1-6 acc:', acc)
target: tf.Tensor([0 2 3 4 2 4 2 3 5 5], shape=(10,), dtype=int32)
target_shape: 10
prob: [[0.25310278 0.21715644 0.16043882 0.13088997 0.04334083 0.19507109]
 [0.05892418 0.04548917 0.00926314 0.14529602 0.66777605 0.07325139]
 [0.09742808 0.08304427 0.07460099 0.04067177 0.626185   0.07806987]
 [0.20478569 0.12294924 0.12010485 0.13751231 0.36418733 0.05046057]
 [0.11872064 0.31072393 0.12530336 0.1552888  0.2132587  0.07670452]
 [0.01519807 0.09672114 0.1460476  0.00934331 0.5649092  0.16778067]
 [0.04199061 0.18141054 0.06647632 0.6006175  0.03198383 0.07752118]
 [0.09226219 0.2346089  0.13022321 0.16295874 0.05362028 0.3263266 ]
 [0.07019574 0.0861177  0.10912605 0.10521299 0.2152082  0.4141393 ]
 [0.01882887 0.26597694 0.19122466 0.24109262 0.14920162 0.13367532]]
pred: [0 4 4 4 1 4 3 5 5 1]
label: [0 2 3 4 2 4 2 3 5 5]
top-1-6 acc: [40.0, 40.0, 50.0, 70.0, 80.0, 100.0]

3.10 填充与复制

pad: 填充

tile:  复制

import tensorflow as tf
a=tf.constant([[1,2,3],[4,5,6],[7,8,9]])
print(a)

# 第一个维度的左边填充1个   右边不填充   第二个维度的左边填充一个  右边不填充
a1=tf.pad(a,[[1,0],[1,0]])
print(a1)
# 第一个维度的左边填充1个   右边填充1个   第二个维度的左边填充一个  右边填充一个
a2=tf.pad(a,[[1,1],[1,1]])
print(a2)



"""
tf.Tensor(
[[0 0 0 0]
 [0 1 2 3]
 [0 4 5 6]
 [0 7 8 9]], shape=(4, 4), dtype=int32)
tf.Tensor(
[[0 0 0 0 0]
 [0 1 2 3 0]
 [0 4 5 6 0]
 [0 7 8 9 0]
 [0 0 0 0 0]], shape=(5, 5), dtype=int32)
"""
#复制
b=a
print(b)
# 列复制为两倍  行不变
b1=tf.tile(b,[1,2])
print(b1)

b2=tf.tile(b,[2,2])
print(b2)

b3=tf.tile(b,[3,3])
print(b3)


""""
tf.Tensor(
[[1 2 3]
 [4 5 6]
 [7 8 9]], shape=(3, 3), dtype=int32)
tf.Tensor(
[[1 2 3 1 2 3]
 [4 5 6 4 5 6]
 [7 8 9 7 8 9]], shape=(3, 6), dtype=int32)
tf.Tensor(
[[1 2 3 1 2 3]
 [4 5 6 4 5 6]
 [7 8 9 7 8 9]
 [1 2 3 1 2 3]
 [4 5 6 4 5 6]
 [7 8 9 7 8 9]], shape=(6, 6), dtype=int32)
tf.Tensor(
[[1 2 3 1 2 3 1 2 3]
 [4 5 6 4 5 6 4 5 6]
 [7 8 9 7 8 9 7 8 9]
 [1 2 3 1 2 3 1 2 3]
 [4 5 6 4 5 6 4 5 6]
 [7 8 9 7 8 9 7 8 9]
 [1 2 3 1 2 3 1 2 3]
 [4 5 6 4 5 6 4 5 6]
 [7 8 9 7 8 9 7 8 9]], shape=(9, 9), dtype=int32)
"""

3.11 张量的限幅

tf.clip_by_value(a,x,y):a中小于x的用x代替  大于y的用y代替
tf.relu
tf.clip_by_global_norm: 整体呈比例的放缩
tf.gradients
a=tf.constant([0,1,2,3,4,4,5,6,7,8,9,9,9])
a1=tf.maximum(a,2)  # tensor 中值大于等于2的数据返回元数据  如果小于2  就将值返回为2
print(a1) # tf.Tensor([2 2 2 3 4 4 5 6 7 8 9 9 9], shape=(13,), dtype=int32)
a2=tf.minimum(a,8) # tensor中 值小于等于8的数据   如果大于8  就返回8
print(a2) # tf.Tensor([0 1 2 3 4 4 5 6 7 8 8 8 8], shape=(13,), dtype=int32)
a3=tf.clip_by_value(a,2,8) # tesnsor 中值大于2  小于8的数据  同上
print(a3)  #tf.Tensor([2 2 2 3 4 4 5 6 7 8 8 8 8], shape=(13,), dtype=int32)
# relu
a4=a-5
print(a4)
a5=tf.nn.relu(a4) # 将tensor中值小于0 的值用0代替
print(a5)

print("---------------------------------------------------------------------------------")
a=tf.random.normal([2,2],mean=10)
print(a)
print('a的二范数:',tf.norm(a))
aa=tf.clip_by_norm(a,15)
print("进行放缩以后:",aa)
print("aa的二范数",tf.norm(aa))
# a->aa这个过程中  方向不变只改变向量的模  即为了不改变向量的方向而缩小向量的模

#Gradient Exploding:一次步长太长
#Gradient vanishing:一次步长太短了

Gradient Exploding:一次步长太长
Gradient vanishing:一次步长太短了

例子:

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__)

(x, y), _ = datasets.mnist.load_data()
x = tf.convert_to_tensor(x, dtype=tf.float32) / 50.
y = tf.convert_to_tensor(y)
y = tf.one_hot(y, depth=10)
print('x:', x.shape, 'y:', y.shape)
train_db = tf.data.Dataset.from_tensor_slices((x, y)).batch(128).repeat(30)
x, y = next(iter(train_db))
print('sample:', x.shape, y.shape)


# print(x[0], y[0])


def main():
    # 784 => 512
    w1, b1 = tf.Variable(tf.random.truncated_normal([784, 512], stddev=0.1)), tf.Variable(tf.zeros([512]))
    # 512 => 256
    w2, b2 = tf.Variable(tf.random.truncated_normal([512, 256], stddev=0.1)), tf.Variable(tf.zeros([256]))
    # 256 => 10
    w3, b3 = tf.Variable(tf.random.truncated_normal([256, 10], stddev=0.1)), tf.Variable(tf.zeros([10]))

    optimizer = optimizers.SGD(lr=0.01)

    for step, (x, y) in enumerate(train_db):

        # [b, 28, 28] => [b, 784]
        x = tf.reshape(x, (-1, 784))

        with tf.GradientTape() as tape:

            # 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] => [b]
            loss = tf.reduce_mean(loss, axis=1)
            # [b] => scalar
            loss = tf.reduce_mean(loss)

        # compute gradient
        grads = tape.gradient(loss, [w1, b1, w2, b2, w3, b3])
        print('==before==')
        for g in grads:
            print(tf.norm(g))

        grads, _ = tf.clip_by_global_norm(grads, 15)

        print('==after==')
        for g in grads:
            print(tf.norm(g))
        # update w' = w - lr*grad
        optimizer.apply_gradients(zip(grads, [w1, b1, w2, b2, w3, b3]))

        if step % 100 == 0:
            print(step, 'loss:', float(loss))


if __name__ == '__main__':
    main()

3.12 高阶操作

where:根据目标进行选择

scatter_nd:根据目标进行更新

meshgrid:生成一个坐标系

# 找出a中大于0的值
a=tf.random.normal([3,3])
print("a:",a)
mask=a>0
print("mask:",mask)
result=tf.boolean_mask(a,mask)
print("result:",result)


"""
a: tf.Tensor(
[[-0.51451117  0.43534276 -1.365595  ]
 [ 0.59900445 -1.5556467  -0.60129905]
 [-1.2485702  -1.3679278  -2.025779  ]], shape=(3, 3), dtype=float32)
mask: tf.Tensor(
[[False  True False]
 [ True False False]
 [False False False]], shape=(3, 3), dtype=bool)
result: tf.Tensor([0.43534276 0.59900445], shape=(2,), dtype=float32)
"""
mask1=tf.where(mask) #得到值为true的坐标  where 中的参数只能是true和false
print("值为true的坐标为:",mask1)
result=tf.gather_nd(a,mask1)
print("result:",result)


""""
值为true的坐标为: tf.Tensor(
[[0 0]
 [0 1]
 [1 0]
 [1 1]
 [1 2]
 [2 0]
 [2 2]], shape=(7, 2), dtype=int64)
result: tf.Tensor(
[0.4553816  0.33047804 0.80143905 0.9520298  1.0377322  0.5832994
 1.2087549 ], shape=(7,), dtype=float32)
"""
# where 的第二种操作  where (mask,a,b):如果mask位置上的值为true就在a中取值 反之在b中取值
print(mask)
A=tf.ones([3,3])
B=tf.zeros([3,3])
c=tf.where(mask,A,B)


"""
tf.Tensor(
[[1. 1. 0.]
 [1. 1. 1.]
 [1. 0. 1.]], shape=(3, 3), dtype=float32)
"""
# 指定位置  修改为指定值
indices=tf.constant([[4],[3],[1],[2]])
updates=tf.constant([9,10,4,1])
shape=tf.constant([8])

result=tf.scatter_nd(indices,updates,shape)
print(result)

"""
tf.Tensor([ 0  4  1 10  9  0  0  0], shape=(8,), dtype=int32)
"""

 

import tensorflow as tf

import matplotlib.pyplot as plt


def func(x):
    """

    :param x: [b, 2]
    :return:
    """
    # [...,0]:取所有点的x部分   [...,1]:取所有点的y部分
    z = tf.math.sin(x[...,0]) + tf.math.sin(x[...,1])

    return z


x = tf.linspace(0., 2*3.14, 500)
y = tf.linspace(0., 2*3.14, 500)
# [50, 50]
point_x, point_y = tf.meshgrid(x, y)
# [50, 50, 2]
points = tf.stack([point_x, point_y], axis=2)
# points = tf.reshape(points, [-1, 2])
print('points:', points.shape)
z = func(points)
print('z:', z.shape)

plt.figure('plot 2d func value')
plt.imshow(z, origin='lower', interpolation='none')
plt.colorbar()

plt.figure('plot 2d func contour')
plt.contour(point_x, point_y, z)
plt.colorbar()
plt.show()

 

4. 数据集的加载 

keras.datasets

- tf.data.Dataset.from_tensor_slices
   
    ▪ shuffle 打乱
    ▪ map  转换
    ▪ batch 
    ▪ repeat  重复

数据集的准备:

例如:minist案例

 

 例如:cifar10/100

 然后上面得到的是一个numpy格式的数据

需要将该数据转换为tensor然后进行迭代

tf.data.Dataset   此类专门是为了抽象数据集迭代的
from_tensor_slices():

 

使用dataset的好处:

可以进行迭代、可以进行数据的预处理、支持多线程、可以拿到数据 也可以拿到数据的label

可以进行shuffle打散:避免数据太过规律   db.shuffle

可以进行数据预处理:

可以进行batch

但是在上面的操作中可能触发迭代(next)的 StopIteration,需要进行catch然后重新进行迭代

可以进行迭代.repeat()

import  os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import  tensorflow as tf
from    tensorflow import keras
from    tensorflow.keras import datasets


# x: [60k, 28, 28], [10, 28, 28]
# y: [60k], [10k]
(x, y), (x_test, y_test) = datasets.mnist.load_data()
# x: [0~255] => [0~1.]
x = tf.convert_to_tensor(x, dtype=tf.float32) / 255.
y = tf.convert_to_tensor(y, dtype=tf.int32)
x_test = tf.convert_to_tensor(x_test, dtype=tf.float32) / 255.
y_test = tf.convert_to_tensor(y_test, dtype=tf.int32)

print(x.shape, y.shape, x.dtype, y.dtype)
print(tf.reduce_min(x), tf.reduce_max(x))
print(tf.reduce_min(y), tf.reduce_max(y))


train_db = tf.data.Dataset.from_tensor_slices((x,y)).batch(128)
test_db = tf.data.Dataset.from_tensor_slices((x_test,y_test)).batch(128)
train_iter = iter(train_db)
sample = next(train_iter)
print('batch:', sample[0].shape, sample[1].shape)


# [b, 784] => [b, 256] => [b, 128] => [b, 10]
# [dim_in, dim_out], [dim_out]
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(100): # iterate db for 10
    for step, (x, y) in enumerate(train_db): # for every batch
        # x:[128, 28, 28]
        # y: [128]

        # [b, 28, 28] => [b, 28*28]
        x = tf.reshape(x, [-1, 28*28])

        with tf.GradientTape() as tape: # tf.Variable
            # x: [b, 28*28]
            # h1 = x@w1 + b1
            # [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]
            out = h2@w3 + b3

            # compute loss
            # out: [b, 10]
            # y: [b] => [b, 10]
            y_onehot = tf.one_hot(y, depth=10)

            # mse = mean(sum(y-out)^2)
            # [b, 10]
            loss = tf.square(y_onehot - out)
            # mean: scalar
            loss = tf.reduce_mean(loss)

        # compute gradients
        grads = tape.gradient(loss, [w1, b1, w2, b2, w3, b3])
        # print(grads)
        # 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(epoch, step, 'loss:', float(loss))


    # test/evluation
    # [w1, b1, w2, b2, w3, b3]
    total_correct, total_num = 0, 0
    for step, (x,y) in enumerate(test_db):

        # [b, 28, 28] => [b, 28*28]
        x = tf.reshape(x, [-1, 28*28])

        # [b, 784] => [b, 256] => [b, 128] => [b, 10]
        h1 = tf.nn.relu(x@w1 + b1)
        h2 = tf.nn.relu(h1@w2 + b2)
        out = h2@w3 +b3

        # out: [b, 10] ~ R
        # prob: [b, 10] ~ [0, 1]
        prob = tf.nn.softmax(out, axis=1)
        # [b, 10] => [b]
        # int64!!!
        pred = tf.argmax(prob, axis=1)
        pred = tf.cast(pred, dtype=tf.int32)
        # y: [b]
        # [b], int32
        # print(pred.dtype, y.dtype)
        correct = tf.cast(tf.equal(pred, y), dtype=tf.int32)
        correct = tf.reduce_sum(correct)

        total_correct += int(correct)
        total_num += x.shape[0]

    acc = total_correct / total_num
    print('test acc:', acc)

5.全连接层 

首先看一下之前的

三层的嵌套机构按照上面的计算方式:降维

 创建一层: 

创建多层全连接

import tensorflow as tf
from tensorflow import keras

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

model = keras.Sequential([
    keras.layers.Dense(2, activation='relu'),
    keras.layers.Dense(2, activation='relu'),
    keras.layers.Dense(2)
])
model.build(input_shape=[None, 3])
model.summary()

for p in model.trainable_variables:
    print(p.name, p.shape)

  6. 输出方式             

 sigmoid:

将整个向量整体进行压缩到[-1,1]

 但是 sigmod不支持分类问题,因为它产生的结果概率和不是1

7. 误差计算 

7.1 损失函数

- 均方差 MSE

- Cross Entropy Loss

- Hinge Loss

 MSE:

7.1.1 交叉熵 

熵越小 其中的信息也就越多,越不稳定

交叉熵:两个分布之间信息衡量的标准

 二分类问题:

单节点的:

 多号分类节点:

 计算多分类问题的交叉熵

 sigmoid+MSE:会出现gradient vanish即 梯度消失   就是 一开始和快要结束的时候  曲线几乎没有梯度 

交叉熵:

梯度下降就会很快,当然这也需要看实际应用场景。

  

 如果  from_logits设定为false 那么就需要下面进行prob的操作,当然这样是不推荐的,因为这样会使数据变得不稳定

8. 梯度下降

什么是梯度下降

梯度的方向,代表了函数增大的方向,梯度的模代表函数增大的速度

  举例:

 自动的更新参数:

8.1 一阶梯度下降

With Tf.GradientTape() as tape:

     将整个计算过程包裹在这个方法中

[w_grad] = tape.gradient(loss,[w]) ,就会返回w的梯度值,传入w1   w2   就返回w1  w2 的梯度值 

 实例:

8.2 二阶梯度下降

例子:

 

 9. 激活函数及梯度

科学家发现青蛙的神经元响应规律:

 自此 科学家从青蛙身上获得启示:

激活函数就是z>0   才可以对y有值

9.1 Sigmoid / Logistic 激活函数   

连续的光滑的,而且值在0--1之间      激活函数不可导,

 例子:

 9.2 Tanh 激活函数

Tanh 主要用于神经网络中

  

 

 主要是在 1--   -1 之间变动

9.3 Relu 激活函数

 z<0    g=0   

z>0    g变为线性结构

 10 Loss及其梯度

 

 10.1 均方差 MSE

 

举例: 

 

 

10.2 Cross Entropy Loss (主要用于分类问题中)

10.3 SoftMax (主要用于分类问题中)

 所有节点的概率都是0--1的   所有节点的概率和为1 

会把 原来分类中概率差距大的,处理成差距更大的,

会把原来分类中概率差距小的,处理成差距更小的,都压缩到一个更小的范围内

11. 链式法则

 链式法则:

 链式法则示例:

 

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值