龙曲良 Tensorflow —— tensorflow基础操作(自用)-1

目录

一、数据类型概念

1.1 相关类型

1.2 tf.constant(数据创建和判断)

1.3 tf.cast、tf.convert_to_tensor(类型转换)

1.4 tf.Variable

1.5 转换成 Numpy

二、创建 Tensor

2.1 From Numpy , List 

2.2 tf.zeros , tf.ones,Fill

2.3 随机化创建

2.3.1 tf.random.normal(分布初始化采样)

2.3.2 tf.random.uniform(均匀采样)

2.3.3 tf.random.shuffle(数据打散)

2.3.4 tf.constant

2.4 各种 shape 的 Tensor

2.4.1 Scalar(标量)

2.4.2 Vector(向量)

2.4.3 Matrix(矩阵)

2.4.4 Dim = 3 Tensor

2.4.5 Dim = 4 Tensor(图片)

2.4.6 Dim = 5 Tensor

三、索引与切片

3.1 单个索引 [idx][idx][idx]

3.2 单个索引 [idx, idx, idx] 

3.3 范围索引  [A : B) 和 [ : ]

3.4 间断索引(双冒号,即 : :)

3.5 三个点  . . .

3.6 selective indexing

3.6.1 tf.gather

3.6.2 tf.gather_nd 

3.6.3 tf.boolean_mask

四、维度变换

4.1 View概念

4.2 tf.reshape

4.3 tf.transpose

4.4 增加、减少维度( Expend dim 和 Squeeze dim )

4.4.1 tf.expend_dims

4.4.2 tf.squeeze

五、Broadcasting(张量维度扩张)

5.1 tf.broadcast_to

5.2 tf.tile

六、数学运算

6.1 加减乘除(+,-,*,/,%,//)

6.2 tf.math.log , tf.exp

6.3 平方,开方(pow,sqrt) 

6.4 矩阵相乘(@ matmul)

七、前向传播实战使用

7.1 代码


一、数据类型概念

1.1 相关类型

numpy 不支持 gpu 

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第1张图片

scalar:数学上讲一个零位的数据,如 1.1,2,3,就是一个准确的数据类型

实际上都可以叫做 tensor

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第2张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第3张图片

1.2 tf.constant(数据创建和判断)

当创建一个 2.2,却指定 int 类型的话就会报错

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第4张图片

cpu 和 gpu 上tensor 的区别就是,对于cpu上的只能cpu操作,gpu的只能gpu操作

ndim 显示的是 维度

name 参数是没有什么意义的

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第5张图片

判断是不是tensor 用 isinstance is_tensor

判断类型也可以如:a.dtype ==  tf.float32

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第6张图片

1.3 tf.cast、tf.convert_to_tensor(类型转换)

numpy的类型 和 tensor 也可以转换

还有 cast 转换函数

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第7张图片

整形和布尔型转换

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第8张图片

1.4 tf.Variable

如 y = wx + b

x,y 都是 tensor类型;而 w 和 b 都是需要被梯度优化的参数,所以他们除了是 tensor 类型以外,还有一个 Variable 属性

相当于把 原本的tensor类型的 w 用 w = tf.Variable(w) 包一下,这样 w 就自动具备一个可求导特性

如下的 w 就具有了 name 和 trainbale(即可训练的意思) 两个属性

但用 isinstance 显示 false,is_tensor 显示 true,所以 isinstance 不推荐使用

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第9张图片

1.5 转换成 Numpy

.numpy() ,或者可以直接如 int(b),float(b)

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第10张图片

二、创建 Tensor

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第11张图片

2.1 From Numpy , List 

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第12张图片

2.2 tf.zeros , tf.ones,Fill

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第13张图片

tf.zeros_like(a) 根据传过来的 shape 建立全 0 的, 等同于tf.zeros(a.shape) 

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第14张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第15张图片

2.3 随机化创建

2.3.1 tf.random.normal(分布初始化采样)

mean:均值 , stddev:方差

truncated_normal:是个截断的,截断部分区间

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第16张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第17张图片

2.3.2 tf.random.uniform(均匀采样)

均匀采样

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第18张图片

2.3.3 tf.random.shuffle(数据打散)

可用于有对应关系的

gather 对有对应关系的数据进行打乱

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第19张图片

2.3.4 tf.constant

tf.constant(1):创建一个标量

tf.constant([1]):创建一个向量龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第20张图片

2.4 各种 shape 的 Tensor

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第21张图片

2.4.1 Scalar(标量)

类似 loss 、 accuracy  

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第22张图片

2.4.2 Vector(向量)

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第23张图片

kernel 是 w,初始化是随机的

bias 是 b,初始化是 0

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第24张图片

2.4.3 Matrix(矩阵)

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第25张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第26张图片

2.4.4 Dim = 3 Tensor

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第27张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第28张图片

2.4.5 Dim = 4 Tensor(图片)

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第29张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第30张图片

2.4.6 Dim = 5 Tensor

如,有 4 个任务,每个人物 64 张图片,每个图片 28 × 28 ×1

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第31张图片

三、索引与切片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第32张图片

3.1 单个索引 [idx][idx][idx]

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第33张图片

3.2 单个索引 [idx, idx, idx] 

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第34张图片

3.3 范围索引  [A : B) 和 [ : ]

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第35张图片

[ : ] :表示取所有维度

如下 a[0] 相当于 a[0, :, :, :]龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第36张图片

3.4 间断索引(双冒号,即 : :)

(1)范围隔行用法     ::

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第37张图片

(2)逆序     :: -1 / -2

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第38张图片

3.5 三个点  . . .

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第39张图片

3.6 selective indexing

        如下,[4, 28, 28, 3],低于第一个28,我们不直接从A到B取索引,而是单独取其中的第3,27,9,13行,这就是切片indices,就用到了gather的功能,这里是取了4行,gather也就是收集的意思

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第40张图片

3.6.1 tf.gather

假设有4个班级,每个班级35个学生,每个学生8门课程

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第41张图片

axis 给出了要取哪个维度

indices 给出了 索引号

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第42张图片

3.6.2 tf.gather_nd 

        如果要获得 多少个学生的多少个学科的成绩,那么该如何实现?

        比如要得到,4个班级 7个学生 3门课的成绩,首先可以通过 两个gather 串联实现

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第43张图片

        但如果 要取第2个学生的第0门课,第3个学生的第4门课,第8个学生的第2门课这种,用两个gather的方法就无法实现

        如下 4个班级的4个学生的成绩,就有 [4, 8] 个数据,相当于是在多个维度,指定了index,gather是在某一个维度

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第44张图片

        如下,tf.gather_nd(a, [0]) 表示在 [ [ ]  [ ]  [ ] ] 取第一个维度 [0] 的全部,所以是 [35, 8],返回的是维度

        最后的 tf.gather_nd(a, [ [0, 1, 2] ]) 输出的是 成绩的一个具体值,标量,所以是1

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第45张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第46张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第47张图片

3.6.3 tf.boolean_mask

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第48张图片

四、维度变换

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第49张图片

4.1 View概念

        了解view 的概念,如下的 view1和 view2,view1 是有一个长和宽的概念,而view2 则是把这个图片当成一个整体,view2不关注图片的具体二维信息,而是直接把图片的 rgb 的数据拿过来使用;view3 把图片分成了上下两部分;view4 只是多了一个 channel;这些view对图片原来的content内容没有改变

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第50张图片

4.2 tf.reshape

        -1  是自动计算,使得满足原来尺寸

        784*3  是数据点的总数量

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第51张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第52张图片

        如上,reshape 操作非常灵活,提供很多的可能性,但有没有具体的含义要具体来看

       但也可能带来潜在的问题,即把图片从 [4,28,28,3] 变成 [4,784,3] 后再变回  [4,28,28,3] 时,这是就需要原来图片 content 的信息 ,如下所示,把 height 和 width 维度记错 或 记混了

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第53张图片

        上述都是在改变 view, 那么如何改变 content 呢?如将 h,w交换,或把 c 提到前面,这就用到一个函数:tf.transpose

4.3 tf.transpose

        与矩阵的转置类似,不设置参数就是全部转置,可以设置参数规定新的维度是什么,所以每一次的 view 必须跟踪相应的 content

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第54张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第55张图片

4.4 增加、减少维度( Expend dim 和 Squeeze dim )

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第56张图片

4.4.1 tf.expend_dims

        如下,要增加一个 school 的维度

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第57张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第58张图片

4.4.2 tf.squeeze

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第59张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第60张图片

五、Broadcasting(张量维度扩张)

        指对某一个维度重复多次,但是没有真正的复制一个数据

        如下 [b, 10] + [10] 得到的是 [b, 10] 的,但不能直接相加,要把 [10] 转换成一个 [b, 10] 的tensor,这个过程就是 broadcasting

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第61张图片

broadcasting操作流程:

        如果 a,b 的 tensor 的 维度 dimension 不一致,如 [4,16,16,32] 和 [32] 相加,首先要把小维度对齐,左边大右边小,往前延伸插入维度,再把每个维度对齐,把1扩张为4,16

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第62张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第63张图片

那么 broadcasting 到底代表什么意义?

       如假设要把英语和物理都加分,英语加5,物理加10,此时是小维度scores,此时创建出班级学生的维度[1,1,8] 在扩张

       而下一种情况是对学生0的成绩都加5分,就是把每个班级前两个学生的每个科目都加5分         

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第64张图片

broadcasting的好处?

(1)写起来更加简洁

(2)节省更多内存

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第65张图片

节省了 2^7 个字节数

什么是能够broadcasting的?

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第66张图片

如下情形: 

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第67张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第68张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第69张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第70张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第71张图片

5.1 tf.broadcast_to

        也可以通过调用 tf.broadcast_to 来完成维度的扩张,不调用就是自动完成

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第72张图片

5.2 tf.tile

        tf.tile(a2, [2,1,1]) 把0维复制2次,1,2维复制1次就是没变,得到shape=(2,3,4)

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第73张图片

a1和a2 在共用上面是等价的,但a2占用内存更大,a1实际上的内存区域是没有扩张复制的

     

六、数学运算

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第74张图片

操作类型:

        (1)对某个具体的元素

        (2)对矩阵类型

        (3)对某个维度,某个轴

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第75张图片

6.1 加减乘除(+,-,*,/,%,//)

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第76张图片

6.2 tf.math.log , tf.exp

        tf.math.log 是 loge ,即 ln,没有log2,log10之类的

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第77张图片

        所以 log2 要变一下得到,根据 log_a^b / log_a^c = log_c^b

        即 ln8 / ln2 = log_2^8 = 3

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第78张图片

6.3 平方,开方(pow,sqrt) 

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第79张图片

6.4 矩阵相乘(@ matmul)

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第80张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第81张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第82张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第83张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第84张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第85张图片

七、前向传播实战使用

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第86张图片

龙曲良 Tensorflow —— tensorflow基础操作(自用)-1_第87张图片

        如何屏蔽这些无用的信息呢?

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

        0是全打印,2是只打印error的信息,这些信息是CPP打印出来的

7.1 代码

具体原理已省略

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import datasets
import os

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


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

print('tensorflow版本号:', tf.__version__)
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)
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]
# stddev = 0.1 方差变为0.1
w1 = tf.Variable(tf.random.truncated_normal([784, 256], stddev=0.1))  # truncated_normal 创建一个正态分布的
b1 = tf.Variable(tf.zeros([256]))
w2 = tf.Variable(tf.random.truncated_normal([256, 128], stddev=0.1))  # truncated_normal 创建一个正态分布的
b2 = tf.Variable(tf.zeros([128]))
w3 = tf.Variable(tf.random.truncated_normal([128, 10], stddev=0.1))  # truncated_normal 创建一个正态分布的
b3 = tf.Variable(tf.zeros([10]))

lr = 1e-3  # 0.001 = 10^-3

for epoch in range(10): # iterate db for 10 对整个数据集迭代10次
    for step, (x,y) in enumerate(train_db): # for every batch对数据集每个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 类型,所以在上面 w,b 的前面加上 tf.Variable
                                         # 这两个类型是一样的,只是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 = x@w1 + b1
            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)  # 只需在 loss 计算之前 onehot 就行

            # 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])
        # 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])
        # 此时出现 loss:nan 梯度爆炸的情况,要在w,b初始化时,给一个范围,stddev = 0.1

        # w1 = w1 - lr * grads[0] # 对 w1 的求导结果,此时计算返回的是 tf.Tensor 类型,不是 tf.Variable 类型了
        #                         # 所以要进行原地更新的操作,使用 w1.assign_sub(lr * grads[0]),使引用保持不变
        # b1 = w1 - lr * grads[1]
        # w2 = w2 - lr * grads[2]
        # b2 = b2 - lr * grads[3]
        # w3 = w3 - lr * grads[4]
        # b3 = b3 - lr * grads[5]

        if step % 100 == 0:
            print(epoch, step, 'loss:', float(loss))  # 美100次打印一次

你可能感兴趣的:(Tensorflow,tensorflow,numpy,python)