0%

Python数据科学_22_Tensorflow2(低阶API)

1
2
import tensorflow as tf
import numpy as np
1
2
# 查看tensorflow2的版本,注意双下划线
tf.__version__
'2.9.1'
1
2
# 查看电脑GPU是否可用   cuda  cudnn
tf.test.is_gpu_available()
False

低阶API

张量的创建

创建常量

1
2
# 创建标量
tf1 = tf.constant(1.0)
1
2
# 使用python内置的print函数进行输出,会打印出张量的数值、尺寸、数据类型
print(tf1)
tf.Tensor(1.0, shape=(), dtype=float32)
1
2
# 使用tf.print可以只将张量的数值打印出来
tf.print(tf1)
1
1
2
3
# 创建一维张量
tf2 = tf.constant([1, 2, 3])
tf.print(tf2)
[1 2 3]
1
2
3
# 创建二维张量
tf3 = tf.constant([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], dtype=tf.float64)
tf.print(tf3)
[[1 2 3 4]
 [5 6 7 8]
 [9 10 11 12]]

创建变量

1
2
tv1 = tf.Variable([[11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34]])
tf.print(tv1)
[[11 12 13 14]
 [21 22 23 24]
 [31 32 33 34]]
1
2
3
4
5
# 数组修改值
array1 = np.array([[11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34]])
print('修改前:', array1)
array1[2, 2] = 333
print('修改后:', array1)
修改前: [[11 12 13 14]
 [21 22 23 24]
 [31 32 33 34]]
修改后: [[ 11  12  13  14]
 [ 21  22  23  24]
 [ 31  32 333  34]]
1
2
3
4
5
6
# 修改张量的值
print('修改前:')
tf.print(tv1)
tv1[2, 2] = 333 # tensorflow中对变量不允许这样直接修改
print('修改后:')
tf.print(tv1)
修改前:
[[11 12 13 14]
 [21 22 23 24]
 [31 32 33 34]]



---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

Cell In [29], line 4
      2 print('修改前:')
      3 tf.print(tv1)
----> 4 tv1[2, 2] = 333
      5 print('修改后:')
      6 tf.print(tv1)


TypeError: 'ResourceVariable' object does not support item assignment
1
2
3
4
5
6
# 修改张量的值,普通赋值
print('修改前:')
tf.print(tv1)
tv1[2, 2].assign(333) # 要想修改指定索引位置上的元素,需要使用assign方法
print('修改后:')
tf.print(tv1)
修改前:
[[11 12 13 14]
 [21 22 23 24]
 [31 32 33 34]]
修改后:
[[11 12 13 14]
 [21 22 23 24]
 [31 32 333 34]]
1
2
3
4
5
6
7
8
# 重新赋值和修改值的区别
tff = tf.Variable([[1, 2, 3], [3, 4, 5], [5, 6, 7]])
tf.print(tff)
print(id(tff))
# 重新赋值
tff = tf.Variable([[1, 2, 33], [3, 4, 5], [5, 6, 7]])
tf.print(tff)
print(id(tff))
[[1 2 3]
 [3 4 5]
 [5 6 7]]
2346999659680
[[1 2 33]
 [3 4 5]
 [5 6 7]]
2346999659776
1
2
3
4
5
6
7
8
# 重新赋值和修改值的区别
tff = tf.Variable([[1, 2, 3], [3, 4, 5], [5, 6, 7]])
tf.print(tff)
print(id(tff))
# 值的修改
tff[0, 2].assign(33)
tf.print(tff)
print(id(tff))
[[1 2 3]
 [3 4 5]
 [5 6 7]]
2346999620512
[[1 2 33]
 [3 4 5]
 [5 6 7]]
2346999620512
1
2
3
4
5
6
# 修改张量的值,自加运算
print('修改前:')
tf.print(tv1)
tv1.assign_add(tv1) # tv1 = tv1 + tv1
print('修改后:')
tf.print(tv1)
修改前:
[[11 12 13 14]
 [21 22 23 24]
 [31 32 333 34]]
修改后:
[[22 24 26 28]
 [42 44 46 48]
 [62 64 666 68]]
1
2
3
4
5
6
# 修改张量的值,自减运算
print('修改前:')
tf.print(tv1)
tv1.assign_sub(tv1) # tv1 = tv1 - tv1
print('修改后:')
tf.print(tv1)
修改前:
[[22 24 26 28]
 [42 44 46 48]
 [62 64 666 68]]
修改后:
[[0 0 0 0]
 [0 0 0 0]
 [0 0 0 0]]

创建全零张量

1
2
tz1 = tf.zeros([3, 3])
tf.print(tz1)
[[0 0 0]
 [0 0 0]
 [0 0 0]]
1
tf.print(tf.zeros_like(tv1))
[[0 0 0 0]
 [0 0 0 0]
 [0 0 0 0]]

创建全1张量

1
2
to1 = tf.ones([3, 3])
tf.print(to1)
[[1 1 1]
 [1 1 1]
 [1 1 1]]
1
tf.print(tf.ones_like(tv1))
[[1 1 1 1]
 [1 1 1 1]
 [1 1 1 1]]

创建均匀分布的随机张量

1
2
3
4
5
6
# shape: 生成张量的尺寸
# minval: 生成张量的最小值
# maxval: 生成张量的最大值
# dtype: 生成张量的数据类型
tu1 = tf.random.uniform(shape=(3, 3), minval=5, maxval=10, dtype=tf.int64)
tf.print(tu1)
[[5 5 8]
 [5 6 9]
 [9 7 9]]
1
2
tf.random.set_seed(123)  # 设置随机种子数
tf.print(tf.random.normal(shape=(3,3)))
[[-0.898083687 -1.82591438 -0.444418073]
 [-1.48829472 -0.785546303 0.196196556]
 [0.17604655 -1.52525055 0.635294]]

创建连续张量

1
2
3
4
5
# tf.range()
# start: 起点
# limit: 终点
# delta: 步长
tf.print(tf.range(start=0, limit=10, delta=2))
[0 2 4 6 8]
1
2
# tf.linspace()
tf.print(tf.linspace(0, 10, 11))
[0 1 2 ... 8 9 10]

张量的索引和切片

1
2
3
tf.random.set_seed(1234)
tu2 = tf.random.uniform((5, 5), minval=5, maxval=100, dtype=tf.int64)
tf.print(tu2)
[[95 51 41 12 23]
 [27 53 83 46 93]
 [20 21 52 19 22]
 [96 33 84 44 43]
 [62 75 23 31 88]]

索引

1
2
# 取出44
tf.print(tu2[3, 3])
44
1
2
3
# 批量取出指定位置上的元素
index = [[3, 3], [4, 4]]
tf.print(tf.gather_nd(tu2, index))
[44 88]

切片

1
tf.print(tu2[2:4, 2:])
[[52 19 22]
 [84 44 43]]
1
tf.print(tu2)
[[95 51 41 12 23]
 [27 53 83 46 93]
 [20 21 52 19 22]
 [96 33 84 44 43]
 [62 75 23 31 88]]
1
2
3
4
# input_: 待切片的张量
# begin: [开始的行索引,开始的列索引]
# size: [取出的行数,取出的列数]
tf.print(tf.slice(input_=tu2, begin=[2, 2], size=[2, 3]))
[[52 19 22]
 [84 44 43]]

取出指定的行和指定的列

1
tf.print(tu2[:, 2])
[41 83 52 84 23]
1
tf.print(tf.gather(tu2, [2, 4, 1], axis=1))
[[41 23 51]
 [83 93 53]
 [52 22 21]
 [84 43 33]
 [23 88 75]]

维度变换

1
tu3 = tf.random.uniform((1, 3, 4), minval=5, maxval=10, dtype=tf.int64)
1
2
3
# tf.reshape()   修改尺寸,但是需要保证数据的大小不变
tu4 = tf.reshape(tu3, shape=(4, 3))
tf.print(tu4)
[[5 6 5]
 [6 9 8]
 [8 5 8]
 [8 6 7]]
1
2
# tf.squeeze()   删除尺寸为1的位置
tf.print(tf.squeeze(tu3).shape)
TensorShape([3, 4])
1
2
# tf.expend_dims()   增加尺寸为1的位置
tf.print(tf.expand_dims(tu3, -1).shape)
TensorShape([1, 3, 4, 1])
1
2
# tf.transpose()    张量的转置
tf.print(tf.transpose(tu4))
[[5 6 8 8]
 [6 9 5 6]
 [5 8 8 7]]

张量的合并和分割

1
2
3
tf.random.set_seed(1234)
tf1 = tf.random.uniform((4, 4), minval=5, maxval=100, dtype=tf.int64)
tf2 = tf.random.uniform((4, 4), minval=5, maxval=100, dtype=tf.int64)
1
2
tf.print(tf1)
tf.print(tf2)
[[95 51 41 12]
 [23 27 53 83]
 [46 93 20 21]
 [52 19 22 96]]
[[80 66 45 36]
 [94 58 18 70]
 [63 83 76 22]
 [62 60 89 15]]

横向合并

1
2
tf.print(tf.concat([tf1, tf2], axis=1))
tf.concat([tf1, tf2], axis=1).shape
[[95 51 41 ... 66 45 36]
 [23 27 53 ... 58 18 70]
 [46 93 20 ... 83 76 22]
 [52 19 22 ... 60 89 15]]





TensorShape([4, 8])

纵向合并

1
2
tf.print(tf.concat([tf1, tf2], axis=0))
tf.concat([tf1, tf2], axis=0).shape
[[95 51 41 12]
 [23 27 53 83]
 [46 93 20 21]
 ...
 [94 58 18 70]
 [63 83 76 22]
 [62 60 89 15]]





TensorShape([8, 4])

横向分割

1
tf.print(tf.split(tf1, 2, axis=0))
[[[95 51 41 12]
 [23 27 53 83]], [[46 93 20 21]
 [52 19 22 96]]]

纵向分割

1
tf.print(tf.split(tf1, 2, axis=1))
[[[95 51]
 [23 27]
 [46 93]
 [52 19]], [[41 12]
 [53 83]
 [20 21]
 [22 96]]]

张量的计算

1
2
tf.print(tf1)
tf.print(tf2)
[[95 51 41 12]
 [23 27 53 83]
 [46 93 20 21]
 [52 19 22 96]]
[[80 66 45 36]
 [94 58 18 70]
 [63 83 76 22]
 [62 60 89 15]]
1
2
# 张量计算的基本方式为对应元素相运算
tf.print(tf1 + tf2)
[[175 117 86 48]
 [117 85 71 153]
 [109 176 96 43]
 [114 79 111 111]]
1
2
3
# 在运算时必须保证一个前提,做运算的两个张量的数据类型必须一致
print('tf1:', tf1.dtype)
print('tf2:', tf2.dtype)
tf1: <dtype: 'int64'>
tf2: <dtype: 'int64'>
1
2
3
# 修改张量的数据类型
tf3 = tf.cast(tf1, tf.float32)
print('tf3:', tf3.dtypeype)
tf3: <dtype: 'float32'>
1
2
# 张量的数据类型不一致,无法运算
tf2 + tf3
---------------------------------------------------------------------------

InvalidArgumentError                      Traceback (most recent call last)

Cell In [32], line 1
----> 1 tf2 + tf3


File D:\Users\Python\Anaconda3.8\envs\tf_new\lib\site-packages\tensorflow\python\util\traceback_utils.py:153, in filter_traceback.<locals>.error_handler(*args, **kwargs)
    151 except Exception as e:
    152   filtered_tb = _process_traceback_frames(e.__traceback__)
--> 153   raise e.with_traceback(filtered_tb) from None
    154 finally:
    155   del filtered_tb


File D:\Users\Python\Anaconda3.8\envs\tf_new\lib\site-packages\tensorflow\python\framework\ops.py:7164, in raise_from_not_ok_status(e, name)
   7162 def raise_from_not_ok_status(e, name):
   7163   e.message += (" name: " + name if name is not None else "")
-> 7164   raise core._status_to_exception(e) from None


InvalidArgumentError: cannot compute AddV2 as input #1(zero-based) was expected to be a int64 tensor but is a float tensor [Op:AddV2]
1
2
tf4 = tf.cast(tf2, dtype=tf.float64)
print(tf4.dtype)
<dtype: 'float64'>
1
tf3 + tf4
---------------------------------------------------------------------------

InvalidArgumentError                      Traceback (most recent call last)

Cell In [34], line 1
----> 1 tf3 + tf4


File D:\Users\Python\Anaconda3.8\envs\tf_new\lib\site-packages\tensorflow\python\util\traceback_utils.py:153, in filter_traceback.<locals>.error_handler(*args, **kwargs)
    151 except Exception as e:
    152   filtered_tb = _process_traceback_frames(e.__traceback__)
--> 153   raise e.with_traceback(filtered_tb) from None
    154 finally:
    155   del filtered_tb


File D:\Users\Python\Anaconda3.8\envs\tf_new\lib\site-packages\tensorflow\python\framework\ops.py:7164, in raise_from_not_ok_status(e, name)
   7162 def raise_from_not_ok_status(e, name):
   7163   e.message += (" name: " + name if name is not None else "")
-> 7164   raise core._status_to_exception(e) from None


InvalidArgumentError: cannot compute AddV2 as input #1(zero-based) was expected to be a float tensor but is a double tensor [Op:AddV2]

tensorflow中的自微分机制

  • 函数为

一阶导数

1
2
3
4
5
6
7
8
# 默认的张量精度为单精度浮点型(tf.float32)
x = tf.Variable(1.0, dtype=tf.float32)
a = tf.constant(1.0)
b = tf.constant(-2.0)
c = tf.constant(1.0)
# 一阶导数
with tf.GradientTape() as tape:
y = a * tf.pow(x, 2) + b*x + c
1
2
dy_dx = tape.gradient(y, x)
tf.print(dy_dx)
0

二阶导数

1
2
3
4
5
# 二阶导数
with tf.GradientTape() as tape0:
with tf.GradientTape() as tape:
y = a * tf.pow(x, 2) + b*x + c
dy_dx = tape.gradient(y, x)
1
2
dy2_dx2 = tape0.gradient(dy_dx, x)
tf.print(dy2_dx2)
2

使用tensorflow对一元线性回归分析进行参数优化

数据下载

1
2
3
# skiprows: 表示要丢弃的行数
# delimiter: 分隔符
data = np.loadtxt('line_fit_data.csv', skiprows=1, delimiter=',')
1
2
3
# 分离特征和标签
x_data = tf.constant(data[:, 0], dtype=tf.float32)
y_data = tf.constant(data[:, 1], dtype=tf.float32)
1
2
3
# 参数初始化
params = tf.Variable(tf.random.normal(shape=(2,)))
params
<tf.Variable 'Variable:0' shape=(2,) dtype=float32, numpy=array([-0.16868056,  1.0764664 ], dtype=float32)>
1
2
3
# Python中定义元组,如果元组中只有单个数据,那么在定义的过程中必须在数据后加上一个逗号。
a = (2)
b = (2,)
1
2
print(type(a))
print(type(b))
<class 'int'>
<class 'tuple'>
1
2
3
4
# yita:学习率
yita = 0.5
# 最大迭代次数
epochs = 100
1
2
3
# 定义模型函数
def line_model(x, w, b):
return x*w + b
1
2
3
# 定义损失函数
def loss(y_true, y_pred):
return 1/2 * tf.pow(y_true - y_pred, 2)
1
2
3
4
5
6
7
8
9
10
11
12
13
for epoch in range(epochs):
for i in range(len(x_data)):
# 取出一条样本
x = x_data[i]
y = y_data[i]
# 使用自微分机制计算梯度
with tf.GradientTape() as grad:
y_pred = line_model(x, params[0], params[1])
error = loss(y, y_pred)
d_params = grad.gradient(error, params)
# 利用梯度进行参数更新
params.assign_sub(d_params * yita)
print('epoch:{}, w:{}, b:{}, error:{}'.format(epoch, params.numpy()[0], params.value()[1], error))
epoch:0, w:2.4750444889068604, b:4.005576133728027, error:2.3561007765238173e-05
epoch:1, w:2.498833656311035, b:4.000260353088379, error:5.149206572241383e-08
epoch:2, w:2.4999454021453857, b:4.000012397766113, error:1.1641532182693481e-10
epoch:3, w:2.49999737739563, b:4.000000953674316, error:1.1368683772161603e-13
epoch:4, w:2.499999761581421, b:4.0, error:0.0
epoch:5, w:2.499999761581421, b:4.0, error:0.0
epoch:6, w:2.499999761581421, b:4.0, error:0.0
epoch:7, w:2.499999761581421, b:4.0, error:0.0
epoch:8, w:2.499999761581421, b:4.0, error:0.0
epoch:9, w:2.499999761581421, b:4.0, error:0.0
epoch:10, w:2.499999761581421, b:4.0, error:0.0
epoch:11, w:2.499999761581421, b:4.0, error:0.0
epoch:12, w:2.499999761581421, b:4.0, error:0.0
epoch:13, w:2.499999761581421, b:4.0, error:0.0
epoch:14, w:2.499999761581421, b:4.0, error:0.0
epoch:15, w:2.499999761581421, b:4.0, error:0.0
epoch:16, w:2.499999761581421, b:4.0, error:0.0
epoch:17, w:2.499999761581421, b:4.0, error:0.0
epoch:18, w:2.499999761581421, b:4.0, error:0.0
epoch:19, w:2.499999761581421, b:4.0, error:0.0
epoch:20, w:2.499999761581421, b:4.0, error:0.0
epoch:21, w:2.499999761581421, b:4.0, error:0.0
epoch:22, w:2.499999761581421, b:4.0, error:0.0
epoch:23, w:2.499999761581421, b:4.0, error:0.0
epoch:24, w:2.499999761581421, b:4.0, error:0.0
epoch:25, w:2.499999761581421, b:4.0, error:0.0
epoch:26, w:2.499999761581421, b:4.0, error:0.0
epoch:27, w:2.499999761581421, b:4.0, error:0.0
epoch:28, w:2.499999761581421, b:4.0, error:0.0
epoch:29, w:2.499999761581421, b:4.0, error:0.0
epoch:30, w:2.499999761581421, b:4.0, error:0.0
epoch:31, w:2.499999761581421, b:4.0, error:0.0
epoch:32, w:2.499999761581421, b:4.0, error:0.0
epoch:33, w:2.499999761581421, b:4.0, error:0.0
epoch:34, w:2.499999761581421, b:4.0, error:0.0
epoch:35, w:2.499999761581421, b:4.0, error:0.0
epoch:36, w:2.499999761581421, b:4.0, error:0.0
epoch:37, w:2.499999761581421, b:4.0, error:0.0
epoch:38, w:2.499999761581421, b:4.0, error:0.0
epoch:39, w:2.499999761581421, b:4.0, error:0.0
epoch:40, w:2.499999761581421, b:4.0, error:0.0
epoch:41, w:2.499999761581421, b:4.0, error:0.0
epoch:42, w:2.499999761581421, b:4.0, error:0.0
epoch:43, w:2.499999761581421, b:4.0, error:0.0
epoch:44, w:2.499999761581421, b:4.0, error:0.0
epoch:45, w:2.499999761581421, b:4.0, error:0.0
epoch:46, w:2.499999761581421, b:4.0, error:0.0
epoch:47, w:2.499999761581421, b:4.0, error:0.0
epoch:48, w:2.499999761581421, b:4.0, error:0.0
epoch:49, w:2.499999761581421, b:4.0, error:0.0
epoch:50, w:2.499999761581421, b:4.0, error:0.0
epoch:51, w:2.499999761581421, b:4.0, error:0.0
epoch:52, w:2.499999761581421, b:4.0, error:0.0
epoch:53, w:2.499999761581421, b:4.0, error:0.0
epoch:54, w:2.499999761581421, b:4.0, error:0.0
epoch:55, w:2.499999761581421, b:4.0, error:0.0
epoch:56, w:2.499999761581421, b:4.0, error:0.0
epoch:57, w:2.499999761581421, b:4.0, error:0.0
epoch:58, w:2.499999761581421, b:4.0, error:0.0
epoch:59, w:2.499999761581421, b:4.0, error:0.0
epoch:60, w:2.499999761581421, b:4.0, error:0.0
epoch:61, w:2.499999761581421, b:4.0, error:0.0
epoch:62, w:2.499999761581421, b:4.0, error:0.0
epoch:63, w:2.499999761581421, b:4.0, error:0.0
epoch:64, w:2.499999761581421, b:4.0, error:0.0
epoch:65, w:2.499999761581421, b:4.0, error:0.0
epoch:66, w:2.499999761581421, b:4.0, error:0.0
epoch:67, w:2.499999761581421, b:4.0, error:0.0
epoch:68, w:2.499999761581421, b:4.0, error:0.0
epoch:69, w:2.499999761581421, b:4.0, error:0.0
epoch:70, w:2.499999761581421, b:4.0, error:0.0
epoch:71, w:2.499999761581421, b:4.0, error:0.0
epoch:72, w:2.499999761581421, b:4.0, error:0.0
epoch:73, w:2.499999761581421, b:4.0, error:0.0
epoch:74, w:2.499999761581421, b:4.0, error:0.0
epoch:75, w:2.499999761581421, b:4.0, error:0.0
epoch:76, w:2.499999761581421, b:4.0, error:0.0
epoch:77, w:2.499999761581421, b:4.0, error:0.0
epoch:78, w:2.499999761581421, b:4.0, error:0.0
epoch:79, w:2.499999761581421, b:4.0, error:0.0
epoch:80, w:2.499999761581421, b:4.0, error:0.0
epoch:81, w:2.499999761581421, b:4.0, error:0.0
epoch:82, w:2.499999761581421, b:4.0, error:0.0
epoch:83, w:2.499999761581421, b:4.0, error:0.0
epoch:84, w:2.499999761581421, b:4.0, error:0.0
epoch:85, w:2.499999761581421, b:4.0, error:0.0
epoch:86, w:2.499999761581421, b:4.0, error:0.0
epoch:87, w:2.499999761581421, b:4.0, error:0.0
epoch:88, w:2.499999761581421, b:4.0, error:0.0
epoch:89, w:2.499999761581421, b:4.0, error:0.0
epoch:90, w:2.499999761581421, b:4.0, error:0.0
epoch:91, w:2.499999761581421, b:4.0, error:0.0
epoch:92, w:2.499999761581421, b:4.0, error:0.0
epoch:93, w:2.499999761581421, b:4.0, error:0.0
epoch:94, w:2.499999761581421, b:4.0, error:0.0
epoch:95, w:2.499999761581421, b:4.0, error:0.0
epoch:96, w:2.499999761581421, b:4.0, error:0.0
epoch:97, w:2.499999761581421, b:4.0, error:0.0
epoch:98, w:2.499999761581421, b:4.0, error:0.0
epoch:99, w:2.499999761581421, b:4.0, error:0.0

张量和数组间的相互转化

1
array2 = np.array([5, 7, 9, 2])

数组转化为张量

1
2
array2tensor = tf.constant(array2)
array2tensor
<tf.Tensor: shape=(4,), dtype=int32, numpy=array([5, 7, 9, 2])>
1
2
array2tensor2 =  tf.Variable(array2)
array2tensor2
<tf.Variable 'Variable:0' shape=(4,) dtype=int32, numpy=array([5, 7, 9, 2])>

张量转化为数组

1
2
tensor2array = array2tensor.numpy()
tensor2array
array([5, 7, 9, 2])
1
2
tensor2array2 = np.array(array2tensor2)
tensor2array2
array([5, 7, 9, 2])
-------------本文结束感谢您的阅读-------------