tensorflow定制模型和训练算法

发布时间:2023年12月19日

1.从自定义损失函数开始

这里先实现一个Lenet-5模型

input_data = keras.layers.Input(shape = (28,28,1))
conv_1 = keras.layers.Conv2D(filters=6, kernel_size=(5,5), strides=1, activation='relu', padding = 'same')(input_data)
pool_1 = keras.layers.AveragePooling2D(pool_size=(2,2), strides=2, padding='valid')(conv_1)
s1 = keras.layers.Normalization()(pool_1)

conv_2 = keras.layers.Conv2D(filters=16, kernel_size=(5,5),strides=1,activation='relu', padding = 'valid')(s1)
pool_2 = keras.layers.AveragePooling2D(pool_size=(2,2),strides=2, padding = 'valid')(conv_2)
s2 = keras.layers.Normalization()(pool_2)

conv_3 = keras.layers.Conv2D(filters=120, kernel_size = 5, strides=1, activation='relu', padding = 'valid')(s2)
flatten = keras.layers.Flatten()(conv_3)
dense = keras.layers.Dense(120, activation='relu')(flatten)
output = keras.layers.Dense(10, activation='softmax')(dense)
model = keras.Model(inputs = [input_data], outputs= [output])

checkPoint = ModelCheckpoint(filepath='model.h5', monitor='val_acc', verbose=1, save_best_only=True)
callback = [checkPoint]
model.compile(loss=’categorical_crossentropy', optimizer='sgd', metrics=['acc'])
hist = model.fit(x_train, y_train, batch_size=32, epochs=10, validation_split=0.3, callbacks=callback)

tensorflow构建模型有两种方法,一种是顺序式,一种是函数式,我用的是函数式。

神经网络架构:

输入28,28,1
卷积层15,5,6
平均池化层12,2
卷积层25,5,16
平均池化层22,2
卷积层35,5,120
全连接层184
输出层10

PS:中间隐藏层使用的是函数为tanh,末尾输出为softmax

我修改了激活函数,使用的是RELU,并在每一层输出后使用了归一化层.

依次为例,如果需要修改这个模型的组件,应该有哪些步骤呢?比如先修改一下损失函数,这里使用的是交叉熵。

修改为自己提供的损失函数。然后保存模型。应该怎么做?

先写出损失函数,考虑到批量梯度下降算法,应该是矩阵的算法

def My_loss(y_true, y_pred):
    error = 0.5 * tf.square(y_true, y_pred)
    return error

然后修改model.compile里面的loss参数

model.compile(loss=My_loss, optimizer='sgd', metrics=['acc'])

这样就能使用自己定义的组件了。

如果我想要修改0.5为0.1怎么办?

你可能会说,在函数里面修改一下不就得了嘛,但是我想保存模型的时候,把这个数字作为自定义的类型呢?

也就是当我们保存模型之后,再次加载模型,然后输入自己的参数。

2.保存和加载自定义的组件

每一个组件都有自己对应的父类,我们把自己的组件作为子类,然后继承父类,实现几个必要的函数就行了。然后使用字典进行初始化。这么说,肯定有点抽象,我们来做一件具体的事情

def My_loss(y_true, y_pred, r):
    error = r * tf.square(y_true, y_pred)
    return error

这里的r就是可变的,但是我们没办法使用到模型中,因为有三个参数,没办法灵活的定义r

model.compile(loss=My_loss(0.1), optimizer='sgd', metrics=['acc'])

你可能会想这么写

显然是错的,程序会崩溃。

解决办法是

def new_loss(r):
    def My_loss(y_true, y_pred):
        error = r * tf.square(y_true - y_pred)
        return error
    return My_loss

model.compile(loss=new_loss(0.1), optimizer='sgd', metrics=['acc'])

model.save_model('model.h5')

这样在保存的模型不会保存你之前设定的阈值,这里就必须自己设定了。

mymodel = keras.Models.load_model('model.h5', custum_objects={‘My_loss’:new_loss(0.1)})

如果想要保存下来,就必须用继承的方式

class NewLoss(keras.Losses.Loss):
    def __init__(self,r, *kwargs):
        self.r = r
        super().__self__(*kwargs)
    
    def call(self, y_true, y_y_pred):
        def myloss(y_true, y_pred):
        error = self.r * tf.square(y_true - y_pred)
        return error
    
    def get_config(self):
        base_config = super().get_config()
        return {**base_config, 'r' :self.r}

model = keras.models.load_model('model.h5', custom_objects={'NewLoss':NewLoss})

然后加载保存的模型 ,就不需要指定参数的大小

不仅仅是这样的损失函数可以保存,还可以自定义包括正则化,初始化,激活函数,层等等,方法与上面的损失一样。

3.建立自己的评价指标

??????? 评价指标有时候和损失函数混用,但是他们毕竟不是一个东西,我导师经常逼我用F1分数给神经网络调参,我真的好无语,如果我说损失函数必须可微才能执行梯度下降,她就会觉得我代码写错了,我最后只好说,啊对对对,我用的是f1分数调参。太痛了。总之,评价函数和损失函数是两个不一样的物种。

??????? keras.metrics里面有许多评价指标,精确度,召回率等等,在训练的时候,如果想要计算自己的指标,也可以按照上面提到的继承法来设置自己的指标。

class My_mertrics(keras.metrics.Metric):
    def __init__(self, r =0.5, **kwargs):
        super().__init__(**kwargs)
        self.r = r
        self.myloss = NewLoss(r)
        self.total = self.add_weight('total', initializer='zeros')
        self.count = self.add_weight('count', initializer='zeros')

    def update_state(self, y_true, y_pred, sample_weight = None):
        metric = self.myloss(y_true, y_pred)
        self.total.assign_add(tf.reduce_sum(metric))
        self.count.assign_add(tf.cast(tf.size(y_true), tf.float32))
    
    def result(self):
        return self.total / self.count
    
    def get_config(self):
        base_config = super().get_config()
        return {**base_config, "r":self.r}

update_state是在每个训练批次进行调用的函数,keras会自动跟踪数据,最后每次返回前面所积累的数据 。

model.compile(loss=new_loss(0.1), optimizer='sgd', metrics=[My_metrics(0.1)])

就会输出自定义的标准了。

文章来源:https://blog.csdn.net/weixin_42581560/article/details/135017071
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。