クソアプリ Advent Calendar 2022 16日目の記事です。
はじめに
今年もこの時期がやってまいりました
前回は、Discordの通知をすべてDiscordで通知するBOTという、discord.pyを使ったくそBOTを作りました。
今回は、少し趣向を変え、自然言語処理を使ったくそアプリを作りました!
その名も...
(β)アンサイクロペディア記事検索機
※この映像は開発段階のものです。実際のアプリと異なる場合があります
対象読者
- Pythonのコードが読める人
- AIに興味がある人
- 少し古くても文句を言わない人
このアプリのくそなところ
このアプリは、後でも紹介しますが、streamlit
というホスティングサービスを使用しています。
これは、githubリポジトリからコードを持ってくることでホストができます。
そして、githubの最大アップロード量は100MB...
モデルの容量が大きすぎたので、今回実装ができたのは、
類義語検索のところまで・・・でした。。
ちなみに、doc2vecでの実装を無理やりword2vecに切り替えたため、アプリ自体もバグってます。
- 一文字での検索のみ対応
- 類似してるかわからない文字が並ぶ
- 読めない
どうぞ、お楽しみください。
使用技術の紹介
Gensim
このアプリでは、Gensimというライブラリを使って実装しています。
詳しい話は、最近話題のChatGPTに聞いてみましょう!
少し誤解が生まれそうな回答ですが、大方このような意味ですし、この記事を理解する上では問題ないので ヨシッ
もっと知りたい方は、Gensimの公式ドキュメントを読んでみてください。
Word2VecとDoc2Vec
このアプリでは、Word2VecとDoc2Vecという、Gensimの中のメソッドを使っています。
二つの違いも聞いておきましょう
まとめると、
- Word2Vec:単語検索ができる
- Doc2Vec:文章検索ができる
ということになります。
Streamlit
今回のアプリのホストには、データを扱う系のアプリに特化したstreamlitというサービスを使用しました。
超簡単に使えました。
詳しくは公式ドキュメント参照
ChatGPTによるコードの生成も、基礎的なものであればうまく行くので、ChatGPTに聞くのもありです。
アンサイクロペディアの記事を取得
アンサイクロペディアはAPIからの記事取得方法もあるそうでしたが、よくわからなかったので、スクレイピングで行いました。
1記事1.5秒、計31,998記事...
めっちゃ時間かかりました。
コードの実装には、以下の記事を参考にしました。
コードはここに置きました。
アンサイクロペディアには、特別ページというものが存在します。
その一つにページ一覧がおいてあるページがあります。
これと
wiki_articles = Wiki_Reader()
wiki_articles.df.to_csv('wiki_article.csv')
print('\nSuccessfully downloaded')
このコードの二つでアンサイクロペディアの記事の取得ができます。
30行目以降のget_article_pages()
はそこからページのリンクをリスト化しています。
72行目移行のget_article_data()
で記事のIDや本文を取得しています。
あまりにも処理が長く、途中で処理を中断しなければならないことが多々あったので、50記事毎に書き出す処理を付けました。
74-76行目です。
17,20,58-61行目のコメントアウトをうまく使うことで、途中から処理を再開させることができます。
doc2vecを使った学習
コードはここにあります。
doc2vecに関しては、ここで特別言うことはありません。
ただ公式docsに書いてあるコードをそのまま実行した感じです。
cached_property
@cached_property
コードの一部にこのデコレーターが見られると思います。
これは、その関数の返り値をキャッシュすることができます。
これにより、毎回呼び出すたびに処理をする、ということを防ぐことができます。
アプリの実装編
コードはここです。
gensim周り
from gensim.models import doc2vec
まず、gensimからdoc2vecを読み込みます。
これは、gensim.modelsに定義されています。
gensim.modelsには、他にも面白い機能を持ったものがあるので、ぜひ調べてみてください。
similar_words1 = model.wv.most_similar(word)
このコードで、入力した単語と似た使われ方をされている単語を探します。
vector = model.infer_vector([word])
similar_words2 = model.dv.most_similar([vector])
後半部分のコードですが、
これは、単語をベクトルに変換しています。
そのあと、近しいベクトルを持った記事を検索しています。
今回は、単語:文章間の検索のいい方法が思いつかなかったので、単純にベクトルの比較を行いました。
いい方法知ってる方、教えてください(ボソッ
streamlit周り
col1, col2 = st.columns(2)
with col1:
...
with col2:
...
これは、二つ以上の要素を横に並べる時に使えます。
詳しくは公式docsを参照
word = st.text_input("Search word:")
これで、単語の入力を行います。
st.title("類義語検索")
タイトルの記述に使います。
st.write("^ 好きな単語を入力してください")
通常文章を記述するときに使用します。
st.markdown(f"[{str(df.title.values)[2:-2].replace('u3000', '')}](https://ansaikuropedia.org/index.php?curid={str(df.id.values)[1:-1]})")
st.markdownは、要素をmarkdown形式で記述することができます。
streamlitでのハイパーテキストの記述は、これで行うそうです。
最後に
いかがでしたか?
次は、アンサイクロペディアの記事を要約する予定です。
お楽しみに
では ノシ
反省
さて、
この記事で紹介したwebサイトまでならよかったのですが、
実際にコードを実行してみた皆様は、
「このアプリのどこがくそアプリなの?」
「普通に精度iijan」
「発展性アルヨネ?」
などと、今にも僕のTwitterを炎上させたい気持ちでいっぱいだと思われます。
言い訳をさせてください。
当初予定では、類義語検索を行い、
「いや、うん、そうなんだけど...」
という言葉を引き出す検索結果を表示する予定でした。
しかし、イレギュラーだらけのアンサイクロペディアを読み込ませても、うまく行ってしまいました。
原因はいくつか考えられますが、一番大きいのは、
終わってる記事は一部だけで、記事のほとんどがまとも
だったことだと思います。
来年度は、この反省を生かし、前回よりも面白く、終わっているくそアプリを作りたいと思います!
では、また会いましょう ノシ