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]))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章