[Scikit-learn Tutorial] 03.02 Обработка текста: классификация и оптимизация

искусственный интеллект
[Scikit-learn Tutorial] 03.02 Обработка текста: классификация и оптимизация

Добро пожаловать на главный сайт Jizhi:Jizhi, двигатель, ведущий к эре интеллекта



обзор

В предыдущем разделе мы получили исходные текстовые данные из сети и с жесткого диска с помощью различных методов, предоставляемых Scikit-learn, и принялиtf-idfМетод успешно извлекает текстовые функции, вы можете еще раз просмотреть процесс в примере ниже.

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer

# 选取参与分析的文本类别
categories = ['alt.atheism', 'soc.religion.christian',
              'comp.graphics', 'sci.med']
# 从硬盘获取原始数据
twenty_train=load_files("/mnt/vol0/sklearn/20news-bydate-train",
        categories=categories,
        load_content = True,
        encoding="latin1",
        decode_error="strict",
        shuffle=True, random_state=42)
# 统计词语出现次数
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(twenty_train.data)
# 使用tf-idf方法提取文本特征
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)
# 打印特征矩阵规格
print(X_train_tfidf.shape)

В этом разделе, на основе работы по извлечению признаков, мы продолжим завершать следующий этап интеллектуального анализа текстовой информации — обучение и оптимизацию классификатора.

обучить классификатор

Существует множество алгоритмов машинного обучения, которые можно использовать для классификации текста, алгоритм наивного Байеса (Наивный байесовский) является одним из них. Scikit-learn включает в себя несколько улучшенных моделей наивного байесовского алгоритма.Наиболее подходящая модель для подсчета слов в тексте называется полиномиальным наивным байесовским алгоритмом, который можно вызвать следующими способами.

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
categories = ["alt.atheism", "soc.religion.christian",
              "comp.graphics", "sci.med"]
twenty_train=load_files("/mnt/vol0/sklearn/20news-bydate-train",
        categories=categories,
        load_content = True,
        encoding="latin1",
        decode_error="strict",
        shuffle=True, random_state=42)
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(twenty_train.data)
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)[/amalthea_pre_exercise_code]
[amalthea_sample_code]
from sklearn.naive_bayes import MultinomialNB
clf = MultinomialNB().fit(X_train_tfidf, twenty_train.target)
print("分类器的相关信息:")
print(clf)

На этом процесс обучения классификатора завершен. Чтобы использовать новый документ для работы классификатора по прогнозированию классификации, мы должны использовать те же методы обработки данных для обработки нашего нового документа. Как показано в примере ниже, мы используем набор пользовательских строк для определения их классификации. Группа строк должна пройтиtransformметод делать прогнозы.

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
categories = ["alt.atheism", "soc.religion.christian",
              "comp.graphics", "sci.med"]
twenty_train=load_files("/mnt/vol0/sklearn/20news-bydate-train",
        categories=categories,
        load_content = True,
        encoding="latin1",
        decode_error="strict",
        shuffle=True, random_state=42)
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(twenty_train.data)
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)
from sklearn.naive_bayes import MultinomialNB
clf = MultinomialNB().fit(X_train_tfidf, twenty_train.target)
# 预测用的新字符串,你可以将其替换为任意英文句子
docs_new = ["Nvidia is awesome!"]
# 字符串处理
X_new_counts = count_vect.transform(docs_new)
X_new_tfidf = tfidf_transformer.transform(X_new_counts)

# 进行预测
predicted = clf.predict(X_new_tfidf)

# 打印预测结果
for doc, category in zip(docs_new, predicted):
    print("%r => %s" % (doc, twenty_train.target_names[category]))

Как базовый алгоритм машинного обучения, основанный на западных теориях, хотя Наивный Байес очень прост, а иногда и очень прост, его скорость работы очень высока, а эффект очень идеален, что можно сравнить со многими более сложными алгоритмами.

Построить трубопровод

Pipeline的本意是管道

Чтобы упростить процесс очистки, выделения признаков и классификации необработанных данных, Scikit-learn предоставляетPipelineclass для реализации интегрированного процесса построения классификатора. Классификатор можно создать, создавPipelineспособ достижения, и различные методы извлечения признаков и классификации могут быть установлены вPipelineПри указании напрямую, что значительно повышает эффективность кодирования и отладки, как показано ниже:

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
categories = ["alt.atheism", "soc.religion.christian",
              "comp.graphics", "sci.med"]
twenty_train=load_files("/mnt/vol0/sklearn/20news-bydate-train",
        categories=categories,
        load_content = True,
        encoding="latin1",
        decode_error="strict",
        shuffle=True, random_state=42)[/amalthea_pre_exercise_code]
[amalthea_sample_code]
from sklearn.pipeline import Pipeline
# 建立Pipeline
text_clf = Pipeline([("vect", CountVectorizer()),
                     ("tfidf", TfidfTransformer()),
                     ("clf", MultinomialNB()),
])
# 训练分类器
text_clf = text_clf.fit(twenty_train.data, twenty_train.target)
# 打印分类器信息
print(text_clf)

Оцените производительность классификатора, используя тестовые данные

Мы можем использовать описанный выше метод, чтобы делать прогнозы на наборе тестовых данных, а затем использоватьNumpyПредоставленная функция получает результат оценки:

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer,TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
if "text_clf" not in dir() :
	categories = ["alt.atheism", "soc.religion.christian",
	              "comp.graphics", "sci.med"]
	twenty_train=load_files("/mnt/vol0/sklearn/20news-bydate-train",categories=categories,  load_content = True, 
	                           encoding="latin1", decode_error="strict",shuffle=True, random_state=42)
	text_clf = Pipeline([("vect", CountVectorizer()),
	                     ("tfidf", TfidfTransformer()),
	                     ("clf", MultinomialNB()),
	])
	text_clf = text_clf.fit(twenty_train.data, twenty_train.target)
import numpy as np
# 获取测试数据
twenty_test=load_files('/mnt/vol0/sklearn/20news-bydate-test',
                        categories=categories,
                        load_content = True, 
                        encoding='latin1',
                        decode_error='strict',
                        shuffle=True, random_state=42)
docs_test = twenty_test.data
# 使用测试数据进行分类预测
predicted = text_clf.predict(docs_test)
# 计算预测结果的准确率
print("准确率为:")
print(np.mean(predicted == twenty_test.target))

Если мы запустим приведенный выше код в обычном режиме, мы должны получить точность 83,4%. У нас есть много способов улучшить этот показатель, используя признанный в отрасли алгоритм, наиболее подходящий для классификации текста — машины опорных векторов (SVM, машина опорных векторов) — хорошее направление (хотя оно будет немного медленнее, чем Наивный Байес). Мы можем сделать это легко, изменив объект, указанный классификатором в Pipeline:

import numpy as np
from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer,TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline

categories = ['alt.atheism', 'soc.religion.christian',
              'comp.graphics', 'sci.med']
if 'twenty_train' not in dir() :
	twenty_train=load_files('/mnt/vol0/sklearn/20news-bydate-train',categories=categories,  load_content = True, 
	                           encoding='latin1', decode_error='strict',shuffle=True, random_state=42)
if 'twenty_test' not in dir() :
	twenty_test=load_files('/mnt/vol0/sklearn/20news-bydate-test',categories=categories,  load_content = True, 
	                           encoding='latin1', decode_error='strict',shuffle=True, random_state=42)
	docs_test = twenty_test.data

from sklearn.linear_model import SGDClassifier
text_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()),
                     ('clf', SGDClassifier(loss='hinge',
                                            penalty='l2',
                                            alpha=1e-3,
                                            n_iter=5,
                                            random_state=42)),
                    ])
_ = text_clf.fit(twenty_train.data, twenty_train.target)
predicted = text_clf.predict(docs_test)
print("准确率:")
print(np.mean(predicted == twenty_test.target))

Мы видим, что точность, полученная методом SVM, значительно улучшилась по сравнению с Наивным Байесом.

Scikit-learn предоставляет больше инструментов оценки, чтобы лучше помочь нам проанализировать производительность классификатора.Как показано ниже, мы можем получить точность, отзыв, значение F и т. д. каждой классификации в результатах прогнозирования и их матрице путаницы.

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer,TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline

categories = ['alt.atheism', 'soc.religion.christian',
              'comp.graphics', 'sci.med']
if 'predicted' not in dir() :
	twenty_train=load_files('/mnt/vol0/sklearn/20news-bydate-train',categories=categories,  load_content = True, 
	                           encoding='latin1', decode_error='strict',shuffle=True, random_state=42)
	twenty_test=load_files('/mnt/vol0/sklearn/20news-bydate-test',categories=categories,  load_content = True, 
	                           encoding='latin1', decode_error='strict',shuffle=True, random_state=42)
	docs_test = twenty_test.data
	from sklearn.linear_model import SGDClassifier
	text_clf = Pipeline([('vect', CountVectorizer()),
	                     ('tfidf', TfidfTransformer()),
	                     ('clf', SGDClassifier(loss='hinge', penalty='l2',
	                                           alpha=1e-3, n_iter=5, random_state=42)),
	])
	_ = text_clf.fit(twenty_train.data, twenty_train.target)
	predicted = text_clf.predict(docs_test)
from sklearn import metrics
print("打印分类性能指标:")
print(metrics.classification_report(twenty_test.target, predicted,
    target_names=twenty_test.target_names))
print("打印混淆矩阵:")
metrics.confusion_matrix(twenty_test.target, predicted)

Неудивительно, что матрица смешения показывает, что две категории, связанные с атеизмом (alt.atheism) и христианством (soc.religion.christian), различить труднее, чем с компьютерной графикой (comp.graphics).

矩阵往往是一种很有用的分析工具

Оптимизация параметров с помощью поиска по сетке

Мы видели много параметров, встречающихся в процессе машинного обучения, таких какTfidfTransformerсерединаuse_idf. Классификаторы, как правило, имеют много параметров, например, наивный алгоритм Байеса содержит гладкие параметры.alpha, алгоритм SVM будет включать параметр штрафаalphaи некоторые другие функции, которые можно настроить.

Чтобы избежать сложной работы, связанной с настройкой этого ряда параметров, мы можем использовать метод поиска по сетке, чтобы найти оптимальное значение каждого параметра. Как показано в примере ниже, мы можем попробовать установить следующие параметры при построении классификатора с использованием алгоритма SVM: использовать слова или фразы, использовать IDF или не использовать IDF, а параметр штрафа равен 0,01 или 0,001.

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer,TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline

categories = ['alt.atheism', 'soc.religion.christian',
              'comp.graphics', 'sci.med']
if 'text_clf' not in dir() :
	twenty_train=load_files('/mnt/vol0/sklearn/20news-bydate-train',categories=categories,  load_content = True, 
	                           encoding='latin1', decode_error='strict',shuffle=True, random_state=42)
	twenty_test=load_files('/mnt/vol0/sklearn/20news-bydate-test',categories=categories,  load_content = True, 
	                           encoding='latin1', decode_error='strict',shuffle=True, random_state=42)
	docs_test = twenty_test.data
	from sklearn.linear_model import SGDClassifier
	text_clf = Pipeline([('vect', CountVectorizer()),
	                     ('tfidf', TfidfTransformer()),
	                     ('clf', SGDClassifier(loss='hinge', penalty='l2',
	                                           alpha=1e-3, n_iter=5, random_state=42)),
	])
from sklearn.grid_search import GridSearchCV
# sklearn 0.18.1 版本请使用以下方式导入网格搜索库
# from sklearn.model_selection import GridSearchCV

# 设置参与搜索的参数
parameters = {'vect__ngram_range': [(1, 1), (1, 2)],
              'tfidf__use_idf': (True, False),
              'clf__alpha': (1e-2, 1e-3),
}

# 构建分类器
gs_clf = GridSearchCV(text_clf, parameters, n_jobs=-1)
print(gs_clf)

Очевидно, что выполнение такого процесса поиска по одному требует больших вычислительных ресурсов. Если у нас многоядерная процессорная платформа, мы можем вычислить эти 8 задач параллельно (каждый параметр имеет два значения, а три параметра имеют в сумме2^3=8комбинация параметров), что требует от нас измененияn_jobsэтот параметр. Если мы установим значение этого параметра равным-1, процесс поиска по сетке автоматически определит количество ядер ЦП, присутствующих в вычислительной среде, и использует все ядра для параллельной работы.

Конкретная модель поиска по сетке согласуется с общей моделью классификатора, и мы можем использовать меньший блок подданных для ускорения процесса обучения модели. правильноGridSearchCVвызов объектаfitЗатем метод получит классификатор, аналогичный предыдущему случаю, который мы можем использовать для прогнозирования.

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer,TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
from sklearn.grid_search import GridSearchCV

categories = ['alt.atheism', 'soc.religion.christian',
              'comp.graphics', 'sci.med']
if 'gs_clf' not in dir() :
	twenty_train=load_files('/mnt/vol0/sklearn/20news-bydate-train',categories=categories,  load_content = True, 
	                           encoding='latin1', decode_error='strict',shuffle=True, random_state=42)
	twenty_test=load_files('/mnt/vol0/sklearn/20news-bydate-test',categories=categories,  load_content = True, 
	                           encoding='latin1', decode_error='strict',shuffle=True, random_state=42)
	docs_test = twenty_test.data
	from sklearn.linear_model import SGDClassifier
	text_clf = Pipeline([('vect', CountVectorizer()),
	                     ('tfidf', TfidfTransformer()),
	                     ('clf', SGDClassifier(loss='hinge', penalty='l2',
	                                           alpha=1e-3, n_iter=5, random_state=42)),
	])
	parameters = {'vect__ngram_range': [(1, 1), (1, 2)],
	              'tfidf__use_idf': (True, False),
	              'clf__alpha': (1e-2, 1e-3),
	}
	gs_clf = GridSearchCV(text_clf, parameters, n_jobs=-1)
# 使用部分训练数据训练分类器
gs_clf = gs_clf.fit(twenty_train.data[:400], twenty_train.target[:400])
# 查看分类器对于新文本的预测结果,你可以自行改变下方的字符串来观察分类效果
twenty_train.target_names[gs_clf.predict(['An apple a day keeps doctor away'])[0]]

Классификатор также содержитbest_score_иbest_params_Два свойства, эти два свойства содержат наилучший результат прогнозирования и конфигурацию параметров, при которой получается наилучший результат прогнозирования. Конечно, мы также можем просмотретьgs_clf.cv_results_Чтобы получить более подробные результаты поиска (это новая функция в sklearn 0.18.1), этот параметр можно легко импортировать в pandas для более глубокого исследования.

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer,TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
from sklearn.grid_search import GridSearchCV

categories = ['alt.atheism', 'soc.religion.christian',
              'comp.graphics', 'sci.med']
if 'gs_clf' not in dir() :
	twenty_train=load_files('/mnt/vol0/sklearn/20news-bydate-train',categories=categories,  load_content = True, 
	                           encoding='latin1', decode_error='strict',shuffle=True, random_state=42)
	twenty_test=load_files('/mnt/vol0/sklearn/20news-bydate-test',categories=categories,  load_content = True, 
	                           encoding='latin1', decode_error='strict',shuffle=True, random_state=42)
	docs_test = twenty_test.data
	from sklearn.linear_model import SGDClassifier
	text_clf = Pipeline([('vect', CountVectorizer()),
	                     ('tfidf', TfidfTransformer()),
	                     ('clf', SGDClassifier(loss='hinge', penalty='l2',
	                                           alpha=1e-3, n_iter=5, random_state=42)),
	])
	parameters = {'vect__ngram_range': [(1, 1), (1, 2)],
	              'tfidf__use_idf': (True, False),
	              'clf__alpha': (1e-2, 1e-3),
	}
	gs_clf = GridSearchCV(text_clf, parameters, n_jobs=-1)
gs_clf = gs_clf.fit(twenty_train.data[:400], twenty_train.target[:400])
print("最佳准确率:%r" % (gs_clf.best_score_))

for param_name in sorted(parameters.keys()):
    print("%s: %r" % (param_name, gs_clf.best_params_[param_name]))

резюме

На данный момент мы полностью отработали весь процесс использования методов машинного обучения для классификации текста, узнали о получении данных из сети и чтении, очистке исходных данных и извлечении векторов признаков, использовании различных алгоритмов для построения классификаторов и использовании Grid. метод поиска для настройки параметров и другие общие моменты в контролируемом машинном обучении. Более сложные вопросы, такие как обработка китайского текста, кластеризация текста и т. д., мы обсудим в последующих статьях.


(Содержание этого курса взято изScikit-Learn - Working With Text Data,Если воспроизводится, укажите источник. )


Рекомендуемое чтение

Поддразнивание мошенников электронной почты с помощью PaddlePaddle (конец)

Этот комментарий ядовит! ——Общая процедура для классификации текста

Я сделал робота по имени Серсея, но она просто хотела, чтобы сир Грегор убивал меня на каждом шагу.