再談語言模型之應用

語言模型的形式

上文介紹的語言模型在效果上得到了非常好的效果,但是在生產環境速度偏慢,因此本文的目的有兩個,意識較輕量級的語言模型的實驗, 二是語言模型在下游任務中應用,語言模型本質上還是去發現語言文法中的潛在的關聯關係,應用該方法理論上在文本的語義方面判斷的任務會有很大幫助。

模型的應用 VAE

這裏展示的是VAE在文本生成過程中加入了,lm_loss用來輔助文本生成,關於VAE的一些東西就不在這展開了,有時間單獨更新吧。

loss 部分的代碼:(lm_loss 是在原有基礎上新加的loss)

xent_loss = K.sum(K.sparse_categorical_crossentropy(input_sentence, output), 1)
kl_loss = - 0.5 * K.sum(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1)

lm_loss_layer = LM_loss_layer(word_dic, inpit_pad,name="loss_lm")
lm_loss_layer.trainable = False
lm_loss = lm_loss_layer(output)

vae_loss = K.mean(xent_loss + kl_loss + lm_loss)

lm_loss自定義層的關鍵代碼

    def call(self, x, mask=None):
     
        data_shape = K.int_shape(x)
        pad_shape = K.int_shape(self.pad_data)
        word_len = data_shape[1]  # 詞序列的長度
        pad_len = pad_shape[1]

        pad_data = K.cast(self.pad_data, tf.int64)
        pad_data_onehot = K.one_hot(indices=pad_data, num_classes=data_shape[-1])

        lm_input = K.concatenate((pad_data_onehot, x), axis=1)

        lm_out = self.lm_model(lm_input)
        class_num = K.int_shape(lm_out)[-1]

        lm_out = K.reshape(x=lm_out, shape=(-1, word_len + pad_len, class_num))

        lm_out = K.max(lm_out, axis=-1) 

        res = -K.log(lm_out)

        res = K.sum(res)

        return res

實驗結果比較demo:
電腦熱的要死,有機會貼出個效果吧,理論上不會太好因爲基礎還是VAE的模型。
如果有實驗的朋友,也可以把權重加到loss上。
有效的前提還是有一個好的LM,不然loss降低反而不通順了。

模型的應用 NER

還有一個小的demo就是將語言模型應用到NER的任務中,之前對bert測試時發現效果不錯,只是生產上速度比較慢,所以想用一個輕便的LM來代替,並且該LM可以按照需求自定義訓練。這裏貼上一些代碼好了。

    def build_model(self):
        inpute_ = layers.Input((self.max_sentence_len,))
        #lm  embeding
        inpit_pad = layers.Input(shape=(self.ngram,))
        lm_embeding_layer = LM_embeding_layer()
        
        emb_lm = lm_embeding_layer([inpute_,inpit_pad])

        emb = layers.Embedding(input_dim=self.word_num, output_dim=128)(inpute_)  
        embedding_layer = layers.Concatenate(axis=-1)([emb, emb_lm])

        model1_in = layers.Conv1D(filters=self.CONV_SIZE, kernel_size=2, activation="relu", padding="same")(
            embedding_layer)
        model1_in = layers.MaxPooling1D(pool_size=2, strides=1, padding="same")(model1_in)

        model2_in = layers.Conv1D(self.CONV_SIZE, kernel_size=4, activation="relu", padding="same")(embedding_layer)
        model2_in = layers.MaxPooling1D(pool_size=2, strides=1, padding="same")(model2_in)

        model3_in = layers.Conv1D(self.CONV_SIZE, kernel_size=6, activation="relu", padding="same")(embedding_layer)
        model3_in = layers.AveragePooling1D(pool_size=2, strides=1, padding="same")(model3_in)

        merged = layers.concatenate([model1_in, model2_in, model3_in, embedding_layer], axis=-1)  # merge
        crf = CRF(self.class_num, sparse_target=False)
        crf_res = crf(merged)
        model = Model([inpute_, inpit_pad], crf_res)

        adam = Adam(lr=0.001)
        model.compile(optimizer=adam, loss=crf.loss_function, metrics=[crf.accuracy])
        print(model.summary())
        return model

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