С нарастването на рекламите и студените съобщения сега получаваме непрекъснати кохерентни нишки от търговски съобщения и имейли. Потребител, като вас и мен, понякога се затруднява да намери текст/имейл, който наистина е полезен за нас или този, който търсим. Игла в купа сено. Хамовете сред спамовете.

Системите за откриване, като например системата за откриване на спам, стават все по-полезни за класифицираневажните данни сред пакета необработени и нежелани данни. В тази публикация ще разгледаме един такъв модел за откриване, модел за откриване на спам, използващ NLP (обработка на естествен език), а също така ще научим за класификацията с помощта на Naive Bayes.

ПРЕДПОСТАВКИ

  1. NLTK модул
import nltk
nltk.download("all")

2. Наивна теорема на Бейс:

P(h|d) = (P(d|h) * P(h)) / P(d)

Където

  • P(h|d) е вероятността за хипотеза h при дадени данни d. Това се нарича постериорна вероятност.
  • P(d|h) е вероятността за данни d при условие, че хипотезата h е вярна.
  • P(h) е вероятността хипотезата h да е вярна (независимо от данните). Това се нарича предварителна вероятност за h.
  • P(d) е вероятността на данните (независимо от хипотезата).

Можете да видите, че се интересуваме от изчисляването на последващата вероятност за P(h|d) от предходната вероятност p(h) с P(D) и P(d|h).

Импортиране на данните:

UCI разполага с наличен набор от данни от повече от 5000 смесени текстови съобщения, щракнете тук.

data = pd.read_csv('./spam.csv', encoding='latin-1')
data = data.drop(labels = ['Unnamed: 1', 'Unnamed: 2', 'Unnamed: 3', 'Unnamed: 4']
display(data.head(n = 10))

Анализиране на данните

Една от най-важните стъпки в науката за данните е винаги да четете, научавате и разбирате данните, които са били осигурени или предоставени. Тук ще приложим същата фундаментална стъпка и ще открием разпространението на радиолюбители и спам съобщения в набора от данни.

data['category'].value_counts().plot(kind = 'pie', explode=[0,0,1], figsize=(5,5), autopct = '%1.1f%%', shadow=True)
plt.ylabel("Spam Vs Ham")
plt.legend(["Ham", "Spam"])
plt.show()

Фигурата показва, че в нашия набор от данни споменатото разпределение е 86,6% -13,4%.

Продължавайки напред, ще се опитаме да генерираме функции, които под капака на науката за данни са известни също като инженерство на функции.

topmessages = data.groupby("text")["category"].agg([len, np.max]).sort_values(by='len', ascending='False').head(n=10)
display(topmessages)

Начинът, по който разбираме това, е, че очевидно спамовете са по-дълги от радиолюбителите. И също така „len“ в тази функция означава честотата, броя на срещанията на този конкретен текст. Какво ще кажете да създадем функция, която показва честотата на повтарящите се думи? Но отново тук трябва да направим нещо преди това. И това е премахване на стоп думите.

from nltk.tokenize import word_tokenize
spam_messages = data[data[‘category’] == “spam”][“text”]
ham_messages = data[data[‘category’] == “ham”][“text”]
spam_words = []
ham_words = []
def extractSpamWords(spamMessages):
 global spam_words
 words = [word.lower() for word in word_tokenize(spamMessages) if word.lower() not in stopwords.words(“english”) and word.lower().isalpha()]
 spam_words = spam_words + words
def extractHamWords(hamMessages):
 global ham_words
 words = [word.lower() for word in word_tokenize(hamMessages) if word.lower() not in stopwords.words(“english”) and word.lower().isalpha()]
 ham_words = ham_words + words
 
spam_messages.apply(extractSpamWords)
ham_messages.apply(extractHamWords)

Стоп-думите са думите на който и да е език, които не добавят голямо значение към изречението. Напр.: the, a, an, is, be и т.н. Правейки това, ние намаляваме вероятността от неточности в нашите данни. Сега можем лесно да намерим думите, които всъщност са честотни и в двата случая.

Освен това ще трябва да токенизирамеданните. Това, което имаме предвид под това, е разделянето на част от текста на по-малки части, като изречения и думи. Оттук и думата токен. Например една дума е лексема в изречение, а изречението е лексема в абзац.

from wordcloud import WordCloud
spam_wordcloud = WordCloud(width=1000, height=400).generate(" ".join(spam_words)
plt.figure(figsize=(10,6), facecolor='k')
plt.imshow(spam_wordcloud)
plt.axis("off")
plt.tight_layout(pad=0)
plt.show()

По същия начин за шунка:

И двата „облака от думи“ ни показват думите, които често се срещат в шунка и спам текстове. Сега нека извлечем горните думи и в двата случая:

spam_words = np.array(spam_words)
print(“Top 10 Spam words are :\n”)
pd.Series(spam_words).value_counts().head(n=10)

По същия начин за шунка:

Нека видим визуално дължината на текста и в двата случая:

f, ax = plt.subplots(1, 2, figsize = (20,6))
sns.distplot(data[data[“category”]==”spam”][“messagesLength”], bins=20, ax=ax[0])
ax[0].set_xlabel(“Spam Message Word Length”)
sns.distplot(data[data[“category”] == “ham”][“messagesLength”], bins = 20, ax = ax[1])
ax[0].set_xlabel(“Ham Message Word Length”)
plt.show()

да Сега можем да видим ясно, че СПАМ съобщенията са по-дълги, което имайте предвид, че също е функция.

STEMMER

Стимулирането е техника за извличане на основната форма на всяка дума. Например основната дума за шоколадов е шоколад.

Съществуват различни алгоритми за стеминг.

В този проект ще използваме снежната топка, но можете да експериментирате с други.

from nltk.stem import SnowballStemmer
stemmer = SnowballStemmer(“english”)
def cleanText(message):
 message = message.translate(str.maketrans(‘’, ‘’, string.punctuation))
 words = [stemmer.stem(word) for word in message.split() if word.lower() not in stopwords.words(“english”)]
 
 return “ “.join(words)
messages[“text”] = messages[“text”].apply(cleanText)
messages.head(n=10)

Ако не бъде забелязано, след като приложим нашия stemmer алгоритъм, всички препинателни знаци се премахват и само думите в основната им форма остават в данните. Това е важно. Моделите за машинно обучение са надеждни само толкова, колкото и чистите данни. Ние не изискваме нищо допълнително или по-малко в нашите данни. Причината е, че данните всъщност са това, което нашият модел за машинно обучение взема, за да „научи“ и след това да изпълни и да даде желания резултат. На същата бележка също трябва да преобразуваме нашите данни във формата, която моделът на машинно обучение ще разбере, т.е. във векторна форма. Това, което ще направим, е да конвертираме нашите данни, думите във векторни форми. Тези вектори няма да бъдат нищо друго освен честотата на думите в нашите данни.

Test-Train split, модел и валидиране

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(features,messages[“category”], stratify=messages[“category”], test_size=0.2)
from sklearn.model_selection import cross_val_score
from sklearn.metrics import fbeta_score
from sklearn.naive_bayes import MultinomialNB
gaussianNb = MultinomialNB()
gaussianNb.fit(X_train, y_train)
y_pred = gaussianNb.predict(X_test)
print(fbeta_score(y_test, y_pred, beta=0.5))

Това ще бъде последното действие в нашия проект. Ще разделим данните на обучителни и тестови групи. Данни за обучение за обучение на нашия модел и оставяне да се учи. Следователно трябва да се уверим, че докато разделяме данните за обучение, съдържат нежелана поща, както и радиолюбители, така че нашият модел да може да прави разлика между двете много точно. Тук правим 80-20 разделение съответно между обучение и тест. Накрая ще създадем нашия модел на Naive Bayes. Всъщност има 3 различни алгоритъма на Naive Bayes.

  1. Gaussian: Обикновено се използва за проблеми с нормална класификация.
  2. Многочлен: Използва се за срещания на думи.
  3. Бернули: Проблеми с двоична класификация.

Тук ще използваме Multinomial, тъй като по време на стъпката на генериране на функция създаваме честотна характеристика, която ще бъде полезна тук. И отново, не се колебайте да експериментирате с други алгоритми. За да потвърдим ефективността на нашия модел, ние използваме тук fbeta резултат, известен също като f1 резултат.

Следва продължение...

Надяваме се, че сте намерили тази публикация за полезна и информативна. Ако го направи и даде някаква стойност, моля, коментирайте/споделете. Коментирайте и вашите лични отзиви. Това е част 1/2 от моята публикация за класификация на текста и анализ на настроението. Останете на линия!