Повышение точности категоризации текста (в настоящее время 62% для наивного Байеса и SVM) - PullRequest
0 голосов
/ 10 мая 2018

У меня есть такой набор данных:

COD| COMPDESC|    CDESCR
0|   10|  STRUCTURE:BODY:DOOR| AUTOMATIC DOOR LOCKS WHEN USED, WILL NOT RELEA...
1|   18|  VEHICLE SPEED CONTROL|   VEHICLE SUDDENLY ACCELERATED OUT OF CONTROL, B...
2|   24|  STEERING:WHEEL AND HANDLE BAR|   STEERING WHEEL BOLTS LOOSENEDAND ROCKED BACK A...
3|   40|  SUSPENSION:FRONT:MACPHERSON STRUT|   MISALIGNMENT, CAUSING VEHICLE TO PULL TO THE R...
4|   55|  STEERING:WHEEL AND HANDLE BAR|   DUE TO DEFECT STEERING BOLTS, STEERING WHEEL I...

Я пытался использовать Наивный Байес и SVM для прогнозирования после использования NLTK для определения и применения CountVectorizer, но прогноз намного ниже, чем этот статья , в которой используется набор данных, содержащий всего 20 000 строк (у моей - 1 миллион, но я могу использовать только 100 000 строк за раз из-за ограничений памяти).

Я пробовал с ngram-range: (1,1) и ngram-range: (1,2)и результаты были почти одинаковыми.И последнее, требовало больше памяти, поэтому мне пришлось уменьшить количество обрабатываемых строк.

Что я могу сделать, чтобы улучшить эту точность?Улучшение очистки данных может быть способом, но с помощью чего еще?Учитывая, что я уже использую Stemming и удаляю стоп-слова (включая цифры).

# The row indices to skip - make sure 0 is not included to keep the header!
skip_idx = random.sample(range(1, num_lines), num_lines - size)

dataset = pd.read_csv('SIMPLE_CMPL.txt', skiprows=skip_idx,
                      delimiter=',', quoting=True, header=0, encoding="ISO-8859-1",
                      skip_blank_lines=True)

train_data, test_data = train_test_split(dataset, test_size=0.3)

from sklearn.feature_extraction import text 
import string
my_stop_words = text.ENGLISH_STOP_WORDS.union(["tt",'one','two','three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', '0','1','2','3','4','5','6','7','8','9','0']).union(string.punctuation)

# Stemming Code
from nltk.stem.snowball import SnowballStemmer
stemmer = SnowballStemmer("english", ignore_stopwords=True)

class StemmedCountVectorizer(CountVectorizer):
    def build_analyzer(self):
        analyzer = super(StemmedCountVectorizer, self).build_analyzer()
        return lambda doc: ([stemmer.stem(w) for w in analyzer(doc)])

stemmed_count_vect = StemmedCountVectorizer(stop_words=my_stop_words, ngram_range=(1,2))

text_mnb_stemmed = Pipeline([('vect', stemmed_count_vect), ('tfidf', TfidfTransformer(use_idf=False)), 
                             ('mnb', MultinomialNB(fit_prior=False, alpha=0.01))])

text_mnb_stemmed = text_mnb_stemmed.fit(train_data['CDESCR'], train_data['COMPID'])

predicted_mnb_stemmed = text_mnb_stemmed.predict(test_data['CDESCR'])

np.mean(predicted_mnb_stemmed == test_data['COMPID'])


# 0.6255




# Stemming Code
from sklearn.linear_model import SGDClassifier
from nltk.stem.snowball import SnowballStemmer
stemmer = SnowballStemmer("english", ignore_stopwords=True)

class StemmedCountVectorizer(CountVectorizer):
    def build_analyzer(self):
        analyzer = super(StemmedCountVectorizer, self).build_analyzer()
        return lambda doc: ([stemmer.stem(w) for w in analyzer(doc)])

stemmed_count_vect = StemmedCountVectorizer(stop_words=my_stop_words, ngram_range=(1,1))

text_svm_stemmed = Pipeline([('vect', stemmed_count_vect), ('tfidf', TfidfTransformer(use_idf=True)), 
                             ('clf-svm', SGDClassifier(loss='hinge', penalty='l2',alpha=0.001, n_iter = np.ceil(10**6 / train_data['COD'].count()), random_state=60))])

text_svm_stemmed = text_svm_stemmed.fit(train_data['CDESCR'], train_data['COMPID'])

predicted_svm_stemmed = text_svm_stemmed.predict(test_data['CDESCR'])

np.mean(predicted_svm_stemmed == test_data['COMPID'])


#0.6299

1 Ответ

0 голосов
/ 11 мая 2018

прогноз гораздо ниже, чем в этой статье, в которой используется набор данных, содержащий всего 20 000 строк

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

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

Что я могу сделать, чтобы улучшить эту точность?Улучшение очистки данных может быть способом, но с помощью чего еще?Учитывая, что я уже использую Stemming и удаляю стоп-слова (включая цифры).

Априори может показаться, что остановка и удаление чисел помогут вашему счету - но вы на самом деле этого не знаете.Иногда такие функции могут помочь модели.Вместо того, чтобы заранее решить, какие значения использовать для ngram_range, stop_words и (что наиболее важно) alpha и т. Д., Эти значения должны быть определены путем перекрестной проверки.Ссылка на статью показывает, как это сделать.Я бы также взглянул на пример в документации sklearn GridSearchCV .

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...