首頁>技術>

應用於自然語言處理的機器學習資料通常包含文字和數字輸入。例如,當您透過twitter或新聞構建一個模型來預測產品未來的銷售時,在考慮文字的同時考慮過去的銷售資料、訪問者數量、市場趨勢等將會更有效。您不會僅僅根據新聞情緒來預測股價的波動,而是會利用它來補充基於經濟指標和歷史價格的模型。 這篇文章展示瞭如何在scikit-learn(對於Tfidf)和pytorch(對於LSTM / BERT)中組合文字輸入和數字輸入。

scikit-learn(例如用於Tfidf)

當你有一個包含數字欄位和文字的訓練dataframe ,並應用一個來自scikit-lean或其他等價的簡單模型時,最簡單的方法之一是使用sklearn.pipeline的FeatureUnion管道。

下面的示例假定X_train是一個dataframe ,它由許多數字欄位和最後一列的文字欄位組成。然後,您可以建立一個FunctionTransformer來分隔數字列和文字列。傳遞給這個FunctionTransformer的函式可以是任何東西,因此請根據輸入資料修改它。這裡它只返回最後一列作為文字特性,其餘的作為數字特性。然後在文字上應用Tfidf向量化並輸入分類器。該樣本使用RandomForest作為估計器,並使用GridSearchCV在給定引數中搜索最佳模型,但它可以是其他任何引數。

import numpy as npfrom sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.pipeline import Pipeline, FeatureUnionfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.preprocessing import FunctionTransformerfrom sklearn.model_selection import GridSearchCV, StratifiedKFold# Create Function Transformer to use Feature Uniondef get_numeric_data(x):    return [record[:-2].astype(float) for record in x]def get_text_data(x):    return [record[-1] for record in x]transfomer_numeric = FunctionTransformer(get_numeric_data)transformer_text = FunctionTransformer(get_text_data)# Create a pipeline to concatenate Tfidf Vector and Numeric data# Use RandomForestClassifier as an examplepipeline = Pipeline([    ('features', FeatureUnion([            ('numeric_features', Pipeline([                ('selector', transfomer_numeric)            ])),             ('text_features', Pipeline([                ('selector', transformer_text),                ('vec', TfidfVectorizer(analyzer='word'))            ]))         ])),    ('clf', RandomForestClassifier())])# Grid Search Parameters for RandomForestparam_grid = {'clf__n_estimators': np.linspace(1, 100, 10, dtype=int),              'clf__min_samples_split': [3, 10],              'clf__min_samples_leaf': [3],              'clf__max_features': [7],              'clf__max_depth': [None],              'clf__criterion': ['gini'],              'clf__bootstrap': [False]}# Training configkfold = StratifiedKFold(n_splits=7)scoring = {'Accuracy': 'accuracy', 'F1': 'f1_macro'}refit = 'F1'# Perform GridSearchrf_model = GridSearchCV(pipeline, param_grid=param_grid, cv=kfold, scoring=scoring,                          refit=refit, n_jobs=-1, return_train_score=True, verbose=1)rf_model.fit(X_train, Y_train)rf_best = rf_model.best_estimator_

Scikit-learn提供了很好的api來管理ML管道,它只完成工作,還可以以同樣的方式執行更復雜的步驟。

Pytorch(例如LSTM, BERT)

如果您應用深度神經網路,更常見的是使用Tensorflow/Keras或Pytorch來定義層。兩者都有類似的api,並且可以以相同的方式組合文字和數字輸入,下面的示例使用pytorch。

要在神經網路中處理文字,首先它應該以模型所期望的方式嵌入。有一個dropout 層也是常見的,以避免過擬合。該模型在與數字特徵連線之前新增一個稠密層(即全連線層),以平衡特徵的數量。最後,應用稠密層輸出所需的輸出數量。

class LSTMTextClassifier(nn.Module):  def __init__(self, vocab_size, embed_size, lstm_size, dense_size, numeric_feature_size, output_size, lstm_layers=1, dropout=0.1):        super().__init__()        self.vocab_size = vocab_size        self.embed_size = embed_size        self.lstm_size = lstm_size        self.output_size = output_size        self.lstm_layers = lstm_layers        self.dropout = dropout        self.embedding = nn.Embedding(vocab_size, embed_size)        self.lstm = nn.LSTM(embed_size, lstm_size, lstm_layers, dropout=dropout, batch_first=False)        self.dropout = nn.Dropout(0.2)        self.fc1 = nn.Linear(lstm_size, dense_size)        self.fc2 = nn.Linear(dense_size + numeric_feature_size, output_size)        self.softmax = nn.LogSoftmax(dim=1)    def init_hidden(self, batch_size):        weight = next(self.parameters()).data        hidden = (weight.new(self.lstm_layers, batch_size, self.lstm_size).zero_(),                  weight.new(self.lstm_layers, batch_size, self.lstm_size).zero_())                return hidden    def forward(self, nn_input_text, nn_input_meta, hidden_state):        batch_size = nn_input_text.size(0)        nn_input_text = nn_input_text.long()        embeds = self.embedding(nn_input_text)        lstm_out, hidden_state = self.lstm(embeds, hidden_state)        lstm_out = lstm_out[-1,:,:]        lstm_out = self.dropout(lstm_out)        dense_out = self.fc1(lstm_out)        concat_layer = torch.cat((dense_out, nn_input_meta.float()), 1)        out = self.fc2(concat_layer)        logps = self.softmax(out)        return logps, hidden_state      class BertTextClassifier(nn.Module):    def __init__(self, hidden_size, dense_size, numeric_feature_size, output_size, dropout=0.1):        super().__init__()        self.output_size = output_size        self.dropout = dropout                # Use pre-trained BERT model        self.bert = BertModel.from_pretrained('bert-base-uncased', output_hidden_states=True, output_attentions=True)        for param in self.bert.parameters():            param.requires_grad = True        self.weights = nn.Parameter(torch.rand(13, 1))        self.dropout = nn.Dropout(dropout)        self.fc1 = nn.Linear(hidden_size, dense_size)        self.fc2 = nn.Linear(dense_size + numeric_feature_size, output_size)        self.softmax = nn.LogSoftmax(dim=1)    def forward(self, input_ids, nn_input_meta):                all_hidden_states, all_attentions = self.bert(input_ids)[-2:]        batch_size = input_ids.shape[0]        ht_cls = torch.cat(all_hidden_states)[:, :1, :].view(13, batch_size, 1, 768)        atten = torch.sum(ht_cls * self.weights.view(13, 1, 1, 1), dim=[1, 3])        atten = F.softmax(atten.view(-1), dim=0)        feature = torch.sum(ht_cls * atten.view(13, 1, 1, 1), dim=[0, 2])        dense_out = self.fc1(self.dropout(feature))        concat_layer = torch.cat((dense_out, nn_input_meta.float()), 1)        out = self.fc2(concat_layer)        logps = self.softmax(out)        return logps

以上程式碼在前向傳播時使用torch.cat將數字特徵和文字特徵進行組合,並輸入到後續的分類器中進行處理。

43
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 立即呼叫函式表示式(IIFE)介紹及使用講解