사용자가 보낸 메시지에 대한 정보가 포함 된 팬더 데이터 프레임이 있습니다. 내 모델의 경우, 수신자 A, B, C가 수신자에게 속해야 하는지를 예기하고자하는 메시지의 수신자 누락을 예측하는 데 관심이 있습니다.FeatureUnion을 사용하여 PipeLine에서 여러 피쳐를 변환하는 방법은 무엇입니까?
OneVsRestClassifier 및 LinearSVC를 사용하여 다중 레이블 분류를 수행하고 있습니다. 기능의 경우 메시지의 수신자를 사용하고 싶습니다. 제목과 본문.
수신자가 사용자 목록이므로 MultiLabelBinarizer를 사용하여 해당 열을 변환하려고합니다. 제목과 본문, 나는 다음과 같이
내 입력 피클 파일에 데이터가 TFIDF를 사용하려면 : 모든 값은받는 사람을 제외하고 문자열 내가 정의와 기능의 조합을 사용하고 세트()
[[message_id,sent_time,subject,body,set(recipients),message_type, is_sender]]
가되어 있습니다 파이프 라인의 변압기는 다음과 같이이를 달성합니다.
from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.base import TransformerMixin, BaseEstimator
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.multiclass import OneVsRestClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.multiclass import OneVsRestClassifier
from sklearn.linear_model import SGDClassifier
from sklearn.svm import SVC, LinearSVC
import pickle
import pandas as pd
import numpy as np
if __name__ == "__main__":
class ColumnSelector(BaseEstimator, TransformerMixin):
def __init__(self, column):
self.column = column
def fit(self, X, y=None, **fit_params):
return self
def transform(self, X, y=None, **fit_params):
return X[self.column]
class MultiLabelTransformer(BaseEstimator, TransformerMixin):
def __init__(self, column):
self.column = column
def fit(self, X, y=None):
return self
def transform(self, X):
mlb = MultiLabelBinarizer()
return mlb.fit_transform(X[self.column])
pipeline = Pipeline([
('features', FeatureUnion([
('subject_tfidf', Pipeline([
('selector', ColumnSelector(column='Subject')),
('tfidf', TfidfVectorizer(min_df=0.0025, ngram_range=(1, 4)))
])),
('body_tfidf', Pipeline([
('selector', ColumnSelector(column='Body')),
('tfidf', TfidfVectorizer(min_df=0.0025, ngram_range=(1, 4)))
])),
('recipients_binarizer', Pipeline([
('multi_label', MultiLabelTransformer(column='CoRecipients'))
])),
])),
('classifier', OneVsRestClassifier(LinearSVC(), n_jobs=-1))
])
top_recips = ['A', 'B', 'C, 'D]
corpus_data = pickle.load(
open("E:\\Data\\messages_items.pkl", "rb"))
df = pd.DataFrame(corpus_data, columns=[
'MessageId', 'SentTime', 'Subject', 'Body', 'Recipients', 'MessageType', 'IsSender'])
df = df.dropna()
# add co recipients and top recipients columns
df['CoRecipients'] = df['Recipients'].apply(
lambda r: [x for x in r if x not in top_recips])
df['TopRecipients'] = df['Recipients'].apply(
lambda r: [x for x in top_recips if x in r])
# drop rows where top recipients = 0
df = df.loc[df['TopRecipients'].str.len() > 0]
df_train = df.loc[df['SentTime'] <= '2017-10-15']
df_test = df.loc[(df['SentTime'] > '2017-10-15') & (df['MessageType'] == 'Meeting')]
mlb = MultiLabelBinarizer(classes=top_recips)
train_x = df_train[['Subject', 'Body', 'CoRecipients']]
train_y = mlb.fit_transform(df_train['TopRecipients'])
test_x = df_train[['Subject', 'Body', 'CoRecipients']]
test_y = mlb.fit_transform(df_train['TopRecipients'])
print "train"
pipeline.fit(train_x, train_y)
print "predict"
predictions = pipeline.predict(test_x)
print "done"
CoRecipients 열의 기능을 올바르게 수행하고 있는지 확실하지 않습니다. 결과가 올바르게 보이지 않기 때문에. 어떤 단서? df_test
mlb = MultiLabelBinarizer(classes=top_recips)
train_x = df_train[['Subject', 'Body', 'CoRecipients']]
train_y = mlb.fit_transform(df_train['TopRecipients'])
test_x = df_test[['Subject', 'Body', 'CoRecipients']]
test_y = mlb.transform(df_test['TopRecipients'])
는 아래 보는 사용하도록 설정 시험
class MultiLabelTransformer(BaseEstimator, TransformerMixin):
def __init__(self, column):
self.column = column
def fit(self, X, y=None):
self.mlb = MultiLabelBinarizer()
self.mlb.fit(X[self.column])
return self
def transform(self, X):
return self.mlb.transform(X[self.column])
를 고정 :
는 UPDATE 1
다음과 같이 MLB 변압기의 코드 변경 KeyError
Traceback (most recent call last):
File "E:\Projects\NLP\FeatureUnion.py", line 99, in <module>
predictions = pipeline.predict(test_x)
File "C:\Python27\lib\site-packages\sklearn\utils\metaestimators.py", line 115, in <lambda>
out = lambda *args, **kwargs: self.fn(obj, *args, **kwargs)
File "C:\Python27\lib\site-packages\sklearn\pipeline.py", line 306, in predict
Xt = transform.transform(Xt)
File "C:\Python27\lib\site-packages\sklearn\pipeline.py", line 768, in transform
for name, trans, weight in self._iter())
File "C:\Python27\lib\site-packages\sklearn\externals\joblib\parallel.py", line 779, in __call__
while self.dispatch_one_batch(iterator):
File "C:\Python27\lib\site-packages\sklearn\externals\joblib\parallel.py", line 625, in dispatch_one_batch
self._dispatch(tasks)
File "C:\Python27\lib\site-packages\sklearn\externals\joblib\parallel.py", line 588, in _dispatch
job = self._backend.apply_async(batch, callback=cb)
File "C:\Python27\lib\site-packages\sklearn\externals\joblib\_parallel_backends.py", line 111, in apply_async
result = ImmediateResult(func)
File "C:\Python27\lib\site-packages\sklearn\externals\joblib\_parallel_backends.py", line 332, in __init__
self.results = batch()
File "C:\Python27\lib\site-packages\sklearn\externals\joblib\parallel.py", line 131, in __call__
return [func(*args, **kwargs) for func, args, kwargs in self.items]
File "C:\Python27\lib\site-packages\sklearn\pipeline.py", line 571, in _transform_one
res = transformer.transform(X)
File "C:\Python27\lib\site-packages\sklearn\pipeline.py", line 426, in _transform
Xt = transform.transform(Xt)
File "E:\Projects\NLP\FeatureUnion.py", line 37, in transform
return self.mlb.transform(X[self.column])
File "C:\Python27\lib\site-packages\sklearn\preprocessing\label.py", line 765, in transform
yt = self._transform(y, class_to_index)
File "C:\Python27\lib\site-packages\sklearn\preprocessing\label.py", line 789, in _transform
indices.extend(set(class_mapping[label] for label in labels))
File "C:\Python27\lib\site-packages\sklearn\preprocessing\label.py", line 789, in <genexpr>
indices.extend(set(class_mapping[label] for label in labels))
KeyError: u'[email protected]'
> 업데이트 2
근무 당신이 잘못 MultiLabelBinarizer의 변형을하고있다
class MultiLabelTransformer(BaseEstimator, TransformerMixin):
def __init__(self, column, classes):
self.column = column
self.classes = classes
def fit(self, X, y=None):
self.mlb = MultiLabelBinarizer(classes=self.classes)
self.mlb.fit(X[self.column])
return self
def transform(self, X):
return self.mlb.transform(X[self.column])
# drop rows where top recipients = 0
df = df.loc[df['TopRecipients'].str.len() > 0]
df_train = df.loc[df['SentTime'] <= '2017-10-15']
df_test = df.loc[(df['SentTime'] > '2017-10-15') &
(df['MessageType'] == 'Meeting')]
mlb = MultiLabelBinarizer(classes=top_recips)
train_x = df_train[['Subject', 'Body', 'CoRecipients']]
train_y = mlb.fit_transform(df_train['TopRecipients'])
test_x = df_test[['Subject', 'Body', 'CoRecipients']]
test_y = mlb.transform(df_test['TopRecipients'])
# get all unique co-recipients
co_recips = list(set([a for b in df.CoRecipients.tolist() for a in b]))
# create pipeline
pipeline = Pipeline([
('features', FeatureUnion(
# list of features
transformer_list=[
('subject_tfidf', Pipeline([
('selector', ColumnSelector(column='Subject')),
('tfidf', TfidfVectorizer(min_df=0.0025, ngram_range=(1, 4)))
])),
('body_tfidf', Pipeline([
('selector', ColumnSelector(column='Body')),
('tfidf', TfidfVectorizer(min_df=0.0025, ngram_range=(1, 4)))
])),
('recipients_binarizer', Pipeline([
('multi_label', MultiLabelTransformer(column='CoRecipients', classes=co_recips))
]))
],
# weight components in FeatureUnion
transformer_weights={
'subject_tfidf': 3.0,
'body_tfidf': 1.0,
'recipients_binarizer': 1.0,
}
)),
('classifier', OneVsRestClassifier(LinearSVC(), n_jobs=-1))
])
print "train"
pipeline.fit(train_x, train_y)
print "predict"
predictions = pipeline.predict(test_x)
제안한대로 MultiLabelTrasnformer의 코드가 변경되었으며 test_x에서 예측하려고 할 때 KeyError가 발생했습니다. 변경 사항이 제안 된 Q 코드를 업데이트하십시오. 나는 당신이 암시하는 것처럼 열차 데이터에없는 테스트 데이터에만 나타나는 일부 수신자가 있기 때문에 오류가 발생했다고 생각합니다. 멀티 라벨 이진 장치가 기차 및 테스트 세트의 모든 가능한 수신자에 대해 알 수 있도록 어떻게 수정해야합니까? – user330612
@ user330612 CoRecipients 열의 알려진 모든 레이블에 대해 'MultiLabelTrasnformer'의 classes 속성을 사용하십시오. y_train과 y_test에 대해했던 것처럼. –
알았어. 그러나이 고유 CoRecipients 목록을 MultiLabelTransformer에 전달하려면 어떻게해야합니까? co_recips = list (set ([a b에 대한 df.CoRecipients.tolist()의 b에 대한 a)) – user330612