You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

229 lines
12 KiB
Markdown

3 years ago
# Лабораторная работа 2. «Предобработка и классификация данных социальных сетей»
[назад](README.md)
## 1. Предварительная обработка данных
Лабораторная работа выполняется с использованием языка программирования Python. В случае отсутствия данного программного обеспечения на компьютере необходимо перейти на официальный сайт и скачать последнюю версию Python. Далее установить Python на компьютер следуя указаниям мастера установки.
Первый этапом данной лабораторной работы является удаление всех сторонних полей с оставлением лишь полезной информации.
Для этого необходимо загрузить скаченный в предыдущей лабораторной работе файл данных из социальной сети VK и извлечь необходимое поле text.
```python
all_wall = []
file = open(r" wall_asp.txt")
for line in file.readlines():
string = line
wall = json.loads(string)
json_decode = json.JSONDecoder()
parsed_response = json_decode.decode(json.dumps(wall))
nodes = parsed_response.get('items')
for node in nodes:
all_wall.append(node.get("text"))
```
## 2. Подсчет слов в собранных текстовых данных
Задание включает в себя реализацию алгоритма WordCount. Это одна из самых простых и тривиальных задач машинного обучения. Она заключается в разбиении текста на слова, а также подсчёт их количества.
Добавим в имеющийся код следующие строки
```python
wordcount={}
for wall in all_wall:
for word in wall.split():
if word not in wordcount:
wordcount[word] = 1
else:
wordcount[word] += 1
try:
for wc in wordcount:
print(wc, wordcount[wc])
except Exception:
k=1
```
В результате перезапуска программы можно увидеть в консоли множество сочетаний вида «значение, ключ».
## 3. Кластеризация текстовых данных
Следующей задачей является кластеризация текстовых данных.
В области анализа данных широко распространена задача разделения множества объектов на подмножества таким образом, чтобы все объекты каждого подмножества имели больше сходства друг с другом, чем с объектами других подмножеств.
Данная задача находит широкое практическое применение. Например, в области медицины алгоритм кластеризации может помочь идентифицировать центры клеток на изображении группы клеток. Используя GPS-данные мобильного устройства, можно определить наиболее посещаемые пользователем места в пределах определенной территории.
В рамках текущей задачи создадим новый файл и импортируем необходимые библиотеки.
```python
import numpy as np
import pandas as pd
import nltk
import re
import os
import codecs
import matplotlib.pyplot as plt
import matplotlib as mpl
```
Необходимо считать данные в массив, а далее приступить к нормализации приведению слова к начальной форме. Это можно сделать несколькими способами, используя стеммер Портера, стеммер `MyStem` и `PyMorphy2`. Стоит отметить `MyStem` работает через wrapper, поэтому скорость выполнения операций очень медленная. Предлагается использовать стеммер Портера, хотя можно использовать другие и комбинировать их с друг другом (например, сначала пройтись `PyMorphy2`, а после стеммером Портера).
```python
print(str(len(all_wall)) + ' запросов считано')
from nltk.stem.snowball import SnowballStemmer
stemmer = SnowballStemmer("russian")
#nltk.download()
3 years ago
3 years ago
def token_and_stem(text):
3 years ago
tokens = [word for sent in nltk.sent_tokenize(text) for word in nltk.word_tokenize(sent)]
filtered_tokens = []
for token in tokens:
if re.search('[а-яА-Я]', token):
filtered_tokens.append(token)
stems = [stemmer.stem(t) for t in filtered_tokens]
return stems
3 years ago
def token_only(text):
3 years ago
tokens = [word.lower() for sent in nltk.sent_tokenize(text) for word in nltk.word_tokenize(sent)]
filtered_tokens = []
for token in tokens:
if re.search('[а-яА-Я]', token):
filtered_tokens.append(token)
return filtered_tokens
3 years ago
3 years ago
#Создаем словари (массивы) из полученных основ
totalvocab_stem = []
totalvocab_token = []
for i in all_wall:
allwords_stemmed = token_and_stem(i)
#print(allwords_stemmed)
totalvocab_stem.extend(allwords_stemmed)
allwords_tokenized = token_only(i)
totalvocab_token.extend(allwords_tokenized)
```
Создадим матрицу весов TF-IDF. Будем считать каждый поисковой запрос за документ (так делают при анализе постов в Twitter, где каждый твит это документ). `tfidf_vectorizer` возьмем из пакета `sklearn`, а стоп-слова выберем из корпуса `ntlk` (изначально придется скачать через `nltk.download()`). Параметры можно подстроить от верхней и нижней границы до количества `n-gram` (в данном случае возьмем 3).
```python
stopwords = nltk.corpus.stopwords.words('russian')
#можно расширить список стоп-слов
3 years ago
stopwords.extend(['что', 'это', 'так', 'вот', 'быть', 'как', 'в', 'к', 'на'])
3 years ago
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer
n_featur=200000
tfidf_vectorizer = TfidfVectorizer(max_df=0.8,
max_features=10000,
stop_words=stopwords,
min_df=0.01,
use_idf=True,
tokenizer=token_and_stem,
ngram_range=(1,3)
)
tfidf_matrix = tfidf_vectorizer.fit_transform(all_wall)
print(tfidf_matrix.shape)
```
Над полученной матрицей начинаем применять различные методы кластеризации.
```python
num_clusters = 5
# Метод к-средних - KMeans
from sklearn.cluster import KMeans
km = KMeans(n_clusters=num_clusters)
km.fit(tfidf_matrix)
idx = km.fit(tfidf_matrix)
clusters = km.labels_.tolist()
print(clusters)
print (km.labels_)
# MiniBatchKMeans
from sklearn.cluster import MiniBatchKMeans
3 years ago
mbk = MiniBatchKMeans(init='random', n_clusters=num_clusters) #(init='k-means++',random or an ndarray)
3 years ago
mbk.fit_transform(tfidf_matrix)
mbk.fit(tfidf_matrix)
miniclusters = mbk.labels_.tolist()
print (mbk.labels_)
# DBSCAN
from sklearn.cluster import DBSCAN
db = DBSCAN(eps=0.3,
min_samples=10).fit(tfidf_matrix)
labels = db.labels_
labels.shape
print(labels)
# Аггломеративная класстеризация
from sklearn.cluster import AgglomerativeClustering
agglo1 = AgglomerativeClustering(
n_clusters=num_clusters,
affinity='euclidean') #affinity можно выбрать любое или попробовать все по очереди: cosine, l1, l2, manhattan
answer = agglo1.fit_predict(tfidf_matrix.toarray())
answer.shape
```
Полученные данные можно сгруппировать в `dataframe` и посчитать количество запросов, попавших в каждый кластер.
```python
#k-means
clusterkm = km.labels_.tolist()
#minikmeans
clustermbk = mbk.labels_.tolist()
#dbscan
clusters3 = labels
#agglo
#clusters4 = answer.tolist()
frame = pd.DataFrame(all_wall, index = [clusterkm])
#k-means
out = { 'title': all_wall, 'cluster': clusterkm }
frame1 = pd.DataFrame(out, index = [clusterkm],
columns = ['title', 'cluster'])
#mini
out = { 'title': all_wall, 'cluster': clustermbk }
frame_minik = pd.DataFrame(out, index =
[clustermbk], columns = ['title', 'cluster'])
frame1['cluster'].value_counts()
frame_minik['cluster'].value_counts()
```
3 years ago
Из-за большого количества запросов не совсем удобно смотреть таблицы и хотелось бы больше интерактивности для понимания. Поэтому сделаем графики взаимного расположения запросов друг относительного друга. Сначала необходимо вычислить расстояние между векторами. Для этого можно применить косинусное расстояние.
3 years ago
Так как графики будут двух- и трехмерные, а исходная матрица расстояний n-мерная, то придется применять алгоритмы снижения размерности. На выбор есть много алгоритмов (MDS, PCA, t-SNE), но остановим выбор на Incremental PCA. Этот выбор сделан вследствие выигрыша данного алгоритма в ресурсоемкости.
Алгоритм Incremental PCA используется в качестве замены метода главных компонентов (PCA), когда набор данных, подлежащий разложению, слишком велик, чтобы разместиться в оперативной памяти. IPCA создает низкоуровневое приближение для входных данных, используя объем памяти, который не зависит от количества входных выборок данных.
```python
3 years ago
from sklearn.metrics.pairwise import cosine_similarity
dist = cosine_similarity(tfidf_matrix)
3 years ago
dist.shape
3 years ago
# Метод главных компонент - PCA
3 years ago
from sklearn.decomposition import IncrementalPCA
3 years ago
icpa = IncrementalPCA(n_components=2, batch_size=16)
3 years ago
icpa.fit(dist)
demo2 = icpa.transform(dist)
xs, ys = demo2[:, 0], demo2[:, 1]
3 years ago
3 years ago
# PCA 3D
from sklearn.decomposition import IncrementalPCA
3 years ago
icpa = IncrementalPCA(n_components=3,batch_size=16)
3 years ago
icpa.fit(dist)
ddd = icpa.transform(dist)
xs, ys, zs = ddd[:, 0], ddd[:, 1], ddd[:, 2]
3 years ago
3 years ago
#Можно сразу примерно посмотреть, что получится в итоге
3 years ago
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(xs, ys, zs)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()
3 years ago
```