Мы поделились«Обработка натурального языка с Sklearn-1», сегодня мы продолжаем использовать sklearn для более сложных задач. Сегодня мы используем набор данных комментариев веб-сайта yelp, чтобы провести некоторое исследование.В дополнение к знаниям по извлечению признаков, использованным в предыдущей статье, в этой статье они также будут.
В этой статье основное внимание уделяется разработке признаков и другим этапам, таким как извлечение признаков, построение конвейеров (многие из них переводятся в нефтяные трубы, я лично думаю, что трубопроводы кажутся более точными), построение настраиваемых преобразователей, объединение признаков, уменьшение размеров и настройка параметров (сетка поиск). Разработка признаков — очень важный шаг в обработке естественного языка и машинном обучении, поэтому в этой статье будет уделено больше времени этому разделу.
В последней статье мы использовали набор данных World News Group 20. Сегодня мы используем веб-сайт yelp для комментариев к набору данных, и я преобразовал его в файл csv, чтобы все могли использовать панды для чтения данных. Набор данных yelp содержит пять полей: звезды, текст, смешной, полезный и классный, Задача этой статьи — предсказать значение звезд для каждого комментария.
1. Импортируйте набор данных yelp comment
import pandas as pddataset = pd.read_csv('yelp-review-subset.csv', delimiter=',', names=['stars', 'text', 'funny', 'useful', 'cool'])#随机查看5条数据print(dataset.sample(5))
скопировать код
результат операции
stars text funny useful \ 37 3 I wouldnt say the best fish sandwich ive ever ... 0 0 1635 2 The order process went well and the delivery a... 0 0 1836 3 Checked out the neighborhood restaurant for Su... 0 0 1040 4 Dining outdoors after a bike ride on the rail ... 0 1 1719 5 If I could give Dr. Bigger 10 stars I would! H... 0 0 cool 37 0 1635 0 1836 0 1040 0 1719 1
скопировать код
Давайте посмотрим на распределение данных снова
print('yelp评论数据集star值有{0}个等级, 工{1}条评论'.format(len(dataset.stars.unique()), len(dataset)))#stars值去重后含有取值范围print(dataset.stars.unique())#stars数据分布print(dataset.stars.value_counts())
скопировать код
результат операции
yelp评论数据集star值有6个等级, 工2501条评论 ['stars' '4' '5' '3' '2' '1'] 1 500 5 500 4 500 2 500 3 500 stars 1 Name: stars, dtype: int64
скопировать код
Далее нам нужно разделить данные на обучающий набор и тестовый набор.
2. Разделите набор данных на обучающий набор и тестовый набор.
from sklearn.model_selection import train_test_split#训练集占3成,数据随机打乱,设置随机状态X_train, X_test, y_train, y_test = train_test_split(dataset[['text', 'funny', 'useful', 'cool']], dataset['stars'], random_state= 100, test_size=0.3)#查看前5条数据print(X_train.head())
скопировать код
результат операции
text funny useful cool 1818 If you go there, be very careful with the pric... 0 1 0 751 I am not a fan of chain restaurants typically ... 0 3 2 545 Love dukes and love the food. I wish i could f... 0 0 0 198 Tonya is super sweet and the front desk people... 0 0 0 1439 Ate here last night...fantastic food & service... 0 0 0
скопировать код
Теперь X_train содержит три столбца (смешные, полезные, классные) числовых данных, что очень удобно для sklearn-анализа. Теперь нам также нужно извлечь признаки из текста
print(X_train.columns)print(type(X_train))print(type(X_train.text))
скопировать код
результат операции
Index(['text', 'funny', 'useful', 'cool'], dtype='object') <class 'pandas.core.frame.DataFrame'> <class 'pandas.core.series.Series'>
скопировать код
Теперь нам нужно выполнить извлечение функций из текста и использовать CountVectorize.Если вы этого не понимаете, вы можете прочитать статью, опубликованную ранее.«Как извлечь информацию об объектах из текста»
3. Извлечение признаков
from sklearn.feature_extraction.text import CountVectorizercounter = CountVectorizer()#如果这里是中文文本数据,我们需要先分词,词语之间以空格隔开的字符串传入X_train_counts = counter.fit_transform(X_train.text)#2000条数据,特征空间有11193个特征词print(X_train_counts.shape)
скопировать код
результат операции
(1750, 11193)
скопировать код
Теперь нашX_train_counts
Содержит экстракт изtext
пространство функций , но как мы можем объединить функции текстовых данных сfunny
, useful
,cool
Отношения между?
4 Pipeline
Конвейер должен состоять из нескольких преобразователей (для подготовки данных), а последний должен быть построен оценщиком (для обучения модели). Все еще могут немного запутаться.Я беру потребителя использовать бензин при вождении, и использование потребителем бензина является последним шагом.До этого добыча нефти, транспортировка и переработка являются трансформаторами.
Метод конвейера sklearn записывается следующим образом.
pipeline = Pipeline([ ('step1', 油田从地下抽石油()), ('step2', 石油炼化厂将石油转化为汽油()), ('step3', 加油站加油()), ('step4', 消费者开车消费()) ])
скопировать код
Среди них этап 1, этап 2 и этап 3 не являются потребительскими секторами, но совместное производство может осуществляться только при правильном соединении вышестоящего и нижестоящего секторов. Конечный продукт совместного производства, наконец, потребляется на этапе 4. Итак, первые 3 шага мы называем преобразователем, а последний шаг 4 — оценщиком.
Мы знаем, что ключом к реализации крупномасштабного промышленного производства является то, что все общество имеет полную стандартную систему.В этом примере каждому отделу нужно знать только свой собственный ввод и вывод, и ему нужно только стандартизировать ввод (соответствие) и вывод (преобразование) Can. Итак, чтобы sklearn понял, что это часть процесса подготовки данных, нам нужно равномерно наследовать признанный стандарт для каждого шага до шага 4, то есть пусть каждый шаг наследует (шаг перед шагом 4) наследует TransformerMixin, BaseEstimator два Тип (стандартная система, которой следует все общество в крупномасштабном промышленном производстве) и инкапсулированный в метод с подгонкой входных данных и преобразованием выходных данных. Возможно, методы подгонки и преобразования не имеют каких-либо операций с материалом или могут иметь операции, но эти два метода должны быть доступны для понимания sklearn.
class ItemSelector(TransformerMixin, BaseEstimator): """性质为transformer器。功能是从dataframe中选定某列(某几列)数据""" def __init__(self, keys): self.keys = keys #ItemSelector的输入fit def fit(self, x, y=None): return self #ItemSelector的输出transform def transform(self, dataframe): return dataframe[self.keys]class VotesToDictTransformer(TransformerMixin, BaseEstimator): """性质为transformer器。功能是将[funny,useful, cool]转化为字典列表""" #VotesToDictTransformer的输入fit def fit(self, x, y=None): return self #VotesToDictTransformer的输出transform def transform(self, votes): funny, useful, cool = votes['funny'], votes['useful'], votes['cool'] return [{'funny': f, 'useful': u, 'cool': c } for f, u, c in zip(funny, useful, cool)]
скопировать код
DictVectorizer также является преобразователем, который просто преобразует данные из списка (списка, содержащего словари) в матрицу признаков. Данные, очищенные на этом этапе, могут быть отправлены оценщику (роль оценщика состоит в том, чтобы позволить модели изучить законы в данных). Давайте посмотрим на эффект выполнения кода DictVectorizer.
from sklearn.feature_extraction import DictVectorizerdictV = DictVectorizer()data = dictV.fit_transform([{'a':3, 'b':5},{'a':0,'b':2},{'a':12,'b':3}])print(data.toarray())print(dictV.get_feature_names())
скопировать код
результат операции
[[ 3. 5.] [ 0. 2.] [12. 3.]] ['a', 'b']
скопировать код
5. FeatureUnion
Это приводит к слиянию функций (FeatureUnion), которое будет обсуждаться далее и которое заключается в вычислении влияния текста на звездочки a и эффекта смешного, полезного, крутого на звездочки b. Затем придайте a и b определенную пропорцию или вес, чтобы получить модель влияния всех данных на звезды.
FeatureUnion и Pipeline могут быть вложены друг в друга. Для простоты понимания возьму пример с вождением автомобиля. Например, наш автомобиль является гибридным автомобилем, и мы хотим знать эксплуатационные расходы на километр, тогда нам нужно знать информацию о бензине, а также нужно знать информацию об электроэнергии, а также нужно знать долю их потребление.
FeatureUnion( transformer_list=[ ('汽油', Pipeline([ ('step1', 油田从地下抽石油()), ('step2', 石油炼化厂将石油转化为汽油()), ('step3', 加油站加油()), ('step4', 消费者开车消费()) ])), ('电', Pipeline([ ('step_1', 挖煤()), ('step_2', 火电厂()), ('step_3', 充电站()), ])), ], #能源消费比 transformer_weights={ '汽油': 3.0, '电': 1 }, )
скопировать код
Фактически, общая функция FeatureUnion по-прежнему является преобразователем, поэтому FeatureUnion может быть вложен в другой конвейер вместе с оценщиком. Объяснение настолько утомительно, что я не знаю, все ли понимают FeatureUnion и Pipeline. Введите приведенный ниже код, который очень длинный, но я надеюсь, что вы в целом понимаете функцию каждой части и сможете медленно переваривать ее в ближайшие дни.
from sklearn.base import TransformerMixin, BaseEstimatorfrom sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.pipeline import FeatureUnion, Pipelinefrom sklearn.linear_model import LogisticRegressionfrom sklearn.feature_extraction import DictVectorizerfrom sklearn.metrics import classification_reportclass ItemSelector(TransformerMixin, BaseEstimator): """性质为transformer器。功能是从dataframe中选定某列(某几列)数据""" def __init__(self, keys): self.keys = keys #ItemSelector的输入fit def fit(self, x, y=None): return self #ItemSelector的输出transform def transform(self, dataframe): return dataframe[self.keys]class VotesToDictTransformer(TransformerMixin, BaseEstimator): """性质为transformer器。功能是将[funny,useful, cool]转化为字典列表""" #VotesDictTransfromer的输入fit def fit(self, x, y=None): return self #VotesDictTransfromer的输出transform def transform(self, votes): funny, useful, cool = votes['funny'], votes['useful'], votes['cool'] return [{'funny': f, 'useful': u, 'cool': c } for f, u, c in zip(funny, useful, cool)]model = Pipeline([ #使用FeatureUnion将text与votes融合起来 ('union', FeatureUnion( transformer_list=[ # 从文本中抽取特征矩阵 ('bagofwords', Pipeline([ ('selector', ItemSelector(keys='text')), ('counts', TfidfVectorizer()), ])), # 从'funny', 'useful', 'cool'获取特征 # 将这些特征转化为Dict形式 # 使用DictVectorizer将dict形式数据转化为矩阵 ('votes', Pipeline([ ('selector', ItemSelector(keys=['funny', 'useful', 'cool'])), ('votes_to_dict', VotesToDictTransformer()), ('vectorizer', DictVectorizer()), ])), ], # 对不同类别的特征赋予权重 transformer_weights={ 'bag-of-words': 3.0, 'votes': 1 }, )), #对融合后的特征矩阵使用LogisticRegression算法 ('clf', LogisticRegression()),])#使用训练集训练模型model.fit(X_train, y_train)#使用测试集做预测predicted = model.predict(X_test)#生成分类效果报告,查看模型的训练准确率情况print(classification_report(predicted, y_test))
скопировать код
результат операции
precision recall f1-score support 1 0.69 0.63 0.65 177 2 0.51 0.44 0.48 165 3 0.33 0.39 0.36 127 4 0.29 0.41 0.34 111 5 0.68 0.54 0.61 171 stars 0.00 0.00 0.00 0 avg / total 0.53 0.50 0.51 751
скопировать код
6. Grid Search
В приведенном выше примере мы использовали TfidfVectorizer и LogisticRegression напрямую, Фактически, некоторые гиперпараметры CNOOC требуют настройки, чтобы найти лучшие параметры. Здесь используется GridSearchCV.
В модели выше
('clf', LogisticRegression())
Таким образом, clf означает логистическую регрессию. Поэтому при использовании gridsearch мы должны указать параметры max_iter и C для LogisticRegression. Чтобы использовать clf__max_iter и clf__C, сообщите sklearn, что мы настраиваем LogisticRegression с именем clf.
В модели выше
('counts', TfidfVectorizer())
Такой способ написания, поскольку содержимое вложено в несколько слоев, псевдоним довольно длинный.union__bagofwords__countsОбозначает TfidfVectorizer. Поэтому при использовании gridsearch нам нужно указать параметр max_df для TfidfVectorizer. Чтобы использовать union__bagofwords__counts__max_df, чтобы сообщить sklearn, что мы объединяем имена с
TfidfVectorizer of union__bagofwords__counts__max_df для настройки.
Обратите внимание, что псевдонимы содержат двойное подчеркивание
from sklearn.model_selection import GridSearchCVparams = dict(clf__max_iter=[50, 80, 100], clf__C=[0.1, 0.2, 0.3], union__bagofwords__counts__max_df = [0.5, 0.6, 0.7, 0.8])grid_search = GridSearchCV(model, param_grid=params)grid_search.fit(X_train, y_train)print(grid_search.best_params_)
скопировать код
результат операции
{'clf__C': 0.3, 'clf__max_iter': 50, 'union__bagofwords__counts__max_df': 0.7}
скопировать код
Согласно результатам настройки GridSearch, когда max_iter = 50, C = 0,3, max_df = 0,7 для LogisticRegression, модель работает лучше.
Затем мы устанавливаем модель в
C и max_iter параметры LogisticRegression,
max_df = 0,7 для TfidfVectorizer,
Посмотрите, улучшится ли точность
model = Pipeline([ #使用FeatureUnion将text与votes融合起来 ('union', FeatureUnion( transformer_list=[ # 从文本中抽取特征矩阵 ('bag-of-words', Pipeline([ ('selector', ItemSelector(keys='text')), ('counts', TfidfVectorizer(max_df = 0.7)), ])), # 从'funny', 'useful', 'cool'获取特征 # 将这些特征转化为Dict形式 # 使用DictVectorizer将dict形式数据转化为矩阵 ('votes', Pipeline([ ('selector', ItemSelector(keys=['funny', 'useful', 'cool'])), ('votes_to_dict', VotesToDictTransformer()), ('vectorizer', DictVectorizer()), ])), ], # 对不同类别的特征赋予权重 transformer_weights={ 'bag-of-words': 3.0, 'votes': 1 }, )), #对融合后的特征矩阵使用LogisticRegression算法 ('clf', LogisticRegression(C=0.3, max_iter=50)),])model.fit(X_train, y_train)predicted = model.predict(X_test)print(classification_report(predicted, y_test))
скопировать код
результат операции
precision recall f1-score support 1 0.72 0.66 0.69 177 2 0.48 0.49 0.48 139 3 0.37 0.39 0.38 143 4 0.34 0.41 0.38 131 5 0.70 0.59 0.64 161 stars 0.00 0.00 0.00 0 avg / total 0.54 0.52 0.53 751
скопировать код
скопировать код
Из вышеизложенного мы обнаружили, что точность, полнота и значение F1 модели после использования гиперпараметров, полученных с помощью gridsearch, были в определенной степени оптимизированы.
7. Conclusion
Две статьи из серии об обработке естественного языка с помощью sklearn могут в основном решить более 80% ваших потребностей в НЛП. Надеюсь, эти две статьи помогут вам.
Получение данных и кода
Прошлые статьи
Учебные материалы по Python объемом 100 ГБ: от начального уровня до мастера!
Как студенты колледжа используют свои знания, чтобы зарабатывать 3000 в месяц
Прошлой ночью я закончил читать «Эпоху интеллекта» У Цзюня.
Сотни наборов текстовых данных G ждут вас | Бесплатная заявка
Почему вы планируете на 2019, а не на 2018 год?
15 лучших библиотек Python для науки о данных в 2017 году
Знакомство с алгоритмом К-средних
Машинное обучение с использованием логистической регрессии для идентификации чисел на картинках
Применение уменьшения размерности PCA для ускорения обучения модели
Машинное обучение | Восемь шагов для решения 90% проблем NLP
Используйте sklearn для обработки естественного языка-1
Сложная вложенная структура данных словаря, обрабатывающая библиотеку-glom
Чтение файлов pdf и docx, профессиональный тест эффективен
Как извлечь информацию об объектах из текста?
Что может сделать nltk для китайцев
Каждое слово, оставленное в Интернете, раскрывает вашу личность
Элегантные и лаконичные списки
Получить список советов и рекомендаций
Как сортировать данные различными способами?
[Объяснение видео] Scrapy рекурсивно собирает информацию о пользователях Jianshu
Артефакт сбора информации о торговце Meituan
Используйте библиотеку chardect для решения проблемы искаженных веб-страниц.
gevent: асинхронная теория и практика
Легкая и эффективная библиотека асинхронного доступа
Подробное объяснение конфигурации селенового диска
Как использовать артефакт сканера PyQuery
Простое изучение базы данных SQLite3
Функция вызова Python по строке