tag:crieit.net,2005:https://crieit.net/users/sgrdk/feed
skybee8の投稿 - Crieit
Crieitでユーザーskybee8による最近の投稿
2021-04-15T21:21:40+09:00
https://crieit.net/users/sgrdk/feed
tag:crieit.net,2005:PublicArticle/16850
2021-04-15T21:19:45+09:00
2021-04-15T21:21:40+09:00
https://crieit.net/posts/KeyBERT
KeyBERTでキーフレーズ抽出を試してみる
<p>最近キーフレーズ抽出に興味がありいろいろと調べていたら、BERT版のキーフレーズ抽出パッケージがあったので試してみた。ちなみにキーフレーズ抽出とは、「文章からその主題を良く表現している句を抽出する技術」のこと。<br />
環境は、Docker for Mac を想定。</p>
<h1 id="環境設定"><a href="#%E7%92%B0%E5%A2%83%E8%A8%AD%E5%AE%9A">環境設定</a></h1>
<h2 id="Docker for Macのメモリ制限解放"><a href="#Docker+for+Mac%E3%81%AE%E3%83%A1%E3%83%A2%E3%83%AA%E5%88%B6%E9%99%90%E8%A7%A3%E6%94%BE">Docker for Macのメモリ制限解放</a></h2>
<p>Decktopにある<code>Preference</code> -> <code>Advance</code> でMemoryの上限を調整する。KeyBERTをインストールするとPytorchをインストールしようとするが、Dockerのデフォルト設定のままだとメモリ不足でインストールに失敗する。なので、設定を変更してメモリ制限を解除する。今回は12Gに設定した。</p>
<h2 id="KeyBERTのインストール"><a href="#KeyBERT%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">KeyBERTのインストール</a></h2>
<pre><code class="python">pip install keybert
</code></pre>
<h2 id="MeCabのインストール"><a href="#MeCab%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">MeCabのインストール</a></h2>
<p>KeyBERTは日本語の分かち書きに対応していないため、MeCabを利用する。</p>
<pre><code class="python">pip install mecab-python3
pip install unidic-lite
</code></pre>
<h1 id="コード"><a href="#%E3%82%B3%E3%83%BC%E3%83%89">コード</a></h1>
<p>今回は、Wikipediaのディズニーランドの記事を使ってみる。</p>
<pre><code class="python">from keybert import KeyBERT
import MeCab
doc1 = """
東京ディズニーランド(とうきょうディズニーランド、英称:Tokyo Disneyland、略称:TDL)は、
千葉県浦安市舞浜にあるディズニーリゾートを形成する日本のディズニーパーク。
年間来場者数は日本最大の約1,800万人で、世界のテーマパーク・アミューズメントパークの中でも、
フロリダ州のウォルト・ディズニー・ワールド・リゾートのマジック・キングダム、カリフォルニア州の
ディズニーランド・リゾートのディズニーランド・パークに次いで世界3位の規模を誇る[1]。
オリエンタルランドがウォルト・ディズニー・カンパニーとのライセンス契約のもと運営している[3]。
"""
# MeCabで分かち書き
words = MeCab.Tagger("-Owakati").parse(doc1)
model = KeyBERT('distilbert-base-nli-mean-tokens')
print(model.extract_keywords(words, top_n = 10, keyphrase_ngram_range=(1, 1)))
</code></pre>
<h1 id="結果"><a href="#%E7%B5%90%E6%9E%9C">結果</a></h1>
<p>キーフレーズとして「ディズニーランド」が上位に上がってくると思いきや、結果は8番目だった。</p>
<pre><code>[('アミューズメント', 0.5486),
('オリエンタル', 0.534),
('ライセンス', 0.5144),
('マジック', 0.4829),
('キングダム', 0.4651),
('フロリダ', 0.4469),
('カンパニー', 0.44),
('日本', 0.4295),
('ディズニー', 0.4252),
('ランド', 0.4068)]
</code></pre>
<h1 id="ちょっとだけ追加検証"><a href="#%E3%81%A1%E3%82%87%E3%81%A3%E3%81%A8%E3%81%A0%E3%81%91%E8%BF%BD%E5%8A%A0%E6%A4%9C%E8%A8%BC">ちょっとだけ追加検証</a></h1>
<p>ちなみに、下記の文章(概要の部分)を追加するとどうなるかというと。。。</p>
<pre><code class="python">doc2 = """
誘致当時の経緯から東京ディズニーシーと共に米国ディズニーグループによる直営ではなく、
日本企業の 株式会社オリエンタルランド が米国ディズニーからのライセンス契約により運営している。
なお、東京ディズニーリゾートで販売されているキャラクターの著作権や版権ビジネスはすべてウォルト・ディズニー・ジャパンが、
アトラクションやショーの企画に関しては、米国ディズニー・パークス・エクスペリエンス・プロダクツおよび米
国ディズニーの子会社であるウォルト・ディズニー・アトラクションズ・ジャパンが担当している。
"""
</code></pre>
<h2 id="結果2"><a href="#%E7%B5%90%E6%9E%9C2">結果2</a></h2>
<p>「ディズニー」が消えてしまった。「エクスペリエンス」って1回して出てきていないんだけど。。</p>
<pre><code>[('エクスペリエンス', 0.5799),
('アトラクション', 0.5603),
('アミューズメント', 0.5486),
('オリエンタル', 0.534),
('キャラクター', 0.5154),
('ライセンス', 0.5144),
('プロダクツ', 0.494),
('マジック', 0.4829),
('ジャパン', 0.4752),
('キングダム', 0.4651)]
</code></pre>
skybee8
tag:crieit.net,2005:PublicArticle/16819
2021-04-05T20:50:12+09:00
2021-04-05T21:17:41+09:00
https://crieit.net/posts/Tesseract-Ubuntu-Docker
TesseractをUbuntu(Docker)で試してみる
<p>DockerでJupyterLab環境で構築し、その中でTesseractを使って画像から文字を抽出する。</p>
<h1 id="DockerでJupyter Lab環境を構築"><a href="#Docker%E3%81%A7Jupyter+Lab%E7%92%B0%E5%A2%83%E3%82%92%E6%A7%8B%E7%AF%89">DockerでJupyter Lab環境を構築</a></h1>
<h2 id="Dockerfileを作る"><a href="#Dockerfile%E3%82%92%E4%BD%9C%E3%82%8B">Dockerfileを作る</a></h2>
<p>任意のフォルダにDockerfileという名前のファイルを作成する。</p>
<pre><code class="shell">$ mkdir ~/Desktop/docker_build
$ cd Desktop/docker_build/
$ touch Dockerfile
</code></pre>
<p>Dockerfileの中身</p>
<pre><code class="docker">FROM ubuntu:latest
# update
RUN apt-get -y update && apt-get install -y \
sudo \
wget \
vim
#install anaconda3
WORKDIR /opt
# download anaconda package and install anaconda
# archive -> https://repo.continuum.io/archive/
RUN wget https://repo.continuum.io/archive/Anaconda3-2019.10-Linux-x86_64.sh && \
sh /opt/Anaconda3-2019.10-Linux-x86_64.sh -b -p /opt/anaconda3 && \
rm -f Anaconda3-2019.10-Linux-x86_64.sh
# set path
ENV PATH /opt/anaconda3/bin:$PATH
# update pip and conda
RUN pip install --upgrade pip
WORKDIR /
RUN mkdir /work
# execute jupyterlab as a default command
CMD ["jupyter", "lab", "--ip=0.0.0.0", "--allow-root", "--LabApp.token=''"]
</code></pre>
<h2 id="Dockerをビルド"><a href="#Docker%E3%82%92%E3%83%93%E3%83%AB%E3%83%89">Dockerをビルド</a></h2>
<pre><code class="shell">$ docker build .
Successfully built d723190a8650
</code></pre>
<h2 id="Dockerを起動"><a href="#Docker%E3%82%92%E8%B5%B7%E5%8B%95">Dockerを起動</a></h2>
<pre><code class="shell">$ docker run -p 8888:8888 -v ~/Desktop/ds_python:/work --name my-lab d723190a8650
</code></pre>
<p>ブラウザからlocalhost:8888にアクセスしてJupyter Labに入る。</p>
<h1 id="Docker上でTesseract"><a href="#Docker%E4%B8%8A%E3%81%A7Tesseract">Docker上でTesseract</a></h1>
<h2 id="Tesseractインストール"><a href="#Tesseract%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">Tesseractインストール</a></h2>
<h3 id="ターミナル起動"><a href="#%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%8A%E3%83%AB%E8%B5%B7%E5%8B%95">ターミナル起動</a></h3>
<ul>
<li>workディレクトリをクリック</li>
<li>File -> New -> Terminal</li>
</ul>
<h2 id="本体インストール"><a href="#%E6%9C%AC%E4%BD%93%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">本体インストール</a></h2>
<p>インストール途中で、ロケーションとタイムゾーンを聞かれるので、Asia、Tokyoを選択</p>
<pre><code class="shell">$ sudo apt-get update
$ sudo apt install tesseract-ocr
$ sudo apt install libtesseract-dev
</code></pre>
<h2 id="バージョン確認"><a href="#%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E7%A2%BA%E8%AA%8D">バージョン確認</a></h2>
<pre><code class="shell">$ tesseract -v
tesseract 4.1.0-rc1-184-g497d
leptonica-1.75.3
libgif 5.1.4 : libjpeg 8d (libjpeg-turbo 1.5.2) : libpng 1.6.34 : libtiff 4.0.9 : zlib 1.2.11 : libwebp 0.6.1 : libopenjp2 2.3.0
Found AVX2
Found AVX
Found SSE
</code></pre>
<h2 id="訓練済みモジュールインストール"><a href="#%E8%A8%93%E7%B7%B4%E6%B8%88%E3%81%BF%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">訓練済みモジュールインストール</a></h2>
<pre><code class="shell">sudo apt install tesseract-ocr-jpn tesseract-ocr-jpn-vert
sudo apt install tesseract-ocr-script-jpan tesseract-ocr-script-jpan-vert
</code></pre>
<p>モジュールがインストールされたか確認</p>
<pre><code class="shell">$ tesseract --list-langs
List of available languages (6):
Japanese
Japanese_vert
eng
jpn
jpn_vert
osd
</code></pre>
<h1 id="Tesseract実行"><a href="#Tesseract%E5%AE%9F%E8%A1%8C">Tesseract実行</a></h1>
<p>第一引数は画像の名前、第二引数はOCRの結果を出力するファイル名。デフォルトで.txt拡張子が付く。</p>
<pre><code class="shell">$ tesseract image.png ocr_out -l jpn
</code></pre>
<h1 id="PythonでTesseract実行"><a href="#Python%E3%81%A7Tesseract%E5%AE%9F%E8%A1%8C">PythonでTesseract実行</a></h1>
<h2 id="pytesseractインストール"><a href="#pytesseract%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">pytesseractインストール</a></h2>
<pre><code class="shell">pip install pytesseract
</code></pre>
<h2 id="pytesseract実行"><a href="#pytesseract%E5%AE%9F%E8%A1%8C">pytesseract実行</a></h2>
<pre><code class="python">import Image
import pytesseract
FILE_NAME = './image.jpg'
print(pytesseract.image_to_string(Image.open(FILE_NAME), lang=('jpn'))
</code></pre>
<h1 id="おまけ"><a href="#%E3%81%8A%E3%81%BE%E3%81%91">おまけ</a></h1>
<h2 id="OpenCVでグレースケール変換"><a href="#OpenCV%E3%81%A7%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%AB%E5%A4%89%E6%8F%9B">OpenCVでグレースケール変換</a></h2>
<h3 id="OpenCVインストール"><a href="#OpenCV%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB">OpenCVインストール</a></h3>
<pre><code class="shell">$ pip install opencv-python
$ apt-get install -y libgl1-mesa-dev
</code></pre>
<h3 id="グレースケール変換"><a href="#%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%AB%E5%A4%89%E6%8F%9B">グレースケール変換</a></h3>
<pre><code class="python">import cv2
im = cv2.imread('./image.jpeg')
im_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
cv2.imwrite('./image_gray.jpeg', im_gray)
print(pytesseract.image_to_string(Image.open('./image_gray.jpeg'), lang='jpn'))
</code></pre>
skybee8
tag:crieit.net,2005:PublicArticle/16818
2021-04-05T16:27:16+09:00
2021-04-05T16:34:35+09:00
https://crieit.net/posts/MMR-Pyspark
MMRアルゴリズムをPysparkで実装する
<p>レコメンド結果にMMRを適用して多様性を考慮したかった。<br />
以下のようにPythonで実装されているコードはあったが、Pysparkで実装れているサンプルがなかったので実装してみた。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://yolo-kiyoshi.com/2020/05/08/post-1781/">MMR実装を参考にしたページ</a></p>
<h2 id="実装コード"><a href="#%E5%AE%9F%E8%A3%85%E3%82%B3%E3%83%BC%E3%83%89">実装コード</a></h2>
<h3 id="モジュールインポート"><a href="#%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88">モジュールインポート</a></h3>
<pre><code class="python">from pyspark.sql import DataFrame as SDF
from typing import Set, Callable, List
import pyspark.sql.functions as F
</code></pre>
<h3 id="検索クエリとアイテムリストの類似度結果を取得する関数"><a href="#%E6%A4%9C%E7%B4%A2%E3%82%AF%E3%82%A8%E3%83%AA%E3%81%A8%E3%82%A2%E3%82%A4%E3%83%86%E3%83%A0%E3%83%AA%E3%82%B9%E3%83%88%E3%81%AE%E9%A1%9E%E4%BC%BC%E5%BA%A6%E7%B5%90%E6%9E%9C%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B%E9%96%A2%E6%95%B0">検索クエリとアイテムリストの類似度結果を取得する関数</a></h3>
<pre><code class="python">def sim_func(df: SDF, item_id: int, rec_item_id: int) -> float:
min_score = df.filter(F.col('item_id') == item_id).groupBy().min('score').collect()[0][0]
try:
score = df.filter((F.col('item_id') == item_id) & (F.col('rec_item_id') == rec_item_id)).collect()[0]['score']
except:
score = min_score
return score
</code></pre>
<h3 id="選択済みアイテムがオリジナルのアイテムと同じ集合になるまでLOOP"><a href="#%E9%81%B8%E6%8A%9E%E6%B8%88%E3%81%BF%E3%82%A2%E3%82%A4%E3%83%86%E3%83%A0%E3%81%8C%E3%82%AA%E3%83%AA%E3%82%B8%E3%83%8A%E3%83%AB%E3%81%AE%E3%82%A2%E3%82%A4%E3%83%86%E3%83%A0%E3%81%A8%E5%90%8C%E3%81%98%E9%9B%86%E5%90%88%E3%81%AB%E3%81%AA%E3%82%8B%E3%81%BE%E3%81%A7LOOP">選択済みアイテムがオリジナルのアイテムと同じ集合になるまでLOOP</a></h3>
<pre><code class="python">def mmr(df: SDF, items: Set[int], item_id: int, lambda_: float, sim_func1: Callable[[SDF, int, int], float], sim_func2: Callable[[SDF, int, int]) -> List[int]:
def _argmax(keys, f):
return max(keys, key=f)
selected = []
while set(selected) != items:
remaining = items - set(selected)
mmr_score = lambda x: labmda_ * sim_func1(df, item_id, x) - (1 - lambda_) * max([sim_func2(df, x, y) for y in set(selected)-{x}] or [0])
next_selected = _argmax(remaining, mmr_score)
selected.append(next_selected)
return selected
</code></pre>
<h3 id="MMR実行"><a href="#MMR%E5%AE%9F%E8%A1%8C">MMR実行</a></h3>
<pre><code class="python">mmr(
df,
set(list(df.filter(F.col('item_id') == 12345678).select('rec_item_id').toPandas()['rec_item_id'])),
12345678,
0.8,
sim_func,
sim_func
)
</code></pre>
skybee8