2017-09-17 61 views
1

我正在使用scikit-learn建立一個分類器,預測兩個句子是否爲釋義(例如:解釋:愛因斯坦與什麼是阿爾伯特愛因斯坦的長度有多高)。如何解決Scikit用Numpy數組學習預處理流水線錯誤?

我的數據包含2個字符串(短語對)列和1個目標列,0和1(=無釋義,釋義)。我想嘗試不同的算法。

我期待下面的最後一行代碼適合模型。相反,預處理Pipeline會產生一個我無法解決的錯誤:「AttributeError:'numpy.ndarray'對象沒有'lower'屬性。」

代碼如下,我已隔離出現在最後一行顯示的錯誤(爲簡潔起見,我排除了其餘部分)。我懷疑這是因爲目標列包含0和1,不能轉爲小寫。

我已經嘗試了類似的問題在stackoverflow的答案,但沒有運氣到目前爲止。

你如何解決這個問題?

question1    question2      is_paraphrase 
How long was Einstein? How tall was Albert Einstein? 1 
Does society place too How do sports contribute to the 0 
much importance on  society? 
sports?     
What is a narcissistic What is narcissistic personality 1 
personality disorder? disorder? 

======

from sklearn.pipeline import Pipeline 
from sklearn.feature_extraction.text import CountVectorizer 
from sklearn.feature_extraction.text import TfidfTransformer 
from sklearn.naive_bayes import MultinomialNB 
from sklearn.model_selection import train_test_split 
import pandas as pd 
import numpy as np 

para = "paraphrases.tsv" 

df = pd.read_csv(para, usecols = [3, 5], nrows = 100, header=0, sep="\t") 

y = df["is_paraphrase"].values 
X = df.drop("is_paraphrase", axis=1).values 
X = X.astype(str) # I have tried this 
X = np.char.lower(X) 

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, 
random_state = 21, stratify = y) 

text_clf = Pipeline([('vect', CountVectorizer()),('tfidf', TfidfTransformer()), 
('clf', MultinomialNB())]) 

text_clf.fit(X_train, y_train) 
+0

你能後的1個或2行的樣本數據集? –

+0

謝謝。我已經在問題中添加了一些示例數據。 – twhale

+0

你的火車數據集包含兩列嗎? 'question1'和'question2'? –

回答

0

這個錯誤是因爲最後一列的不是,那是因爲你的火車xdataset將包含兩列question1question2。現在這會導致你X_train每行都作爲值列表。因此,當CountVectorizer試圖將其轉換爲小寫字母時,它會返回一個錯誤,因爲numpy.ndarray不包含較低的函數。

要解決此問題,您需要將數據集X_train分爲兩部分,分別爲X_train_pt1X_train_pt2。然後對這些個體執行CountVectorizer,然後對每個單獨的結果執行tfidfTransformer。還要確保您在這些數據集上進行相同的對象轉換。

最後,將這兩個數組堆疊在一起,並將其作爲輸入提供給分類器。您可以找到類似implementation here

更新:
我認爲下面應該有一定的幫助(我承認這段代碼可以更高的效率進一步提高):

def flat_list(my_list): 
    return [str(item) for sublist in my_list for item in sublist] 


def transform_data(trans_obj_list,dataset_splits): 
    X_train = dataset_splits[0].astype(str) 
    X_train = flat_list(X_train) 

    for trfs in trans_obj_list: 
     transformed_vector = trfs().fit(X_train) 
     for x in xrange(0,len(dataset_splits)): 
      dataset_splits[x] =flat_list(dataset_splits[x].astype(str)) 
      dataset_splits[x]=transformed_vector.transform(dataset_splits[x]) 

    return dataset_splits 

new_X_train,new_X_test = transform_data([CountVectorizer,TfidfTransformer],[X_train,X_test]) 
+0

好的,我明白了。將嘗試它。非常感謝。 – twhale

+0

難道還有可能小寫的X_train單獨地CountVectorizer「關掉」的lowercasing?這樣代碼可以保持更短(更快)。 – twhale

+1

即使以某種方式「關機」的下殼體(雖然這是不可能的)的CountVectorizer實現對一個字符串的工作,而不是字符串列表。你將不得不改變整個實施。所以更好的做法是創建一個接受tfIdfTransformer或CountVectorizo​​r對象並執行轉換並相應返回數據的泛型函數。 –