繁体   English   中英

如何从经过训练的多标签文本分类 model 中预测看不见的数据?

[英]How to predict unseen data from trained multi-label text classification model?

首先我想说我对机器学习完全陌生,并且仍在学习这些东西是如何工作的。 我正在将评论分类为多个标签,并通过参考此代码构建了一个多标签文本分类器。

model 被训练为将评论分类为 9 个标签,model 分别预测每个 label 的值。 到目前为止,我如何训练 model 以及如何测试 model 如下。 我没有包括文本处理部分,否则它将是一个冗长的代码。

这是 model 和这里使用的一样

#bert text model
class TEXT_MODEL(tf.keras.Model):

def __init__(self,
             vocabulary_size,
             embedding_dimensions=128,
             cnn_filters=50,
             dnn_units=512,
             model_output_classes=2,
             dropout_rate=0.1,
             training=False,
             name="text_model"):
    super(TEXT_MODEL, self).__init__(name=name)
    
    self.embedding = layers.Embedding(vocabulary_size,
                                      embedding_dimensions)
    self.cnn_layer1 = layers.Conv1D(filters=cnn_filters,
                                    kernel_size=2,
                                    padding="valid",
                                    activation="relu")
    self.cnn_layer2 = layers.Conv1D(filters=cnn_filters,
                                    kernel_size=3,
                                    padding="valid",
                                    activation="relu")
    self.cnn_layer3 = layers.Conv1D(filters=cnn_filters,
                                    kernel_size=4,
                                    padding="valid",
                                    activation="relu")          

    self.pool = layers.GlobalMaxPool1D()
    
    self.dense_1 = layers.Dense(units=dnn_units, activation="relu")
    self.dropout = layers.Dropout(rate=dropout_rate)
    if model_output_classes == 2:
        self.last_dense = layers.Dense(units=1,
                                       activation="sigmoid")
    else:
        self.last_dense = layers.Dense(units=model_output_classes,
                                       activation="softmax")

def call(self, inputs, training):
    l = self.embedding(inputs)
    l_1 = self.cnn_layer1(l) 
    l_1 = self.pool(l_1) 
    l_2 = self.cnn_layer2(l) 
    l_2 = self.pool(l_2)
    l_3 = self.cnn_layer3(l)
    l_3 = self.pool(l_3) 
    
    concatenated = tf.concat([l_1, l_2, l_3], axis=-1) # (batch_size, 3 * cnn_filters)
    concatenated = self.dense_1(concatenated)
    concatenated = self.dropout(concatenated, training)
    model_output = self.last_dense(concatenated)
    
    return model_output

这就是我将我的标记化评论传递到 model 并对其进行训练并最终对其进行测试的方式

    whole_predictions = []
    whole_real_predictions = []
    whole_threshold_predictions = []
    
    one=0
    #predict for each label individualy

for i in range(len(y_train[0])):
    print("\n" + str(i)+"\'th label prediction started")
    count_zero=0
    count_one=0
    new_label=[]
    new_tokenized_data_train=[]
    label = column(y_train,i)
    count_one=sum(label)
    print("count_one",count_one)
    
    for k in range(len(label)):
        if count_zero< count_one and label[k]==0:
            new_label.append(0)
            new_tokenized_data_train.append(X_train[k])
            count_zero=count_zero+1
        if label[k]==1:
            new_label.append(1)
            new_tokenized_data_train.append(X_train[k])

            
    print("count_zero",count_zero) 
    print()  
    data_with_len = [[value,new_label[j],len(value)]
                     for j,value in enumerate(new_tokenized_data_train)]


    data_with_len.sort(key=lambda x: x[2])
    sorted_data_labels = [(data_lab[0], data_lab[1]) for data_lab in data_with_len]
    processed_dataset = tf.data.Dataset.from_generator(lambda: sorted_data_labels, output_types=(tf.int32, tf.int32))
    BATCH_SIZE = 32
    batched_dataset = processed_dataset.padded_batch(BATCH_SIZE, padded_shapes=((None, ), ()))
    TOTAL_BATCHES = math.ceil(len(sorted_data_labels) / BATCH_SIZE)
    TEST_BATCHES = TOTAL_BATCHES // TOTAL_BATCHES
    batched_dataset.shuffle(TOTAL_BATCHES)
    test_data = batched_dataset.take(TEST_BATCHES)
    train_data = batched_dataset.skip(TEST_BATCHES)
    
   
    VOCAB_LENGTH = len(tokenizer.vocab)
    EMB_DIM = 260
    CNN_FILTERS = 50
    DNN_UNITS = 256
    OUTPUT_CLASSES = 2

    DROPOUT_RATE = 0.2

    NB_EPOCHS = 6

    text_model = TEXT_MODEL(vocabulary_size=VOCAB_LENGTH,
                        embedding_dimensions=EMB_DIM,
                        cnn_filters=CNN_FILTERS,
                        dnn_units=DNN_UNITS,
                        model_output_classes=OUTPUT_CLASSES,
                        dropout_rate=DROPOUT_RATE)

    if OUTPUT_CLASSES == 2:
        text_model.compile(loss="binary_crossentropy",
                           optimizer="adam",
                           metrics=["acc"])
    else:
        text_model.compile(loss="sparse_categorical_crossentropy",
                           optimizer="adam",
                           metrics=["sparse_categorical_acc"])

    text_model.fit(train_data, epochs=NB_EPOCHS)

    self_label_predictions = []
    self_threshold_predictions = []
    self_label_real_values = []
    print("Predicting " + str(i) + "th label...")
    
    for e,item in enumerate(X_test):
        if e%2==0:
            progress(e,len(X_test))
        res = text_model.predict([item])
        self_label_real_values.append(res[0][0])
      
        if res[0][0] > 0.93:
            self_threshold_predictions.append(res[0][0])
        else :
            self_threshold_predictions.append(0.0)

    whole_threshold_predictions.append(self_threshold_predictions)
    whole_real_predictions.append(self_label_real_values)

    
whole_threshold_predictions = list(map(list, zip(*whole_threshold_predictions)))
whole_real_predictions = list(map(list, zip(*whole_real_predictions)))

现在我需要使用这个Text_model来预测看不见的数据。 所以我研究了类似的案例,他们提到我需要保存和加载 model 并且在训练 model 时必须以类似的方式传递数据。 现在,我尝试了 go 与相同的 model 是 Text_model 和代码如下。

   user=pd.read_csv("Noodlesam.csv")
    user=user.dropna()
    user['Trimmed text'] = user['Trimmed text'].astype(str).apply(text_cleaner)
    input=user['Trimmed text'].tolist()

    def tokenized_input(data):
        return tokenizer.convert_tokens_to_ids(tokenizer.tokenize(data))

    tokenized_input = [tokenized_input(data) for data in input]
    print(len(tokenized_input))

    new_whole_threshold_predictions=[]
    new_whole_real_predictions=[]
    new_self_threshold_predictions = []
    new_self_label_real_values = []

      for q,item1 in enumerate(tokenized_input):
              if q%2==0:            
                  progress(q,len(tokenized_input))
              res = text_model.predict([item1])
              new_self_label_real_values.append(res[0][0])
            
              if res[0][0] > 0.93:
                  new_self_threshold_predictions.append(1.0)
              else :
                  new_self_threshold_predictions.append(0.0)

      new_whole_threshold_predictions.append(new_self_threshold_predictions)
      new_whole_real_predictions.append(new_self_label_real_values)

  new_whole_threshold_predictions = list(map(list, zip(*new_whole_threshold_predictions)))
  new_whole_real_predictions = list(map(list, zip(*new_whole_real_predictions)))

但这给了我 output 仅用于 9 个标签中的一个 label。 在前面的代码中我很理解,训练数据已经适合 model 内部for k in range(len(label)): loop 这意味着 9 次。 从这一点来看,我不明白这个 model 是如何工作的,我需要知道如何将这个 model 用于看不见的数据。

我认为这解释了我的问题,任何帮助将不胜感激

如果我理解正确的话。 您可以通过设置 model 的 output 和OUTPUT_CLASSES = 2来训练 model。 在此条件下,使其对 output 层使用 sigmoid。

if model_output_classes == 2:
    self.last_dense = layers.Dense(units=1,
                                   activation="sigmoid")
else:
    self.last_dense = layers.Dense(units=model_output_classes,
                                   activation="softmax")

这意味着您将仅获得一个 label,其概率范围为 0 到 1。您可以通过将此变量编辑为您的 label 的数量来解决此问题,以将 softmax 用于 Z78E6221F6393D1356681DB398F14CEDZ 层。 Softmax 会给你一个超过标签的概率。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM