tensorflow自定義結構初步

0.摘要

對輸入值x,標籤y,模型參數c,我們希望習得一個最優的Model-c滿足y=Model(x,c)。機器學習的任務就是要確定這個Model中的參數。但是因爲Model的形狀(如層數,節點個數等)是離散的,處理起來相對麻煩,所以我們在這裏只討論可導的參數c(tensorflow的一個優勢就在於可以自動求導)。我們希望對於一個確定確定的模型Model,我們要找到這樣的c滿足c=argmin(loss),其中loss表示損失函數,如loss=sum(square(y-Model(x,c)))。我們算到這一步之後,可以再根據loss對各參數的偏導用梯度下降法更新梯度,也就是我們的學習過程,更新所用的對象爲optimizer。

簡而言之,訓練分爲如下幾步:

1.y_pred=Model(x,c)
2.L=loss(y_pred,y)
3.g=optimizer(DL/Dc)
4.c=c-g

在下文中,Section1介紹瞭如何準備測試數據(傻瓜下載法);Section2,3介紹瞭如何構造一個訓練用的Model。這個Model,就是我們在tensorflow中直接用於訓練的對象。在深度學習中,這個Model就是神經網絡,而神經網絡又由許多層狀結構組成,這就是我們構造過程中的次級對象layer;Section4介紹瞭如何構造一個Optimizer;Section5是訓練的過程;Section6則是數據評估。

Talk is cheap,先從引入必要的庫開始。

#引入庫,開啓eager模式
import tensorflow as tf
import numpy as np
tf.enable_eager_execution()

1.數據準備

__init__ __call__
下載名爲mnist的數據庫,並且分出4塊 從訓練集中隨機抽取batch_size個訓練數據
class DataLoader():
    def __init__(self):
        mnist=tf.contrib.learn.datasets.load_dataset("mnist")
        self.train_data=mnist.train.images
        self.train_label=np.asarray(mnist.train.labels,dtype=np.int32)
        self.eval_data = mnist.test.images
        self.eval_labels = np.asarray(mnist.test.labels, dtype=np.int32)
    def __call__(self,batch_size):
        index=np.random.randint(np.shape(self.train_data)[0],size=batch_size)
        return self.train_data[index,:],self.train_label[index]

2.自定義層

__init__ __call__
構造一個確定輸入輸入的全連接層,並生成對應初始數據 用該層對輸入值X進行計算並返回計算值
class FullConnectedLayer(tf.keras.layers.Layer):
    def __init__(self,input_num,output_num):
        super().__init__()
        self.output_num=output_num
        self.input_num=input_num
        self.w=self.add_variable(name='w',shape=[self.input_num,self.output_num],initializer=tf.random_uniform_initializer(minval=0.,maxval=0.1))
        self.b=self.add_variable(name='b',shape=[1,self.output_num],initializer=tf.random_uniform_initializer(minval=0.,maxval=0.1))
    def __call__(self,X):
        y_pred=tf.nn.sigmoid(tf.matmul(X,self.w)+self.b)
        return y_pred

3.自定義模型

__init__ __call__ predict
繼承父類,構造複合層結構 用各層計算輸入值input,返回預測值 利用argmax函數得到對應數據的標籤
class MLP(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.dense1=tf.keras.layers.Dense(100,activation=tf.nn.relu)
        self.dense2=tf.keras.layers.Dense(10)
    def __call__(self,input):
        x=self.dense1(input)
        x=self.dense2(x)
        return x
    def predict(self,input):
        logits=self(input)
        return tf.argmax(logits,axis=-1)

4.自定義優化器

翻來覆去就那麼幾個,正常情況下直接用api就可以了。特殊情況?你除了用Adam和偶爾用上幾次SGD之外還用得着啥?實在不行徒手寫一個就行了。其實是懶得寫了。

5.訓練

#1 #2 #3
定義超參數 實例化模型,數據,優化器 用tf.GradientTape()函數自動求導,optimizer和model訓練
#1
epoch=1000
batch_size=32
eta=0.003
#2
mlp=MLP()
data_loader=DataLoader()
optimizer=tf.train.AdamOptimizer(learning_rate=eta)
#3
for i in range(epoch):
    X,y=data_loader(batch_size)
    with tf.GradientTape() as tape:
        y_pred=mlp(tf.convert_to_tensor(X))
        L=tf.losses.sparse_softmax_cross_entropy(labels=y,logits=y_pred)
    g=tape.gradient(L,mlp.variables)
    optimizer.apply_gradients(grads_and_vars=zip(g,mlp.variables))

6.評估

y_pred=mlp.predict(data_loader.eval_data).numpy()
print("acc:%f"%(sum(y_pred==data_loader.eval_labels)/np.shape(data_loader.eval_labels)[0]))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章