Когда я использую ColumnTransformer для предварительной обработки различных столбцов (включая числовые, категории, текстовые) с конвейером, я не могу получить имена функций окончательных преобразованных данных, что трудно отладить.
Вот код:
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()
получит ошибку:AttributeError: Transformer numeric (type Pipeline) does not provide get_feature_names.
ColumnTransformer
, text_transformer
может обрабатывать только строку (например, 'Sex'), но не список строк как text_columns
Это не проблема ColumnTransformer.
eli5
реализует функцию имен функций, которая может поддерживать конвейер.Касательно 2. Возможно, вы правы в том, что у нас нет чистого способа применить векторизатор текста к каждому столбцу. Я не уверен, как этого можно добиться, если мы просто не начнем поддерживать несколько столбцов ввода в CountVectorizer и т. Д.
Это не проблема ColumnTransformer.
- это о трубопроводе. Обратите внимание, что
eli5
реализует функцию имен функций, которая может поддерживать конвейер.Касательно 2. Возможно, вы правы в том, что у нас нет чистого способа применить векторизатор текста к каждому столбцу. Я не уверен, как этого можно добиться, если мы просто не начнем поддерживать несколько столбцов ввода в CountVectorizer и т. Д.
Спасибо за любезный ответ!
Насколько я знаю, когда я предварительно обрабатываю столбец с использованием методов, которые могут изменить один столбец на несколько столбцов, таких как OneHotEncoder
, CountVectorizer
, я могу получить новые имена столбцов данных из преобразователя последнего шага конвейера, функция get_feature_names
при использовании методов, которые не создают новые столбцы, может просто установить имя исходных столбцов.
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
Используя приведенный выше код, я могу получить имена столбцов preprocesser
.
Этот код решает этот вопрос?
Что касается eli5, я не нахожу эту функцию. Можете ли вы дать мне ссылку на явный пример или api для eli5?
Что касается eli5, см. Transform_feature_names (используется объяснением_весов)
1 - это дубликат # 6425, верно? Я хочу написать об этом сон.
Я думаю, что поддержка нескольких текстовых столбцов довольно проста с помощью ColumnTransformer
. Это не самый красивый код, но вы можете просто добавить CountVectorizer для каждого текстового столбца.
И ваш фрагмент на самом деле не решает проблему, потому что отсутствие get_feature_names
не означает, что вы можете просто использовать имена столбцов.
1 - это дубликат # 6425, верно? Я хочу написать об этом сон.
Я думаю, что поддержка нескольких текстовых столбцов довольно проста с помощьюColumnTransformer
. Это не самый красивый код, но вы можете просто добавить CountVectorizer для каждого текстового столбца.И ваш фрагмент на самом деле не решает проблему, потому что отсутствие
get_feature_names
не означает, что вы можете просто использовать имена столбцов.
да, после того, как pandas DataFrame подает в конвейер предварительной обработки, лучше получить имена функций, чтобы можно было точно знать, что произошло, только на основе сгенерированных данных.
хорошо, закрываю как дубликат.
Это не проблема ColumnTransformer.
- это о трубопроводе. Обратите внимание, что
eli5
реализует функцию имен функций, которая может поддерживать конвейер.Касательно 2. Возможно, вы правы в том, что у нас нет чистого способа применить векторизатор текста к каждому столбцу. Я не уверен, как этого можно добиться, если мы просто не начнем поддерживать несколько столбцов ввода в CountVectorizer и т. Д.
Спасибо за любезный ответ!
Насколько я знаю, когда я предварительно обрабатываю столбец с использованием методов, которые могут изменить один столбец на несколько столбцов, таких какOneHotEncoder
,CountVectorizer
, я могу получить новые имена столбцов данных из преобразователя последнего шага конвейера, функцияget_feature_names
при использовании методов, которые не создают новые столбцы, может просто установить имя исходных столбцов.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
Используя приведенный выше код, я могу получить имена столбцов
preprocesser
.
Этот код решает этот вопрос?
Что касается eli5, я не нахожу эту функцию. Можете ли вы дать мне ссылку на явный пример или api для eli5?
Я сделал небольшое улучшение, чтобы вернуть имя типа rawname_value для форм 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
Это не проблема ColumnTransformer.
- это о трубопроводе. Обратите внимание, что
eli5
реализует функцию имен функций, которая может поддерживать конвейер.Касательно 2. Возможно, вы правы в том, что у нас нет чистого способа применить векторизатор текста к каждому столбцу. Я не уверен, как этого можно добиться, если мы просто не начнем поддерживать несколько столбцов ввода в CountVectorizer и т. Д.
Спасибо за любезный ответ!
Насколько я знаю, когда я предварительно обрабатываю столбец с использованием методов, которые могут изменить один столбец на несколько столбцов, таких какOneHotEncoder
,CountVectorizer
, я могу получить новые имена столбцов данных из преобразователя последнего шага конвейера, функцияget_feature_names
при использовании методов, которые не создают новые столбцы, может просто установить имя исходных столбцов.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
Используя приведенный выше код, я могу получить имена столбцов
preprocesser
.
Этот код решает этот вопрос?
Что касается eli5, я не нахожу эту функцию. Можете ли вы дать мне ссылку на явный пример или api для eli5?
Как насчет того, чтобы применить simpleimputer с add_indicator в конвейере? Такой подход не сработает.
Как насчет того, чтобы применить simpleimputer с add_indicator в конвейере? Такой подход не сработает.
Было бы неплохо иметь метод get_feature_names для этой конфигурации.
Как насчет того, чтобы применить simpleimputer с add_indicator в конвейере? Такой подход не сработает.
Вот мой вклад в краткосрочное решение. Он приводит все различные типы массивов к спискам и обрабатывает случай SimpleImputer (add_indicate = True). Это также немного более многословно.
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
К вашему сведению, я написал код и блог о том, как извлекать имена функций из сложных конвейеров и преобразователей столбцов. Код является улучшением по сравнению с моим предыдущим постом. https://towardsdatascience.com/extracting-plotting-feature-names-importance-from-scikit-learn-pipelines-eb5bfa6a31f4
@kylegilde Отличная статья и спасибо за код. Работает как шарм. Для глобальных объяснений я несколько часов боролся с KernelSHAP и алиби, но не смог заставить мой onehot преобразователь работать без handle_unkown='ignore'
Вот еще одна версия фрагмента @pjgao , которая включает столбцы из напоминания:
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
Что вы думаете о добавлении аналогичной функции в основную кодовую базу?
Самый полезный комментарий
Спасибо за любезный ответ!
Насколько я знаю, когда я предварительно обрабатываю столбец с использованием методов, которые могут изменить один столбец на несколько столбцов, таких как
OneHotEncoder
,CountVectorizer
, я могу получить новые имена столбцов данных из преобразователя последнего шага конвейера, функцияget_feature_names
при использовании методов, которые не создают новые столбцы, может просто установить имя исходных столбцов.Используя приведенный выше код, я могу получить имена столбцов
preprocesser
.Этот код решает этот вопрос?
Что касается eli5, я не нахожу эту функцию. Можете ли вы дать мне ссылку на явный пример или api для eli5?