参考链接:
https://blog.csdn.net/yeshang_lady/article/details/124615743?ops_request_misc=&request_id=&biz_id=102&utm_term=tensorflow%20%E5%BC%A0%E9%87%8F&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-5-124615743.142v52pc_rank_34_queryrelevant25,201v3add_ask&spm=1018.2226.3001.4187
import tensorflow as tf
import numpy as np
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 不显示等级2以下的提示信息,去掉tf一些烦人的输出
可以直接在tf.constant中写入数组来构建tensor,此时如果指定数据类型,就会按照指定的创建.如果不指定数据类型,会自动分配数据类型.
如果都是整数,那么dtype就是int型,如果有一个元素是浮点,那么dtype就是float型.
整形当中,默认最小的类型是int32,不会使用int16,除非额外特别指定.
int16: -32768~32767
int32:-2147483648~2147483647
int64:-9223372036854775808~9223372036854775807
单精度:float32:精确到小数点后6位,4个字节
双精度:float64:精确到小数点后15位,8个字节
tf.constant([1,2,3,4,5,6])
创建的变量类型都是EagerTensor
a = tf.constant([1,2,3,4,5,6])
type(a)
tensorflow.python.framework.ops.EagerTensor
可以通过.numpy()来访问数组
a.numpy()
array([1, 2, 3, 4, 5, 6], dtype=int32)
tf.constant([1,2,3,4,5,6],dtype=tf.int16)
tf.constant([1,2,3,4,5,6.1])
也可以先通过numpy创建数组a,然后通过tf.constant(a)创建tensor.
a = np.array([1,2,3,4,5,6])
tf.constant(a)
如果设定了shape,那么会对value进行reshape.
当value是一个常数时,会被复制填充shape
当value本身就是一个数组时,则要求元素数量必须和reshape后的数量一致,否则会报错.
tf.constant(1,shape=(2,3))
tf.constant([1,2,3,4,5,6],shape=(2,3))
另外,如果value是一个eager值,则没有影响,还可以计算梯度
v= tf.Variable([0.0])
u=tf.Variable([1.1])
with tf.GradientTape() as g:
loss = tf.constant(3*v+u) #等效于loss = 3*v + u
g.gradient(loss,v).numpy()
array([3.], dtype=float32)
但是如果value是一个符号张量,tf.constant(value)就会报错了.
所谓的符号张量可以理解为只是声明的为tf.graph,并没有实例化.只有在图流动时才进行实例化.
with tf.compat.v1.Graph().as_default():
i=tf.compat.v1.placeholder(shape=[None, None], dtype=tf.float32)
t=tf.constant(i)
(1)tf.convert_to_tensor()
也可以创建tensor,但是与tf.constant有两点不同
with tf.compat.v1.Graph().as_default():
i=tf.compat.v1.placeholder(shape=[None, None], dtype=tf.float32)
t=tf.convert_to_tensor(i)
(2)tf.fill()可以用于创建标量构成的tensor,但是与tf.constant有很大不同:
tf.fill([2,3],9.1)
这种创建出来的张量内元素值都是一样的.
tf.ones创建全1张量,tf.zeros创建全0张量
默认会采用tf.float32的变量类型存储
tf.ones([2,3],dtype=tf.int32)
tf.zeros([2,3])
当然,也可以使用1.1中的constant,fill,convert_to_tensor创建变量
tf.constant(0,shape=[2,3])
tf.fill((2,3),1)
a = np.zeros((2,3))
tf.convert_to_tensor(a)
都是通过tf.random函数进行构建
tf.random.uniform([1,5],minval=0,maxval=5)
tf.random.normal([2,2],mean=5,stddev=0.1)
创建一个连续的序列,和python自带的range函数基本一致
tf.range(1,10,2)
for i in range(1,10,2):
print(i)
1
3
5
7
9
前面可以知道,tf.constant创建的张量是不可优化的.而tf.variable建立的变量是可以优化的.
a = tf.constant([1,2,3])
b = tf.Variable([1,2,3])
c = tf.fill([1,2],0)
i = np.zeros((2,3))
d = tf.convert_to_tensor(i)
print(type(a))
print(type(b))
print(type(c))
print(type(d))
可见,只有 通过tf.Variable建立的变量才是可以用于模型训练的变量.并且tf.Variable变量有特有的属性:
print(b.name,b.trainable)
Variable:0 True
Tensorflow中有几个以initializer结尾的方法,这几个方法的使用有一些特殊,因为这些方法得到的并不是张量,而是一个可调用对象。下面以tf.random_uniform_initializer()为例进行说明。具体如下:
组合起来,就可以创建一些具有特殊分布的张量,例如下面就是创建了一个具有均匀分布的tensor变量
a = tf.random_uniform_initializer(minval=0,maxval=5) #产生均匀分布的函数
print(type(a))
print(callable(a))
True
tf.constant(a(shape=[2,3],dtype=tf.int32))
a = tf.random.uniform([2,3],0,10,dtype=tf.int32)
print(a)
b=tf.expand_dims(a,axis=0)
print(b)
c= tf.expand_dims(a,axis=1)
print(c)
d= tf.expand_dims(a,axis=2)
print(d)
tf.Tensor(
[[7 5 2]
[0 4 3]], shape=(2, 3), dtype=int32)
tf.Tensor(
[[[7 5 2]
[0 4 3]]], shape=(1, 2, 3), dtype=int32)
tf.Tensor(
[[[7 5 2]]
[[0 4 3]]], shape=(2, 1, 3), dtype=int32)
tf.Tensor(
[[[7]
[5]
[2]]
[[0]
[4]
[3]]], shape=(2, 3, 1), dtype=int32)
d = tf.squeeze(b)
print(d)
tf.Tensor(
[[7 5 2]
[0 4 3]], shape=(2, 3), dtype=int32)
上面的两种方法: tf.expand_dims和tf.squeeze都不会改变张量的存储顺序和大小,值是改变了理解方式.
tf.tile()
a = tf.constant([1,2,3,4])
b = tf.tile(a,multiples=[2])
print(b)
tf.Tensor([1 2 3 4 1 2 3 4], shape=(8,), dtype=int32)
a = tf.constant([1,2,3,4],shape=[2,2])
b = tf.tile(a,multiples=[2,2])
print(b)
tf.Tensor(
[[1 2 1 2]
[3 4 3 4]
[1 2 1 2]
[3 4 3 4]], shape=(4, 4), dtype=int32)
下面对a和b在axis=0的维度进行拼接
a = tf.random.uniform([2,3],1,10,dtype=tf.int32)
b= tf.random.uniform([1,3],1,10,dtype=tf.int32)
c = tf.concat([a,b],axis=0)
print(tf.shape(c))
print(c.shape)
tf.Tensor([3 3], shape=(2,), dtype=int32)
(3, 3)
a = tf.random.uniform([2,3],1,10,dtype=tf.int32)
b= tf.random.uniform([2,3],1,10,dtype=tf.int32)
c = tf.stack([a,b],axis=0)
print(a)
print(b)
print(c)
tf.Tensor(
[[3 8 7]
[9 8 6]], shape=(2, 3), dtype=int32)
tf.Tensor(
[[3 4 6]
[3 9 4]], shape=(2, 3), dtype=int32)
tf.Tensor(
[[[3 8 7]
[9 8 6]]
[[3 4 6]
[3 9 4]]], shape=(2, 2, 3), dtype=int32)
上述过程可以用expand_dim和concat来复现:
a = tf.expand_dims(a,axis=0)
b = tf.expand_dims(b,axis=0)
c = tf.concat([a,b],axis=0)
print(c)
tf.Tensor(
[[[3 8 7]
[9 8 6]]
[[3 4 6]
[3 9 4]]], shape=(2, 2, 3), dtype=int32)
张量分割就是张量合并的逆过程
a = tf.squeeze(a)
print(a)
tf.Tensor(
[[3 8 7]
[9 8 6]], shape=(2, 3), dtype=int32)
通过调整axis可以指定切片的维度.
a_split_1=tf.split(a,num_or_size_splits=[1,2],axis=1)
a_split_0=tf.split(a,num_or_size_splits=[1,1],axis=0)
print(a_split_1[0])
print(a_split_1[1])
print(a_split_0[0])
print(a_split_0[1])
tf.Tensor(
[[3]
[9]], shape=(2, 1), dtype=int32)
tf.Tensor(
[[8 7]
[8 6]], shape=(2, 2), dtype=int32)
tf.Tensor([[3 8 7]], shape=(1, 3), dtype=int32)
tf.Tensor([[9 8 6]], shape=(1, 3), dtype=int32)
同一个axis也可以有不同的切片方式,通过调整num_or_size_splits=[1,1,1],就可以把a张量切片成3分
a_split_1=tf.split(a,num_or_size_splits=[1,1,1],axis=1)
print(a_split_1[0])
print(a_split_1[1])
print(a_split_1[2])
tf.Tensor(
[[3]
[9]], shape=(2, 1), dtype=int32)
tf.Tensor(
[[8]
[8]], shape=(2, 1), dtype=int32)
tf.Tensor(
[[7]
[6]], shape=(2, 1), dtype=int32)