K-meansクラスタリングでテキストの一覧を分類

# 概要
特に外向けに難しいことを発信しようとしたわけでもなく、今後もたまに使いそうだと思った備忘、そのいくつか。

手っ取り早い機械学習のあるあるだと思うのですが、ズラーっとテキストデータの一覧があって、それをざっくり分類分けしたい、なときに使えそうなもの。

あまり複雑に作り込まず、そこにフォーカスして手元で実行できるようにやってみました。

# やったこと
* K-meansクラスタリングを用いて、テキストデータの一覧CSVファイルの各行を分類するスクリプトを作成
* 使ったテキストデータの一覧は
    * ファイル名：sample.csv
    * 内容：「text」の項目一列で構成されたシンプルなもの

## 環境
たぶんすぐやるなら以下一択だったとは思いますが念のため補足がてら。

* 言語：python
* ライブラリ：scikit-learn

https://udemy.benesse.co.jp/development/python-work/scikit-learn.html#:~:text=scikit%2Dlearn%EF%BC%88%E3%82%B5%E3%82%A4%E3%82%AD%E3%83%83%E3%83%88%E3%83%BB%E3%83%A9%E3%83%BC%E3%83%B3%EF%BC%89%E3%81%A8%E3%81%AF%E3%80%81Python,%E3%81%AB%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%89%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82

* 環境：jupyter notebook

https://jupyter.org/

# 成果物

## パッケージのインストール

* janome：日本語の形態素解析（日本語を意味を保持したまま噛み砕く的な）
* gensim：文書をベクトル（数値）化（そもそもベクトル化ばハテナな方はこの辺を：https://www.tryeting.jp/column/6839/
* scikit-learn：言わずとしれた機械学習ライブラリ　https://aiacademy.jp/media/?p=1916

```
!pip install janome
!pip install gensim
!pip install scikit-learn
```

## 取得テキストを解析しやすくする

```python
from janome.tokenizer import Tokenizer
from janome.analyzer import Analyzer
from janome.charfilter import UnicodeNormalizeCharFilter
from janome.tokenfilter import POSStopFilter, LowerCaseFilter, ExtractAttributeFilter

# ストップワードの削除
def remove_stopwords(text, stop_words):
    tokenizer = Tokenizer()
    tokens = tokenizer.tokenize(text)
    filtered_tokens = [token for token in tokens if token.surface not in stop_words]
    return "".join([token.surface for token in filtered_tokens])

# 単語のレンマタイゼーション
def lemmatize_words(text):
    char_filters = [UnicodeNormalizeCharFilter()]
    token_filters = [POSStopFilter(['助詞', '助動詞', '記号']),
                     LowerCaseFilter(),
                     ExtractAttributeFilter('base_form')]
    tokenizer = Tokenizer()
    analyzer = Analyzer(char_filters=char_filters, tokenizer=tokenizer, token_filters=token_filters)
    lemmatized_text = " ".join(analyzer.analyze(text))
    return lemmatized_text

# # サンプルテキスト
# text = "猫が怠けて寝ている間に、犬たちは元気に遊んでいた。"

# # 日本語のストップワード（一例）
# stop_words = ["の", "に", "て", "で", "が", "いる", "た", "と", "する"]

# # 前処理の実行
# text_no_stopwords = remove_stopwords(text, stop_words)
# text_lemmatized = lemmatize_words(text_no_stopwords)

# print("Original Text:", text)
# print("After Stopword Removal:", text_no_stopwords)
# print("After Lemmatization:", text_lemmatized)

```

## テキストをベクトル化

```python
import pandas as pd
import gensim
from gensim.models import Word2Vec
from janome.tokenizer import Tokenizer

# CSVファイルからデータを読み込む
data = pd.read_csv('sample.csv')
texts = data['text'].tolist()

# 分かち書き（単語ごとに分割）
def tokenize(text):
    tokenizer = Tokenizer()
    tokens = tokenizer.tokenize(text)
    return [token.surface for token in tokens]

# 分かち書きを実行
tokenized_texts = [tokenize(text) for text in texts]

# Word2Vecモデルの学習
model = Word2Vec(sentences=tokenized_texts, vector_size=100, window=5, min_count=1)

# テキストデータをベクトル化
vectorized_texts = []
for text in tokenized_texts:
    text_vector = sum([model.wv[word] for word in text]) / len(text)
    vectorized_texts.append(text_vector)

# 結果を表示
for i, vec in enumerate(vectorized_texts):
    print(f"Text {i+1}")
```

## K-means法でクラスタリング実施

```python
from sklearn.cluster import KMeans

# クラスタ数の設定
num_clusters = 5

# K-meansクラスタリングの実行
kmeans = KMeans(n_clusters=num_clusters, random_state=42)
kmeans.fit(vectorized_texts)

# クラスタリング結果を表示
for i, label in enumerate(kmeans.labels_):
    print(f"Text {i+1}: Cluster {label+1}")
```

# おわり

きっとあなたの周辺にも「どっさりデータはあるけど全部テキストなんだよな、なんか分類したら面白いことにならないかな」なデータは存在します。そんなときの気軽な十徳ナイフの一つになればうれしいですね。