Найти тему

Базовая обработка естественного языка за 30 мин (БЕЗ BS)

Миссия: Разработать классификатор, чтобы определить, является ли фильм Свежим или гнилым, основываясь на отзывах, данных о фильме.

Модель прогнозирования: Наивный Байес

Одной из самых важных вспомогательных функций здесь является CountVectorizer, он преобразует необработанный текст в " мешок слов’ векторов.

По определению, вектор " ЛУК " - это структура данных, которая сообщает вам, сколько раз конкретное слово появляется в рекламном объявлении.

from sklearn.feature_extraction.text import CountVectorizertext = ['machine learning rocks', 'machine learning rules', 'rocks rocks rules']print("Original text is:-\n", '\n'.join(text))
print()vectorizer = CountVectorizer(min_df=0)# call `fit` to build the vocabulary
vectorizer.fit(text)# call `transform` to convert text to a bag of words
x = vectorizer.transform(text)# CountVectorizer uses a sparse array to save memory, but it's easier in this assignment to
# convert back to a "normal" numpy array
x = x.toarray()print("Transformed text vector is \n", x)
print()
# `get_feature_names` tracks which word is associated with each column of the transformed x
print("Words for each feature:-")
print(vectorizer.get_feature_names())

При выполнении описанной выше функции ожидаемый результат будет следующим:

-2

Теперь предположим, что у нас есть входная матрица X(n review, n words) и вектор y(n review), оба они являются массивом:

X: каждая строка соответствует представлению пакета слов для одного обзора (вход)

y: кодирование того, является ли обзор свежим(1) или гнилым(0) (Вывод)

Примечание: убедитесь, что X и y имеют одинаковое измерение в строке (обзор)

Следующий шаг-выполнить разделение тестового поезда (80%/20%) следующим образом:

X_train, X_test, y_train, y_test= train_test_split(X, Y, test_size= .2, random_state = 42, stratify= Y)

Время реализации MultinomialNB (используйте только обучающий набор для обучения вашей модели ), здесь мы используем accuracy_score в качестве целевой функции.

from sklearn.metrics import accuracy_scoreclf = MultinomialNB()
clf.fit(X_train, y_train)
y_train_pred = clf.predict(X_train)
y_test_pred = clf.predict(X_test)
train_pred_score = accuracy_score(y_train, y_train_pred)
test_pred_score = accuracy_score(y_test, y_test_pred)print('Training Set Accuracy Score: \n', (100 * train_pred_score))
print('Testing Set Accuracy Score: \n', (100 * test_pred_score))

-3

Вуаля, это почти слишком просто, не так ли?

Однако мы хотим оптимизировать модель. Наши методы имеют несколько гиперпараметров, и это значения, которые мы хотим настроить с помощью перекрестной проверки.

  1. min_df в CountVectorizer, который игнорирует слова, которые появляются в меньшей, чем min_df, доле отзывов.
  2. альфа в MultinomialNB, известном как “параметр сглаживания” — увеличение значения уменьшает чувствительность к любому отдельному признаку и имеет тенденцию приближать вероятность предсказания к 50%

Прежде чем мы проведем перекрестную проверку, нам нужно понять, что определяет " лучшее’ значение параметра.

Цель: найти значение, которое максимизирует логарифмическую вероятность наших данных.

-4

В этом случае мы имеем целевую функцию:

L = Sum_fresh(logo(fresh)) + Some_rotten(log(rotten))

Зачем использовать log_likelibility:

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

С этой интуицией нам нужна логоподобная функция, и вот она!

def log_likelihood(model, x, y):
prob = model.predict_log_proba(x)
rotten = y == 0
fresh = ~rotten
return prob[rotten, 0].sum() + prob[fresh, 1].sum()# output the likelihood of test data
log_likelihood(clf, X_test, y_test)

Теперь у вас есть все части, время показать вам какой-то код!

alphas = [0, 1, 5, 10, 50]
min_dfs = [0.0001,0.001,0.01, 0.1, 0.2] min_df, and the best classifier
best_alpha = None
best_min_df = None
max_loglike = -np.inffor alpha in alphas:

print('alpha is : ' + str(alpha))

for min_df in min_dfs:

print('min_df is : ' + str(min_df))

''initialize vecotizer
vectorizer = CountVectorizer(min_df = min_df)
X = vectorizer.fit_transform(x)

X = X.toarray()
Y = y.to_numpy()

''train test split
X_train, X_test, y_train, y_test= train_test_split(X, Y, test_size= .2, random_state = 42, stratify= Y)

''initialize NB model
clf = MultinomialNB(alpha = alpha) ''cross validating the NB model using 5 cv
score = cross_val_score(clf, X_train, y_train, cv=5, scoring = log_likelihood)

print('log scores: {:.2f}'.format(np.mean(score)))

''updating the best parameters
if np.mean(score) > max_loglike:
max_loglike = np.mean(score)
best_alpha = alpha
best_min_df = min_dfprint("best alpha, best min_dfs: ",best_alpha, best_min_df)
-5

Теперь мы можем обучить окончательную модель , используя best_alpha, best_min_df, и повторно оценить точность на обучающих и тестовых наборах.

best_alpha = 5
best_min_df = 0.001 ''final vectorizer model and X, Y data
vectorizer_final = CountVectorizer(min_df = best_min_df)X = vectorizer_final.fit_transform(X)
X = X.toarray()
Y = y.to_numpy() ''train-test split
X_train_final, X_test_final, y_train_final, y_test_final = train_test_split(X, Y, test_size= .2, random_state = 42, stratify= Y_final)#fit NB model on the training datasets
clf_final = MultinomialNB(alpha = best_alpha)
clf_final.fit(X_train_final, y_train_final)#predict y on training data
y_train_pred = clf_final.predict(X_train_final)#predict y on testing data
y_test_pred = clf_final.predict(X_test_final)#accuracy score for training and testing predictions
test_pred_score = accuracy_score(y_test_final, y_test_pred)
train_pred_score = accuracy_score(y_train_final, y_train_pred)print('Training set Accuracy Score: \n', (100 * train_pred_score))
print('Testing set Accuracy Score: \n', (100 * test_pred_score))
-6

Теперь у нас есть базовая наивная модель Байеса, простая, но эффективная.

Мораль в том, что всегда сначала пробуйте простые вещи.

Мы можем попробовать пройти обзор и попросить модель предсказать, является ли фильм "Гнилым" или "Свежим".

В этом примере тестовый обзор, который мы используем, звучит так: “Этот фильм ничем не примечателен, трогателен или превосходен”

''predict the probability of a given reviewdef predict_prob(s, model=clf_final):
s_tf = vectorizer_final.transform([s]).toarray()
proba_s = model.predict_proba(s_t)

return proba_spredict_prob("This movie is not remarkable, touching, or superb in any way")

Учитывая вероятность корреспондента [Гнилой, Свежий], эта модель фактически выдает неправильный ответ; потому что чувство положительных слов перевешивает отрицательное ключевое слово " не’. Такие слова, как “но”, “не” и т. Д.

Однако, поскольку наивный Байес рассматривает каждое слово отдельно, он не способен уловить такого рода словесные взаимодействия.

Зависимости между атрибутами неизбежно уменьшают способность Наивного Байеса различать, что происходит.