ChatGPTに、二つの文章の類似度を判定してもらうPythonプログラムを書いてもらいました。最初の指示だとあまり使えないコードが出力されたので、そのあとに改良版として少し具体的に指示した結果ものせてます。
指示文(プロンプト)1:
二つの文章の類似度を判定するpythonプログラムを提示ください。比較する文章は標準入力とします。
回答:
以下はPythonで二つの文章の類似度を判定するプログラムの例です。入力された文章を前処理し、テキストの類似度を計算するためにcosine類似度を使用しています。
import re
from collections import Counter
import math
def preprocess(text):
# テキストの前処理を行う関数
text = text.lower() # 小文字に変換
text = re.sub(r'\W+', ' ', text) # 英数字以外の文字を削除
text = re.sub(r'\s+', ' ', text) # 連続するスペースを1つに置換
return text
def get_cosine_similarity(text1, text2):
# 2つのテキストのcosine類似度を計算する関数
# テキストを前処理
text1 = preprocess(text1)
text2 = preprocess(text2)
# テキストを単語に分割
words1 = text1.split()
words2 = text2.split()
# 単語の出現回数をカウント
word_count1 = Counter(words1)
word_count2 = Counter(words2)
# 共通の単語の出現回数を取得
common_words = set(word_count1.keys()) & set(word_count2.keys())
# cosin類似度の計算に必要な分子と分母を計算
numerator = sum([word_count1[word] * word_count2[word] for word in common_words])
denominator1 = sum([word_count1[word] ** 2 for word in words1])
denominator2 = sum([word_count2[word] ** 2 for word in words2])
# 分子と分母が共に0であれば類似度は0とする
if denominator1 == 0 or denominator2 == 0:
similarity = 0
else:
similarity = numerator / (math.sqrt(denominator1) * math.sqrt(denominator2))
return similarity
if __name__ == '__main__':
# 比較する2つの文章を標準入力から取得
text1 = input('1つ目の文章を入力してください: ')
text2 = input('2つ目の文章を入力してください: ')
# 2つの文章の類似度を計算
similarity = get_cosine_similarity(text1, text2)
# 類似度を出力
print('2つの文章の類似度は: {:.2%}'.format(similarity))
このプログラムは、2つの文章を入力として受け取り、cosine類似度を計算して出力します。cosine類似度は0から1の値を取り、1に近いほど類似していることを示します。類似度が高いほど、2つの文章の内容が似ていると言えます。
結果:
一応、動作はしますが、精度が全然よくありません。下記はほぼ同じ文章を、単語の言い換えや言い回しの変更のみを施したものです。
まったく同じ文章の場合は100%:
少しだけ違う文章にしたら44.7%
指示文(プロンプト)2:
二つの文章の類似度を判定するpythonプログラムを提示ください。比較する文章は標準入力とします。精度を上げるために、形態素解析も使ってください。
回答:
import MeCab
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
# MeCabのインスタンスを作成
mecab = MeCab.Tagger()
# 文章を入力
text1 = input("文1を入力してください: ")
text2 = input("文2を入力してください: ")
# 文章を形態素解析して単語に分割する関数
def tokenize(text):
tokens = mecab.parse(text)
tokens = [t.split('\t')[0] for t in tokens.split('\n')]
return tokens[:-2]
# TfidfVectorizerを用いて文書をベクトル化する
vectorizer = TfidfVectorizer(tokenizer=tokenize)
tfidf_matrix = vectorizer.fit_transform([text1, text2])
# コサイン類似度を計算する
similarity = cosine_similarity(tfidf_matrix[0:1], tfidf_matrix[1:2])
# 類似度を出力
print("類似度: ", similarity[0][0])
結果:
以下のように、かなり良い精度になりました。
単語が少し違うだけの文章の比較:
文章の前後を入れ替えたもので、意味は同じ:
全く違う文章:
形態素解析にjanomeを指定した場合:
形態素解析をMeCabではなく、Janomeを指定したプロンプトへの回答はこちら。JanomeはPure pythonでインストールが楽なので、MeCabがない環境でさくっとやりたいときなどに。
from janome.tokenizer import Tokenizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
def tokenize(text):
"""文章を形態素解析してトークン化する関数"""
tokenizer = Tokenizer()
tokens = [token.surface for token in tokenizer.tokenize(text)]
return tokens
def calculate_similarity(text1, text2):
"""二つの文章の類似度を計算する関数"""
# 形態素解析してトークン化
tokens1 = tokenize(text1)
tokens2 = tokenize(text2)
# 文章を単語のリストに結合
text1 = " ".join(tokens1)
text2 = " ".join(tokens2)
# TF-IDFベクトル化
vectorizer = TfidfVectorizer()
tfidf_matrix = vectorizer.fit_transform([text1, text2])
# コサイン類似度を計算
similarity = cosine_similarity(tfidf_matrix[0], tfidf_matrix[1])
return similarity[0][0]
if __name__ == "__main__":
# 入力された二つの文章を取得
text1 = input("文章1を入力してください: ")
text2 = input("文章2を入力してください: ")
# 類似度を計算
similarity = calculate_similarity(text1, text2)
# 類似度を出力
print("二つの文章の類似度: {:.2f}".format(similarity))
結果:
こちらもきちんと動作しますが、精度は少しだけ落ちるかも。