tensorflow 基礎API

tensorflow 常量(constant)

創建常量

矩陣創建常量、常量定義類型、定義一個隨機數(標量)

t = tf.constant([[1.,2.,3.],[2.,3.,4.]])#矩陣創建常量
#設置類型爲int32
zero_vector = tf.zeros(shape=(2), dtype=tf.int32)


# 定義一個隨機數(標量)
random_float = tf.random.uniform(shape=())

定義一個有2個元素的零向量、定義兩個2×2的常量矩陣

# 定義一個有2個元素的零向量
zero_vector = tf.zeros(shape=(2))

# 定義兩個2×2的常量矩陣
A = tf.constant([[1., 2.], [3., 4.]])
B = tf.constant([[5., 6.], [7., 8.]])

0維張量、字符串張量

t = tf.constant(2.718)#0維張量

矩陣操作

舉例加法、平方、矩陣相乘、轉置

print(t+10)#加法
print(tf.square(t))#平方
print(t @ tf.transpose(t))#矩陣相乘,transpose是矩陣轉置

輸出矩陣信息

打印矩陣、打印範圍行、打印第幾行、用numpy輸出

print(t)#打印t
print(t[:,1:])#打印後兩行
print(t[...,1])#打印第幾行
print(t.numpy())#用numpy的方法輸出

輸出矩陣形狀、類型

print(t.shape)      #輸出張量形狀
print(A.dtype)      # 輸出類型

和numpy相互轉換

print(t.numpy())#用numpy的方法輸出
np_t = np.array([[1.,2.,3.],[4.,5.,6.]])#創建numpy數組
print(tf.constant(np_t))#將numpy轉成constant

字符串張量

創建字符串常量、打印字符串常量

t = tf.constant("cafe")#創建字符串常量
t = tf.constant(["cafe","coffee","咖啡"]) #字符串組成的數組
print(t)#打印字符串

獲得字符串長度、獲得在utf8編碼下的長度、將字符串從unicode轉換成utf-8

print(tf.strings.length(t))#獲得字符串長度
print(tf.strings.length(t, unit = "UTF8_CHAR"))#獲得在utf8編碼下的長度
print(tf.strings.unicode_decode(t,"UTF8"))#將字符串從unicode轉換成utf-8

不等長矩陣、不等長矩陣轉換成普通矩陣

# ragged tensor
r = tf.ragged.constant([[1.,2.],[2.,4.,5.],[],[41.]])#不等長矩陣
print(r.to_tensor())#不等長張量轉換成普通張量,缺失的地方用0補齊

矩陣拼接

print(tf.concat([r,r2],axis = 0))#縱向拼接
print(tf.concat([r,r2],axis = 1))#橫向拼接

創建稀疏矩陣

#sparse tensor
s = tf.SparseTensor(#創建稀疏矩陣
    indices = [[0,1],[1,0],[2,3]],#制定不是零的元素的座標
    values=[1.,2.,3.],#不是零的元素的值
    dense_shape = [3,4]#矩陣大小
)

將稀疏矩陣轉成密集矩陣、和密集矩陣相乘

s6 =tf.sparse.reorder(s) #針對稀疏矩陣未排好序的時候可以執行排序後在輸出
print(tf.sparse.to_dense(s6))

print(tf.sparse.to_dense(s))#講稀疏矩陣轉換成密集矩陣
print(tf.sparse.sparse_dense_matmul(s,s4))#和密集矩陣進行矩陣相乘

tensorflow 變量(Variable)

創建變量矩陣

v = tf.Variable([
    [1.,2.,3.],
    [4.,5.,6.]
])

打印變量矩陣、常量引用、numpy輸出

print(v)#打印變量矩陣
print(v.value())#打印變量的常量引用
print(v.numpy())#打印numpy形式的輸出

變量重賦值

v.assign(2*v)#變量重新賦值
v[0,1].assign(42)#對變量的某個位置賦值
v[1].assign([7.,8.,9.])#對一行進行賦值

自定義損失函數

#自定義損失函數
def customized_mse(y_true,y_pred): 
    return tf.reduce_mean(tf.square(y_pred - y_true)) 
#在下面loss直接等於這個函數就可以使用了

自定義層次(繼承)

# 自定義層
class  customizedDenseLayer(keras.layers.Layer):
    def __init__(selff,unit,actication = None,**kwargs):
        self.units = units
        self.activation = keras.layers.Activation(activation)
        super(CustomizedDenseLayer,self).__init__(**kwargs)
    def build (self,input_shape):
        """構建所需要的參數"""
        self.kernel = self.add_weight(
            name = 'kernel',#名字叫什麼
            shape = (input_shape[1],self.unis),#形狀是什麼樣的
            initializer = 'uniform',#初始化方式
            trainable = True#是否可訓練                     
        )
        self.bias = self.add_weight(
            name = 'bias',#名字叫什麼
            shape = (self.units,),#形狀是什麼樣的
            initializer = 'zeros',#初始化方式
            trainable = True#是否可訓練
        )
        super(customizedDenseLayer,self).build(input_shape)
    def call(self,x):
        """完成正向計算"""
        return self.activation(x @ self.kernel + self.bias)

自定義層次(lambda)

#用lambda實現定義層
customized_softplus = keras.layers.Lambda(lambda x : tf.nn.softplus(x))#傳入一個lambda表達式

打印層信息

打印layers所有參數、打印可訓練參數、查看layer的方法和參考

layer.variables#打印layer中的所有參數
layer.trainable_variables#獲得所有的可訓練的變量
help(layer)#查看layer的方法和參考

tf.function()

#tf.function and auto-graph
def scaled_elu(z,scale=1.0,alpha=1.0):
    is_positive = tf.greater_equal(z, 0.0)
    return scale * tf.where(is_positive, z, alpha * tf.nn.elu(z))
scaled_elu_tf = tf.function(scaled_elu)#用function方法將python函數轉換成tf圖結構

print(scaled_elu_tf.python_function is scaled_elu )#用python_function方法取得原來的python函數

@tf.function

@tf.function
def converge_to_2(n_iters):
    total = tf.constant(0.)
    increment = tf.constant(1.)
    for _ in range(n_iters):
        total +=increment
        increment /= 2.0
    return total
print(converge_to_2(20))


#tf.Variable不能定義在function裏
var = tf.Variable(0.)
@tf.function
def add_21():
    return var.assign_add(21) #+=
print(add_21())


#在正常的函數裏輸入什麼類型就會輸出什麼類型
@tf.function
def cube(z):
    return tf.pow(z, 3)
print(cube(tf.constant([1.,2.,3.])))
print(cube(tf.constant([1,2,3])))

簽名函數

@tf.function(input_signature = [tf.TensorSpec([None],#必須是tf類型
                                                                   tf.int32,#必須是什麼類型
                                                                   name = 'x')])#起了個名字
def cube(z):
    return tf.pow(z, 3)
print(cube(tf.constant([1.,2.,3.])))

展示@tf.function生成的tensorflow代碼

def display_tf_code(func):
    code = tf.autograph.to_code(func)
    from ipython.display import display, Markdown
    display(Markdown('```python\n{}\n```'.format(code)))
display_tf_code(scaled_elu)

轉換成圖結構

cube_func_int32 = cube.get_concrete_function(
    tf.TensorSpec([None],tf.int32)#None那個方塊裏填寫數字也可以
)
print(cube_func_int32)

轉換圖

cube_func_int32.graph

得到圖結構裏的所有操作

cube_func_int32.graph.get_operations()

打印圖結構裏的操作

pow_op = cube_func_int32.graph.get_operations()[2]
print(pow_op)

打印操作輸入輸出

print(list(pow_op.inputs))
print(list(pow_op.outputs))

通過名字獲取tenser

cube_func_int32.graph.get_tensor_by_name("z:0")#一般在名字後面加個:0

打印所有節點信息

cube_func_int32.graph.as_graph_def()

自動求導

import tensorflow as tf

x = tf.Variable(initial_value=3.)
with tf.GradientTape() as tape:     # 在 tf.GradientTape() 的上下文內,所有計算步驟都會被記錄以用於求導
    y = tf.square(x)
y_grad = tape.gradient(y, x)        # 計算y關於x的導數
print([y, y_grad])

自動求偏導

x1 = tf.Variable(2.0)
x2 = tf.Variable(3.0)
def g(x1,x2):
    return (x1+5) * (x2**2)
with tf.GradientTape(persistent=True) as tape:#persistent=True是保存結果tape可以多次調用false就只能調用一次
    z = g(x1,x2)
dz_x1 = tape.gradient(z,x1)#輸入(結果/哪個變量)獲取導數
dz_x2 = tape.gradient(z,x2)#輸入(結果/哪個變量)獲取導數
del tape
print(dz_x1)
print(dz_x2)

#或者
x1 = tf.Variable(2.0)
x2 = tf.Variable(3.0)
def g(x1,x2):
    return (x1+5) * (x2**2)
with tf.GradientTape(persistent=True) as tape:#persistent=True是保存結果tape可以多次調用false就只能調用一次
    z = g(x1,x2)
dz = tape.gradient(z,[x1,x2])#輸入(結果/哪個變量)獲取導數
del tape
print(dz)

自定義求偏導(常量模式)

#自定義求偏導(常量模式)
x1 = tf.constant(2.0)
x2 = tf.constant(3.0)
def g(x1,x2):
    return (x1+5) * (x2**2)
with tf.GradientTape(persistent=True) as tape:#persistent=True是保存結果tape可以多次調用false就只能調用一次
    tape.watch(x1)#對常量求導必須關注這個變量
    tape.watch(x2)#對常量求導必須關注這個變量
    z = g(x1,x2)
dz = tape.gradient(z,[x1,x2])#輸入(結果/哪個變量)獲取導數
del tape
print(dz)

多個目標函數對一個變量求導

x = tf.Variable(5.0)
with tf.GradientTape() as tape:#persistent=True是保存結果tape可以多次調用false就只能調用一次
    z1 = 3 *x
    z2 = x ** 2
dz = tape.gradient([z1,z2],x)#輸入(結果/哪個變量)獲取導數
print(dz)#輸出是變量對兩個函數的導數相加

二階求導

#求二階導數
x1 = tf.Variable(2.0)
x2 = tf.Variable(3.0)
def g(x1,x2):
    return (x1+5) * (x2**2)
with tf.GradientTape(persistent=True) as outer_tape:#persistent=True是保存結果tape可以多次調用false就只能調用一次
    with tf.GradientTape(persistent=True) as inner_tape:
        z = g(x1,x2)
    inner_grads = inner_tape.gradient(z,[x1,x2])#輸入(結果/哪個變量)獲取導數
outer_grads = [outer_tape.gradient(inner_grad,[x1,x2])
              for inner_grad in inner_grads]
del outer_tape,inner_tape
print(outer_grads)

模擬梯度下降

#模擬梯度下降
learning_rate = 0.1
x = tf.Variable(1.0)
def f (x):
    return x*x
for i in range(100):
    with tf.GradientTape() as tape:
        z = f(x)
    dz_dx = tape.gradient(z,x)
    x.assign_sub(learning_rate * dz_dx)
print(x)

keras優化器與求導結合實現梯度下降

#keras優化器與求導結合實現梯度下降
learning_rate = 0.1
x = tf.Variable(1.0)
def f (x):
    return x*x
optimizer = keras.optimizers.SGD(lr = learning_rate)#調用keras裏的模型優化器的方法
for i in range(100):
    with tf.GradientTape() as tape:
        z = f(x)
    dz_dx = tape.gradient(z,x)
    optimizer.apply_gradients([(dz_dx,x),])#傳入是個列表,麼個元素是個元組,元組中導數在前,變量在後
print(x)

線性迴歸


X = tf.constant(X)
y = tf.constant(y)

a = tf.Variable(initial_value=0.)
b = tf.Variable(initial_value=0.)
variables = [a, b]

num_epoch = 10000
optimizer = tf.keras.optimizers.SGD(learning_rate=1e-3)
for e in range(num_epoch):
    # 使用tf.GradientTape()記錄損失函數的梯度信息
    with tf.GradientTape() as tape:
        y_pred = a * X + b
        loss = 0.5 * tf.reduce_sum(tf.square(y_pred - y))
    # TensorFlow自動計算損失函數關於自變量(模型參數)的梯度
    grads = tape.gradient(loss, variables)
    # TensorFlow自動根據梯度更新參數
    optimizer.apply_gradients(grads_and_vars=zip(grads, variables))

print(a, b)

自定義fit函數

#自定義fit函數
epochs = 100#訓練多少輪
batch_size = 32#每一次訓練的數據量
steps_per_epoch = len(x_train_scaled) // batch_size#應該訓練多少次
optimizer = keras.optimizers.SGD()#定義優化器
metric = keras.metrics.MeanSquaredError()#定義損失函數

def random_batch(x,y,batch_size = 32):#定義取數據的方法
    idx = np.random.randint(0, len(x),size = batch_size)
    return x[idx] , y[idx]

model = keras.models.Sequential([#定義模型
    keras.layers.Dense(30, activation = 'relu',
                      input_shape= x_train.shape[1:]),
    keras.layers.Dense(1),
])

#訓練
for epoch in range(epochs):
    metric.reset_states()
    for step in range(steps_per_epoch):
        x_batch , y_batch = random_batch(x_train_scaled,y_train,  batch_size)
        with tf.GradientTape() as tape:
            y_pred = model(x_batch)
            loss = tf.reduce_mean(keras.losses.mean_squared_error(y_batch, y_pred))
            metric(y_batch, y_pred)
        grads = tape.gradient(loss , model.variables)
        grads_and_vars = zip(grads, model.variables)
        optimizer.apply_gradients(grads_and_vars)
        print("\rEpoch",epoch, "train mse:",metric.result().numpy(),end="")
    y_valid_pred = model(x_valid_scaled)
    valid_loss = tf.reduce_mean( keras.losses.mean_squared_error(y_valid_pred,y_valid))
    print("\t","valid mse:",valid_loss.numpy())
    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章