MENU

Doc2Vecで作成したモデルで作者の分類

作者の分類をするプログラム。

前提として事前に青空文庫から取得した文書データを使用してDoc2Vecでモデルの作成を行っている。そのモデルを使用して作者の分類を行っていく。

import urllib.request as req
import zipfile
import os.path
import MeCab
from gensim import models

#Mecabの初期化
mecab.parse("")

#保存したDoc2Vec学習モデルを読み込み --- (*7)
model = models.Doc2Vec.load('aozora.model')

#分類用のZipファイルを開き、中の文書を取得する --- (*8)
def read_book(url, zipname):
  if not os.path.exists(zipname):
    req.urlretrieve(url, zipname)

  with zipfile.ZipFile(zipname,"r") as zf:
    for filename in zf.namelist():
     with zf.open(filename,"r") as f:
      return f.read().decode("shift-jis")

#引数のテキストを分かち書きして配列にする
def split_words(text):
  node = mecab.parseToNode(text)
  wakati_words =
  while node is not None:
   hinshi = node.feature.split(",")[0]
   if hinshi in ["名詞"]:
    wakati_words.append(node.surface)
   elif hinshi in ["動詞", "形容詞"]:
    wakati_words.append(node.feature.split(",")[6])
  node = node.next
  return wakati_words

#引数のタイトル、URLの作品を分類する --- (*9)
def similar(title, url):
  zipname = url.split("/")[-1]
 
  words = read_book(url, zipname)
  wakati_words = split_words(words)
  vector = model.infer_vector(wakati_words)
  print("--- 「" + title + '」 と似た作品は? ---')
  print(model.docvecs.most_similar([vector],topn=3))
  print("")

#各作家の作品を1つずつ分類 --- (*10)
similar("宮沢 賢治:よだかの星",

similar("芥川 龍之介:犬と笛",

similar("ポー エドガー・アラン:マリー・ロジェエの怪事件",

similar("紫式部:源氏物語 06 末摘花",

実行結果

f:id:hanamichi_sukusuku:20210123223054p:plain

結果としてモデルに学習させたものと類似度の高いものを出力している。

モデルの読み込み

model = models.Doc2Vec.load('aozora.model')

 

関数呼び出し、各作家の作品を一つずつ分類

 

引数のタイトル、URLの作品を分類する

def similar(title, url):
zipname = url.split("/")[-1]
 
words = read_book(url, zipname)
wakati_words = split_words(words)
vector = model.infer_vector(wakati_words)
print("--- 「" + title + '」 と似た作品は? ---')
print(model.docvecs.most_similar([vector],topn=3))
print("")

 

ここではread_book()関数で中身の文書を取得し、split_words()関数で引数で受け取った文章を分かち書きにして配列にして返している。

model.infer_vector()では分かち書きデータを渡すことでベクトルを作成している。

model.docvecs.most_similar()では引数に渡したデータの類似度の高いものから3作品を出力している。topn=N(トップからN番目までを出力)model.docvecs[文書名]で文書のベクトル。model.docvecs.most_similar(文書名(ベクトルデータ))で文書の類似度を確認できる。

 

read_bok()関数、zipファイルを開き、中の文書を取得

def read_book(url, zipname):
  if not os.path.exists(zipname):
   req.urlretrieve(url, zipname)

  with zipfile.ZipFile(zipname,"r") as zf:
   for filename in zf.namelist():
    with zf.open(filename,"r") as f:
     return f.read().decode("shift-jis")

 

if not os.path.exists(zipname):で引数に指定したファイル名が存在しなければ関数の引数で受け取ったurlにアクセスしアクセス先のファイルをダウンロードする処理をしている。

with zipfile.ZipFile()ではzipファイルを解凍しfor文で解凍したzipファイルの中身のファイル名を取得してwith zf.open()でファイルを開きf.read().decode(:shift-jis)でファイルの中身を読み込み、Shift-JISでデコードして文書を呼び出し元に返している。

 

split_word()関数、分かち書きにして配列にする

def split_words(text):
node = mecab.parseToNode(text)
wakati_words =
  while node is not None:
    hinshi = node.feature.split(",")[0]
    if hinshi in ["名詞"]:
     wakati_words.append(node.surface)
    elif hinshi in ["動詞", "形容詞"]:
     wakati_words.append(node.feature.split(",")[6])
   node = node.next
  return wakati_words

 

mecab.parseToNode()で文章を渡し、単語、品詞情報を持ったオブジェクトを変数に代入。

while文のなかのif文でストップワードの除去を行い、新しい配列に追加していく。

最後に作成した配列を呼び出し元に返している。