2019の7日目の記事です。PytorchとElasticsearchで簡単な画像(画風)検索エンジンを作りたいと思います。結果(おまけ)Kibanaでデータ確認という流れで、解説していきたいと思います。(今回の記事では、自分の解釈を入れながら厳密な説明を避け大まかに説明しています。論文の理解や実装について誤りがある場合は、教えて頂けると幸いです。)コードはこちらで公開しています。そもそものきっかけ(少しポエムっぽいですので、手法が気になる方はこちらはスキップしてください。いう書籍を読みまして抽象芸術に興味を持ち始めました。喚起するために還元主義を用いる)、その方法は似通っている」というテーマのもと、抽象芸術がなぜ生まれたのか、脳はいかにして抽象芸術を理解するか、芸術への還元主義の影響などについてノーベル賞を受賞したエリック・R・カンデルさんが書いたものになります。この本を読みながら、絵画を還元的に見るとはどういうことで、それを定式化するとしたらどういものになるだろうと考えていたところ、ディープラーニングで画風を変換する手法をふと思い出し、確かその論文内で画風を定式化していたように記憶していたので、再度その論文を読み直してみようと思ったのがきっかけになります。前々からPytorchとElasticsearchのベクトル検索に興味があったので、せっかくの機会なので調べながら画風検索エンジンを作ることにしました。Networksというタイトルで発表されました。画像をピカソ風にしたり、ゴッホ風にしたりできます。個人的にこちらの論文の最もすごかったことは、画風を下記の数式として表現したことにあると思っています。1こちらは、ディープラーニングのとある中間層における特徴量マップの内積をとったグラム行列になります。これの意味するところは、各特徴量マップが線の太さや色彩の情報をもってあり、それの相関を計算することで、この画像は線が細くて赤と緑の組み合わせが多いなどの画風に関する情報を上手く表現しています。こちらの画風ベクトルとコンテツベクトルを利用することで画像変換を達成しています。コンテンツベクトルは、中間層の特徴量マップをそのまま使用し、画像の形状に関する情報を保持したものになります。この2つのベクトルを利用することで、元画像の形状を保ったまま画風を変換することができます。1枚の画像から、形状に関するコンテンツベクトルと画風に関する画風ベクトルを取得することができます。この2つのベクトルをデータベースに格納することで、形状が似た画像の検索と画風が似た画像の検索ができるようになると思い、PytorchとElasticsearchで実装してみます。公式のPytorchによる画風変換のチュートリアルを参考にして、画風ベクトルの抽出を実装します。get_upper_triangle_values(gram_matrix(trained_model(image)))まず、学習済みのモデルを使用して、中間層の特徴量マップを取得します。それのグラム行列を計算します。グラム行列は対称行列なので上三角部分の要素だけを残して、そのベクトルを保存します。コンテンツベクトルは、中間層の特徴量をFlattenしたものになります。trained_model(image).view(-1)Elasticsearchにデータを格納して、似ている画風画像を検索Elasticsearchは分散型RESTful検索/分析エンジンです。ベクトル検索を使用することで、word2vecやbertで得られたベクトルを用いて、類似文章の検索ができます。今回は画風ベクトルとコンテツベクトルを格納2して、類似画風検索を行います。Indexの情報とPythonでのIndex作成とデータの格納は次のとおりです。documents)類似画風検索をするには、入力画像の画風ベクトルを計算して、そのベクトルをElasticsearchに渡すことで、類似画像を得ることができます。1234類似画風画像の1、2位は、入力画像を描いたルノワールによって書かれた作品になります。類似画風検索のほうがより印象派の画風に似た結果になっているように思います。(この記事では、手元でいくつかの画像を検索することで定性的に評価をしました。定量的にする場合は、画像に印象派やキュビズムなどのタグを付けて、タグの一致率などで検証できますが、今回は時間とデータの理由で定量的には評価はできておりません。upでKibanaとElasticsearchを起動します。localhttp://localhost:5601/にアクセスすると格納したデータを確認することができます。今後(今回できなかったこと。Networks画像の質感を表現するものとして、2015年に提案されています。searchのベクトル検索の上限値は1000のため格納できません。そこで次元圧縮して100次元にしてからデータを格納しました。upLoginユーザーは見つかりませんでした。