2
3

More than 1 year has passed since last update.

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

Posted at

概要

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

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

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

やったこと

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

環境

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

  • 言語:python
  • ライブラリ:scikit-learn

  • 環境:jupyter notebook

成果物

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

  • 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

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

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)

テキストをベクトル化

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法でクラスタリング実施

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}")

おわり

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

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3