Ketika saya menggunakan ColumnTransformer untuk memproses kolom yang berbeda (termasuk numerik, kategori, teks) dengan pipa, saya tidak bisa mendapatkan nama fitur dari data yang diubah akhir, yang sulit untuk debugging.
Berikut kodenya:
titanic_url = ('https://raw.githubusercontent.com/amueller/'
'scipy-2017-sklearn/091d371/notebooks/datasets/titanic3.csv')
data = pd.read_csv(titanic_url)
target = data.pop('survived')
numeric_columns = ['age','sibsp','parch']
category_columns = ['pclass','sex','embarked']
text_columns = ['name','home.dest']
numeric_transformer = Pipeline(steps=[
('impute',SimpleImputer(strategy='median')),
('scaler',StandardScaler()
)
])
category_transformer = Pipeline(steps=[
('impute',SimpleImputer(strategy='constant',fill_value='missing')),
('ohe',OneHotEncoder(handle_unknown='ignore'))
])
text_transformer = Pipeline(steps=[
('cntvec',CountVectorizer())
])
preprocesser = ColumnTransformer(transformers=[
('numeric',numeric_transformer,numeric_columns),
('category',category_transformer,category_columns),
('text',text_transformer,text_columns[0])
])
preprocesser.fit_transform(data)
preprocesser.get_feature_names()
akan mendapatkan kesalahan:AttributeError: Transformer numeric (type Pipeline) does not provide get_feature_names.
ColumnTransformer
text_transformer
hanya dapat memproses string (misalnya 'Seks'), tetapi bukan daftar string sebagai text_columns
Ini bukan masalah tentang ColumnTransformer.
eli5
mengimplementasikan fungsi nama fitur yang dapat mendukung Pipeline.Re 2. mungkin Anda benar bahwa itu tidak ramah bahwa kami tidak memiliki cara yang bersih untuk menerapkan vectorizer teks ke setiap kolom. Saya tidak yakin bagaimana itu dapat dicapai dengan bersih, kecuali jika kita mulai mendukung beberapa kolom input di CountVectorizer dll.
Ini bukan masalah tentang ColumnTransformer.
- adalah tentang Pipa. Perhatikan bahwa
eli5
mengimplementasikan fungsi nama fitur yang dapat mendukung Pipeline.Re 2. mungkin Anda benar bahwa itu tidak ramah bahwa kami tidak memiliki cara yang bersih untuk menerapkan vectorizer teks ke setiap kolom. Saya tidak yakin bagaimana itu dapat dicapai dengan bersih, kecuali jika kita mulai mendukung beberapa kolom input di CountVectorizer dll.
Terima kasih atas balasan Anda yang baik!
Seperti yang saya ketahui, ketika saya melakukan praproses kolom menggunakan metode yang dapat mengubah satu kolom menjadi multi-kolom seperti OneHotEncoder
, CountVectorizer
, saya bisa mendapatkan nama kolom data baru dari trafo langkah terakhir pipa dengan function get_feature_names
, saat menggunakan metode yang tidak membuat kolom baru, cukup atur nama kolom mentah.
def get_column_names_from_ColumnTransformer(column_transformer):
col_name = []
for transformer_in_columns in column_transformer.transformers_[:-1]:#the last transformer is ColumnTransformer's 'remainder'
raw_col_name = transformer_in_columns[2]
if isinstance(transformer_in_columns[1],Pipeline):
transformer = transformer_in_columns[1].steps[-1][1]
else:
transformer = transformer_in_columns[1]
try:
names = transformer.get_feature_names()
except AttributeError: # if no 'get_feature_names' function, use raw column name
names = raw_col_name
if isinstance(names,np.ndarray): # eg.
col_name += names.tolist()
elif isinstance(names,list):
col_name += names
elif isinstance(names,str):
col_name.append(names)
return col_name
Dengan menggunakan kode di atas, saya bisa mendapatkan nama kolom preprocesser
.
Apakah kode ini menyelesaikan pertanyaan ini?
Pada eli5, saya tidak menemukan fungsi itu, Bisakah Anda memberi saya tautan untuk contoh eksplisit atau api untuk eli5?
Sehubungan dengan eli5, lihat transform_feature_names (digunakan oleh explain_weights)
1 adalah duplikat dari #6425, kan? Saya ingin menulis tentang itu.
Saya pikir mendukung banyak kolom teks cukup mudah dengan ColumnTransformer
. Ini bukan kode yang paling cantik tetapi Anda bisa menambahkan CountVectorizer untuk setiap kolom teks.
Dan cuplikan Anda tidak benar-benar menyelesaikan masalah karena tidak ada get_feature_names
tidak berarti Anda bisa menggunakan nama kolom saja.
1 adalah duplikat dari #6425, kan? Saya ingin menulis tentang itu.
Saya pikir mendukung banyak kolom teks cukup mudah denganColumnTransformer
. Ini bukan kode yang paling cantik tetapi Anda bisa menambahkan CountVectorizer untuk setiap kolom teks.Dan cuplikan Anda tidak benar-benar menyelesaikan masalah karena tidak ada
get_feature_names
tidak berarti Anda bisa menggunakan nama kolom saja.
ya, setelah dataFrame panda dimasukkan ke dalam pipa praproses, Lebih baik mendapatkan nama fitur sehingga bisa tahu persis apa yang terjadi hanya dari data yang dihasilkan.
ok, tutup sebagai duplikat.
Ini bukan masalah tentang ColumnTransformer.
- adalah tentang Pipa. Perhatikan bahwa
eli5
mengimplementasikan fungsi nama fitur yang dapat mendukung Pipeline.Re 2. mungkin Anda benar bahwa itu tidak ramah bahwa kami tidak memiliki cara yang bersih untuk menerapkan vectorizer teks ke setiap kolom. Saya tidak yakin bagaimana itu dapat dicapai dengan bersih, kecuali jika kita mulai mendukung beberapa kolom input di CountVectorizer dll.
Terima kasih atas balasan Anda yang baik!
Seperti yang saya ketahui, ketika saya melakukan praproses kolom menggunakan metode yang dapat mengubah satu kolom menjadi multi-kolom sepertiOneHotEncoder
,CountVectorizer
, saya bisa mendapatkan nama kolom data baru dari trafo langkah terakhir pipa dengan functionget_feature_names
, saat menggunakan metode yang tidak membuat kolom baru, cukup atur nama kolom mentah.def get_column_names_from_ColumnTransformer(column_transformer): col_name = [] for transformer_in_columns in column_transformer.transformers_[:-1]:#the last transformer is ColumnTransformer's 'remainder' raw_col_name = transformer_in_columns[2] if isinstance(transformer_in_columns[1],Pipeline): transformer = transformer_in_columns[1].steps[-1][1] else: transformer = transformer_in_columns[1] try: names = transformer.get_feature_names() except AttributeError: # if no 'get_feature_names' function, use raw column name names = raw_col_name if isinstance(names,np.ndarray): # eg. col_name += names.tolist() elif isinstance(names,list): col_name += names elif isinstance(names,str): col_name.append(names) return col_name
Dengan menggunakan kode di atas, saya bisa mendapatkan nama kolom
preprocesser
.
Apakah kode ini menyelesaikan pertanyaan ini?
Pada eli5, saya tidak menemukan fungsi itu, Bisakah Anda memberi saya tautan untuk contoh eksplisit atau api untuk eli5?
Saya membuat peningkatan kecil untuk mendapatkan kembali nama seperti rawname_value untuk formulir onehot:
def get_column_names_from_ColumnTransformer(column_transformer):
col_name = []
for transformer_in_columns in column_transformer.transformers_[:-1]:#the last transformer is ColumnTransformer's 'remainder'
raw_col_name = transformer_in_columns[2]
raw_col_name_reverse = raw_col_name[::-1]
if isinstance(transformer_in_columns[1],Pipeline):
transformer = transformer_in_columns[1].steps[-1][1]
else:
transformer = transformer_in_columns[1]
try:
names = transformer.get_feature_names()
exchange_name = [(_.split("_")) for _ in preprocessor.transformers_[:-1][0][1].steps[-1][1].get_feature_names()]
last_pre_name = ""
last_raw_name = ""
for pre_name,value in exchange_name:
if pre_name==last_pre_name:
col_name.append(last_raw_name+"_"+value)
if pre_name!=last_pre_name:
last_pre_name=pre_name
last_raw_name=raw_col_name_reverse.pop()
col_name.append(last_raw_name+"_"+value)
except AttributeError: # if no 'get_feature_names' function, use raw column name
names = raw_col_name
if isinstance(names,np.ndarray): # eg.
col_name += names.tolist()
elif isinstance(names,list):
col_name += names
elif isinstance(names,str):
col_name.append(names)
return col_name
Ini bukan masalah tentang ColumnTransformer.
- adalah tentang Pipa. Perhatikan bahwa
eli5
mengimplementasikan fungsi nama fitur yang dapat mendukung Pipeline.Re 2. mungkin Anda benar bahwa itu tidak ramah bahwa kami tidak memiliki cara yang bersih untuk menerapkan vectorizer teks ke setiap kolom. Saya tidak yakin bagaimana itu dapat dicapai dengan bersih, kecuali jika kita mulai mendukung beberapa kolom input di CountVectorizer dll.
Terima kasih atas balasan Anda yang baik!
Seperti yang saya ketahui, ketika saya melakukan praproses kolom menggunakan metode yang dapat mengubah satu kolom menjadi multi-kolom sepertiOneHotEncoder
,CountVectorizer
, saya bisa mendapatkan nama kolom data baru dari trafo langkah terakhir pipa dengan functionget_feature_names
, saat menggunakan metode yang tidak membuat kolom baru, cukup atur nama kolom mentah.def get_column_names_from_ColumnTransformer(column_transformer): col_name = [] for transformer_in_columns in column_transformer.transformers_[:-1]:#the last transformer is ColumnTransformer's 'remainder' raw_col_name = transformer_in_columns[2] if isinstance(transformer_in_columns[1],Pipeline): transformer = transformer_in_columns[1].steps[-1][1] else: transformer = transformer_in_columns[1] try: names = transformer.get_feature_names() except AttributeError: # if no 'get_feature_names' function, use raw column name names = raw_col_name if isinstance(names,np.ndarray): # eg. col_name += names.tolist() elif isinstance(names,list): col_name += names elif isinstance(names,str): col_name.append(names) return col_name
Dengan menggunakan kode di atas, saya bisa mendapatkan nama kolom
preprocesser
.
Apakah kode ini menyelesaikan pertanyaan ini?
Pada eli5, saya tidak menemukan fungsi itu, Bisakah Anda memberi saya tautan untuk contoh eksplisit atau api untuk eli5?
Bagaimana jika Anda menerapkan simpleimputer dengan add_indicator dalam pipa? Pendekatan ini tidak akan berhasil.
Bagaimana jika Anda menerapkan simpleimputer dengan add_indicator dalam pipa? Pendekatan ini tidak akan berhasil.
Akan menyenangkan untuk memiliki metode get_feature_names untuk konfigurasi ini.
Bagaimana jika Anda menerapkan simpleimputer dengan add_indicator dalam pipa? Pendekatan ini tidak akan berhasil.
Inilah kontribusi saya untuk solusi jangka pendek. Ini memaksa semua jenis array yang berbeda ke daftar, dan menangani kasus SimpleImputer(add_indicate=True). Ini juga sedikit lebih bertele-tele.
def get_column_names_from_ColumnTransformer(column_transformer):
col_name = []
for transformer_in_columns in column_transformer.transformers_[:-1]: #the last transformer is ColumnTransformer's 'remainder'
print('\n\ntransformer: ', transformer_in_columns[0])
raw_col_name = list(transformer_in_columns[2])
if isinstance(transformer_in_columns[1], Pipeline):
# if pipeline, get the last transformer
transformer = transformer_in_columns[1].steps[-1][1]
else:
transformer = transformer_in_columns[1]
try:
if isinstance(transformer, OneHotEncoder):
names = list(transformer.get_feature_names(raw_col_name))
elif isinstance(transformer, SimpleImputer) and transformer.add_indicator:
missing_indicator_indices = transformer.indicator_.features_
missing_indicators = [raw_col_name[idx] + '_missing_flag' for idx in missing_indicator_indices]
names = raw_col_name + missing_indicators
else:
names = list(transformer.get_feature_names())
except AttributeError as error:
names = raw_col_name
print(names)
col_name.extend(names)
return col_name
FYI, saya menulis beberapa kode dan blog tentang cara mengekstrak nama fitur dari Pipelines & ColumnTransformers yang kompleks. Kode ini merupakan peningkatan dari posting saya sebelumnya. https://towardsdatascience.com/extracting-plotting-feature-names-importance-from-scikit-learn-pipelines-eb5bfa6a31f4
@kylegilde Artikel yang bagus dan terima kasih untuk kodenya. Bekerja seperti pesona. Untuk penjelasan global, saya telah bergulat dengan KernelSHAP dan alibi selama beberapa jam tetapi transformator onehot saya tidak berfungsi tanpa handle_unkown='ignore'
Berikut adalah versi lain dari cuplikan @pjgao yang menyertakan kolom dari pengingat:
def get_columns_from_transformer(column_transformer, input_colums):
col_name = []
for transformer_in_columns in column_transformer.transformers_[:-1]: #the last transformer is ColumnTransformer's 'remainder'
raw_col_name = transformer_in_columns[2]
if isinstance(transformer_in_columns[1],Pipeline):
transformer = transformer_in_columns[1].steps[-1][1]
else:
transformer = transformer_in_columns[1]
try:
names = transformer.get_feature_names(raw_col_name)
except AttributeError: # if no 'get_feature_names' function, use raw column name
names = raw_col_name
if isinstance(names,np.ndarray): # eg.
col_name += names.tolist()
elif isinstance(names,list):
col_name += names
elif isinstance(names,str):
col_name.append(names)
[_, _, reminder_columns] = column_transformer.transformers_[-1]
for col_idx in reminder_columns:
col_name.append(input_colums[col_idx])
return col_name
Apa pendapat Anda tentang menambahkan fungsi serupa ke basis kode inti?
Komentar yang paling membantu
Terima kasih atas balasan Anda yang baik!
Seperti yang saya ketahui, ketika saya melakukan praproses kolom menggunakan metode yang dapat mengubah satu kolom menjadi multi-kolom seperti
OneHotEncoder
,CountVectorizer
, saya bisa mendapatkan nama kolom data baru dari trafo langkah terakhir pipa dengan functionget_feature_names
, saat menggunakan metode yang tidak membuat kolom baru, cukup atur nama kolom mentah.Dengan menggunakan kode di atas, saya bisa mendapatkan nama kolom
preprocesser
.Apakah kode ini menyelesaikan pertanyaan ini?
Pada eli5, saya tidak menemukan fungsi itu, Bisakah Anda memberi saya tautan untuk contoh eksplisit atau api untuk eli5?