for Startups Tech blog

このブログのデザインを刷新しました。(2023/12/26)

【フォースタ テックブログ】タグの自動予測について。STARTUP DBに機械学習を組み込んだ話【後編】

f:id:forStartups:20211025162517p:plain

こんにちは。テックラボの松原です。

以前、投稿しました「タグの自動予測について。STARTUP DBに機械学習を組み込んだ話【前編】」の続きのお話です。

前編では、STARTUP DBに登録する企業のサービスに適したタグはどれなのか予測する仕組みをつくるため、AWSのコグニティブサービスを試して回り、「やりたいことを、それなりの精度でやるためには、自身で実装しないと厳しい」という結論になったというお話でした。

今回は、手前で開発したその仕組みについて、お話をさせてもらおうと思います。

学習モデル作成

前回も簡単に記載しましたが、学習モデルは、以下の図のようなフローで作成しています。

①学習を行うためのデータ取得と解凍・抽出

まず、言語の処理をするためには、自然言語の文章を構造化し大規模に集積したもの「コーパス」が必要になります。品詞などの情報を含んだ百科事典のようなものですかね。
「全集」とも呼ばれるそうです。

当初、STARTUP DBの中にあるデータだけで、コーパス作成を試みたですが、情報量が足りず、計算できなかったり、過学習が起きました。

後でベクトル化の話をしているのですが、ベクトル化できない言葉が多く、ベクトル化できたデータもベクトルの向きがおかしい…という現象が出てきたのです。
ベクトルは「大きさと方向を持つ量」です。[ 1, 3, 2.5 ]のような数のリストとして表現ができます。

もっと大量の、一般的な文章データが必要だということで、利用したのがWikipediaのデータです。

Wikipediaのコンテンツデータは、再配布や再利用のために利用できる一元化されたデータベース・ダンプでの提供が行われています。
日本語のダンプファイル(出力ファイル)は、こちらからダウンロードができるようになっています。

ダウンロードしたファイルは、bz2という圧縮ファイルになっています。
それを解凍すると、下の画像のようなXML形式のデータが確認できます。

このままだと使えないので、このXMLから本文を抽出する必要があります。

そこで抽出に使うのが、オープンソースで提供されているWikiextractorです。
名前の通りですが、Wikipediaのダンプファイルから本文を抽出するためのプログラムです。

ダウンロードした圧縮ファイルを指定して、このようなコマンドでWikiextractorを実行すると

python -m wikiextractor.WikiExtractor jawiki-latest-pages-articles.xml.bz2

本文が抽出された、複数のテキストファイルが保存されます。

テキストの中身はこんな感じです。

見て分かる通り、<doc ….>というような、不要な文が残ってはしまいます。
なので、このあたりの不要な文も除去して、学習の大元となるデータの完成です。

分かち書き

日本語は、英語などのスペースで区切られた言語と異なり、どこからどこまでが1つの単語なのか、判別が容易ではありません。

日本語の自然言語処理をするためには、その区切りを見つけるために、形態素解析を用いて分かち書きするというのが一般的です。

最近では、深層学習により適した前処理として、WordPiece、Byte-pair encoding (BPE)、 SentencePiece など、テキストを「サブワード」と呼ばれる単語よりも短い単位に分割する手法が用いられるようになってきていますが、深層学習を用いたいわけでもない、というのと、可能な限りブラックボックスにせず、見えるロジックで解いておきたいという思いがあり、昔ながらのやり方ではありますが、MeCab分かち書きを行うようにしました。

MeCab (和布蕪)とは、京都大学で開発された形態素分析のエンジンです。
2013年からバージョンは0.996のままですが、今でもよく利用されているエンジンです。

他の形態素解析のツールとしては、Sudachiというワークスアプリケーションズが開発したものや、JANOMEというオープンソースもあります。
検索・分析エンジンのElasticsearchでよく使われている、kuromojiというものもあります。

IPAdicやNEologdなどの辞書を使いたいとか、速度を重視した時にMeCabを使うのがお薦めです。(メモリの消費はよろしくないです)

このタグ予測の仕組みの場合、APIのリクエストを受けた時にも形態素解析を動かすようにするのですが、レスポンスに時間を掛けすぎないという目的もあり、MeCabを選択しています。

全部ひっくるめたモデルに文章をインプットして、タグが返ってくるようにするというよりは、途中途中の処理をホワイトにすることで、チューニングがちゃんと行えるようにしたいという意図もあり、APIのコントローラー上で形態素解析を動かす必要が出てきたという経緯です。

辞書は、新語・固有表現に強いNEologdを使っています。

新語に強いと言っても、スタートアップ界隈の言葉は全然カバーしきれず、独自の辞書が必要になりはするのですが…

MeCabを使い、①のテキストを分かち書きすると、以下のような結果を得ることができます。

ちなみに、品詞付での出力をするように設定して実行してます。

見て分かる通り、ノイズがとても多いですね。

「、」「。」などの記号、「の」「は」などの助詞、「きっと」「もっと」などの副詞、これらは、文章全体の意味を捉えるという目的に対しては、不要な情報と言っていいと思います。

なので、あらかじめ除外する品詞や単語を決めておき、分かち書きしながら、取り除くという処理を行います。

# 除外する品詞1リスト
except_main_features = ['記号', '助詞', '助動詞', '感動詞', '接頭詞', '副詞', '連体詞', '接続詞']
# 除外する品詞2リスト
except_sub_features = ['代名詞', '接尾','副詞可能', '自立', '非自立', '形容動詞語幹']

そうすることで、もう少し意味のある言葉のみを抽出することができます。

お見せしている例では助詞と副詞を除いてますが、結果次第では含めても良いかもしれませんね。

参考までに助詞、助動詞などを除いた場合、ベクトルの精度があがるという論文のリンクを貼っておきます。

分かち書き + ノイズの除去を行ったデータをS3にアップロードして、学習データの準備完了です。

③学習

前編でも紹介したSageMakerで提供されているアルゴリズムであるBlazingText、これを用いて、ベクトルデータを生成するモデルを作っていきます。

必要なプログラムは、sagemakerのパッケージに含まれているため、考慮することはハイパーパラメータ(機械学習を行うためのそのアルゴリズムに設定する値)をどうするかぐらいでしょうか?

自身で何度も試して決めることもできますが、自動でハイパーパラメータを調整する仕組みもAWSにはあるので、それを使うのもいいかと思います。

参考: https://t-redactyl.io/blog/2020/11/automatic-word2vec-model-tuning-using-sagemaker.html

まずは、BlazingTextのimageを取得します。

image = sagemaker.amazon.amazon_estimator.get_image_uri(region_name, "blazingtext", "latest")

そのimageを使って、Estimator(トレーニングとかするオブジェクト)を生成します。

estimator = sagemaker.estimator.Estimator(image,
                                          role,
                                          train_instance_count=2,
                                          train_instance_type='ml.c4.2xlarge',
                                          train_volume_size = 30,
                                          train_max_run = 360000,
                                          input_mode= 'File',
                                          output_path=s3_output_location,
                                          sagemaker_session=sess)

Estimatorに対して、ハイパーパラメータを設定後、

estimator.set_hyperparameters(mode="batch_skipgram",
                              epochs=5,
                              min_count=5,
                              sampling_threshold=0.0001,
                              learning_rate=0.05,
                              window_size=5,
                              vector_dim=100,
                              negative_samples=5,
                              batch_size=11, #  = (2*window_size + 1) (Preferred. Used only if mode is batch_skipgram)
                              evaluation=True,# Perform similarity evaluation on WS-353 dataset at the end of training
                              subwords=False) # Subword embedding learning is not supported by batch_skipgram

レーニングデータを指定し、

train_data = sagemaker.session.s3_input(s3_train_data, distribution='FullyReplicated',
                                        content_type='text/plain', s3_data_type='S3Prefix')
data_channels = {'train': train_data}

学習を開始します。

estimator.fit(inputs=data_channels, logs=True)

これでモデルの完成です。

出来たモデルに対して、単語を投げると、その単語のベクトルを得ることができます。

タグの予測

①サービスの説明文の分かち書きとベクトル化

STARTUP DBの管理画面にある、企業のサービス編集画面の「タグ予測」ボタンが押されると、Flaskで構築したアプリケーションサーバーにサービスの説明文が投げられます。
アプリケーションサーバーには、学習用のデータを作成したサーバーと同様に、MeCabがインストールされており、分かち書きが行われます。

アプリケーションサーバーは、その後、分かち書きされたサービスの説明文をBlazingTextで作成したモデルが乗っているエンドポイント(MLホスティングインスタンス)に投げて、各単語のベクトルを取得します。

②タグの一覧の取得とベクトル化

アプリケーションサーバーは、タグの一覧を、企業情報用のサーバーからAPIを叩いて取得します。

その後、アプリケーションサーバーはサービスの説明文と同様に、タグ一覧をモデルが乗っているエンドポイントに投げて、各タグのベクトルを取得します。

③ベクトルのクラスタリング

分かち書きで得た単語の数は、もちろん一つではなく、ベクトルの向きも様々です。
近似のタグを見つけるためには、それらを集約させる必要があります。
そのために、得られたベクトルをクラスタリングさせる必要があります。

複数のベクトルの集まりをテンソルと言いますが、テンソルはn次元の行列という形で表現ができ、行列の次元を削減するためにクラスタリングを利用しています。

次元を削減するというのは、n次元の行列をk次元に減らすという作業です。

次元削減自体にも、主成分分析 (Principal Component Analysis: PCA) や非負値行列因子分解(Non-negative matrix factorization: NMF)など次元削減の手法がありますが、今回の内容においては、クラスタリングでいい、という判断をしています。

SageMakerの提供しているアルゴリズムの中にも、クラスタリングを行えるアルゴリズムがあります。ただし、問題になるのは、そのアルゴリズムの種類です。

SageMakerで用意されているクラスタリングアルゴリズムは、K-meansです。
K-meansは、中心を仮定してクラスタリングする方法で、今回の目的とは実は合致しません。

と、言葉で言っても分かりにくいですが、Python機械学習ライブラリであるscikit-learnのWebページに非常に分かりやすい図があります。

参照: https://scikit-learn.org/stable/auto_examples/cluster/plot_cluster_comparison.html

K-meansは1番左の列の図になりますが、図にもみられるように、境界を越えてクラスタリングが行われてしまうのが見えますでしょうか?

また、密度連結成分を検出するDBSCANは、非常に綺麗に分けてくれるアルゴリズムではありますが、

境界がなさ過ぎるとすべて同じクラスタとして見なされてしまいます。

今回のケースだと、似たようなまとまりの集まりだったとしてもそれをいくつかの方向にクラスタリングして欲しいところです。

なので、タグ予測でやりたいクラスタリングを考慮し、アルゴリズムはSpectral Clusteringを選択しています。

Spectral Clusteringは、固有値によるスペクトル分解を行うもので、内部でK-meansやDBSCANのロジックが動いていたりします。

このSpectral Clusteringを利用するため、SageMakerは利用せず、アプリケーションサーバー内にscikit-learnを用意し、Spectral Clusteringを用いたクラスリングを行わせるという方針をとっている訳です。

クラスタリングしたのち、クラスタリングしたベクトルの平均合成を行い、クラスタの方向を導き出します。

④コサイン類似度を用いた類似のタグの算出

ベクトルの近似値は、「コサイン類似度」によって求めることができます。

ベクトルの行列を内積やらなんやらすることで計算することができます。

参考: https://www.cse.kyoto-su.ac.jp/~g0846020/keywords/cosinSimilarity.html#:~:text=%E3%82%B3%E3%82%B5%E3%82%A4%E3%83%B3%E9%A1%9E%E4%BC%BC%E5%BA%A6%E3%81%A8%E3%81%AF,%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%81%93%E3%81%A8%E3%81%AB%E3%81%AA%E3%82%8B%E3%80%82

アプリケーションサーバーは、タグのベクトルと、クラスタリングされた説明文のベクトルを比較し、近い順にランク付けを行い、管理画面に返します。

最後、これを管理画面で表示してあげるだけです。

課題

この方法には、まだいくつか課題が残っています。

Wikipediaのデータが一般的過ぎて、サービス固有の名前や説明がうまくベクトル化できない → コーパスにスタートアップ関連の記事を多く取り込む必要がある

②辞書に無い言葉がサービスに多く出てくるため、うまくベクトル化できない単語がある → 独自辞書に随時言葉を登録していく作業が発生する

③あっちこっちで処理をさせるようになっており、仕組みが複雑 → SageMakerで動くモデルを自作し、そこに投げるだけでいい仕組みにしてもいいかもしれない

などが、大きな課題です。

まとめ

ブラックボックスにし過ぎず、理解できるロジックで組み上げたことで、細かい調整がきき、精度も確かに出るようになったと思います。ただし、課題にも挙げているように、予測したい文章と学習させる文章が合うかどうか、未知の言葉に対する対応など、潰しきれない課題はどうしても出てくるものだと実感させられました。

文中でも記載しましたが、深層学習に適した前処理なども確立されてきていますし、日本語で、BERTを用いた自然言語処理などもでてきており、 そういうものを導入することで、未知語への対応も、より高い精度の学習もできる可能性があります。そのような新しい仕組みに入れ替えることも考慮に入れた上で、引き続き、ブラッシュアップをしていこうと思っています。

【フォースタ テックブログ】STARTUP DBリニューアルについて 〜スタートアップ業界にとって新たな一歩をつくる〜

2021年3月に、国内最大級の成長産業に特化した情報プラットフォームである「STARTUP DB」(スタートアップデータベース)のサービスリニューアルを行いました。本記事では、プロダクトオーナーと開発責任者それぞれの目線から今回のリニューアルについて纏めてもらいましたので、リリースに至るまでの道程をご紹介します。

プロダクトオーナーが語るサービスリニューアルについて

こんにちは、弊社で運営している成長産業に特化した情報プラットフォーム「STARTUP DB」のプロダクトオーナー寺田(@yuyaterada)です。この度、2021年3月18日にサービスリニューアルとあわせて、ENTERPRISE β版の機能リリースをしました。リリースまでの経緯とリニューアル内容について紹介をしていきます。

リリースまでの経緯、コンセプト

STARTUP DBは2018年5月31日にサービスを開始してから間もなく3周年を迎えます。

約1年前にプロダクトに関わるメンバーでプロダクト合宿をし、STARTUP DBで目指す世界観やプロダクトポリシーなどについて議論しました。コロナ禍でもあった為、リモートでGoogleのJamboardを使って議論を進めました。その合宿の中で、スタートアップエコシステムとは?誰に対してどんな価値を提供するのか?など深い議論を重ね、チームとして『国内スタートアップエコシステムのキャッシュフローの総量を増やすこと』をプロダクトミッションとして、国内スタートアップとエコシステムビルダー、それぞれの信頼できるパートナーとの出会いを創出することを目指していく方針になりました。

※プロダクト合宿でつかったJamboardの1例

そこで、よりミッション達成に向けて推進するべく、サービスリニューアルPJTを開始しました。

STARTUP DBでは会社のバリューでもある「Startups First(注1)」をプロダクトポリシーとして一番重きをおいています。それを第一前提に、合宿で話をした、直近で実現したいこと、中長期的に達成したいことを踏まえ、リニューアルプロジェクトを進めました。検討を進める中で既存UIでの追加機能開発も検討としてありましたが、アウトプットの点で実現できない部分があり、今回リニューアルという選択をとりました。

2020年5月頃からN1分析(注2)をスタートし、ユーザーシナリオなどを詰めていきました。10月頃から開発をスタートし、約半年弱の開発期間を経て、リニューアルリリースしました。

注1:全ては日本の成長のために。スタートアップスのために。スタートアップス=『進化の中心』にいることを選択する挑戦者達。

注2:1人の顧客を深く知り、そこからアイデアを掴んで実践に落とし込むという手法。西口一希氏著の「たった一人の分析から事業は成長する 実践 顧客起点マーケティング」より

スタートアップとの事業創造をサポートする機能「ENTERPRISE」

今回サービスリニューアルに合わせて、「ENTERPRISE β版」という機能もリリースしています。「ENTERPRISE β版」は、スタートアップとの事業創造をサポートする機能です。主に大手事業会社や投資家を中心としたエコシステムビルダーの皆様と国内スタートアップ、それぞれが信頼のできるパートナーとのアライアンス機会を創造していき、ひいては、スタートアップ、エコシステムビルダー双方のグロース支援に繋げていきたいと考えています。

ENTERPRISE β版」は先着30社審査制で6月末まで無償提供をします。7月以降の正式版リリースに向けて、利用企業と伴走しながら、プロダクトのアップデートをしていく予定です。リリース後多くの反響を頂き、既に先着30社の受付は終了しており、現在正式版の事前案内申込(特典あり)を受け付けしています。

開発責任者が語るリニューアルに伴うシステム変遷

こんにちは。アクセラレーション本部 テックラボグループの竹内です。ここからはSTARTUP DBのリニューアルの技術的な部分について説明します。

リニューアルに伴い変更したインフラ構成

旧STARTUP DBの構成図

新STARTUP DBの構成図

技術構成について

STARTUP DB(NEW)

言語:TypeScript
フレームワーク:Nuxt.js
インフラ:ALB, CloudFront, ECS, Fargate, ElastiCache, S3

SDBユーザー管理システム(NEW)

言語:Ruby
フレームワークRails
インフラ:ALB, ECS, Fargate, ElastiCache, RDS

SDB管理システム

言語:Ruby
フレームワークRails
インフラ:ALB, CloudFront, EC2, RDS, S3, ElastiSearch(NEW)

インフラの変更点について

まず大きな変更点としてRailsで作成していたSTARTUP DBをフロントエンド(STARTUP DB)とバックエンド(SDBユーザー管理システム)に分離しました。さらにEC2からECS+Fargateにしました。Fargateを選択することでEC2インスタンスを一切管理する必要がなくなり日々の負担が大きく軽減できたと思います。SDB管理システムがまだEC2ですが、今後同様にECSにしていく予定です。
SDB管理システムには全文検索を行うためのElasticsearchを追加しています。検索については後述しています。
これらのインフラはTerraformを利用してコード管理できるようになっています。

フロントエンドについて

Nuxt.jsでSSRモードを選択しました。また、CompositionAPIを採用しています。
これはCompositionAPIがVue3.xで正式に採用され今後の主流になるだろうと思ったこと、そしてレイアウト実装とロジックの分離を行いやすくなることを期待して選択しました。
個人としてはロジックの外出しに関してはうまくできたのではないかと思っています。

機能

認証方式の変更(Firebase Authentication)

今回のリニューアルで認証の実装をFirebase Authenticationを利用して認証する方式に変更しました。Firebaseのおかげでアプリケーション側のDBにはFirebaseのuidさえ保存しておけばユーザー管理ができるようになるため、よりセキュアな状態になっています。

Elasticsearchを使っての全文検索

今回、Elasticsearchを導入し、企業名および通称名だけでなく企業紹介の内容やサービス内容でも検索できるようになりました。
これにより、よりスタートアップの情報をお届けできるようなったと思います。ぜひ「ロボット 開発」「ロボット 利用」など色々なキーワードで検索してみてください。
検索結果画面の投資企業は検索キーワードでヒットしたスタートアップに投資している企業が並ぶようになっています。こちらもぜひ利用してみてください。
今後よりブラッシュアップしていきますので楽しみにしていてください。

全ポジション仲間募集中です!

STARTUP DBのプロダクトミッション『国内スタートアップエコシステムのキャッシュフローの総量を増やすこと』を達成していく為にはまだまだ序章です。今後スタートアップ、エコシステムビルダー双方のマッチング機会を増やしていくことで、事業創造の可能性を広げ、スタートアップエコシステムをブーストさせていきたく考えています。やりたいことがまだまだたくさんあり、是非1人目の事業開発、エンジニア、デザイナーなど全方位で仲間を募集しています!

【フォースタ テックブログ】タグの自動予測について。STARTUP DBに機械学習を組み込んだ話【前編】

f:id:forStartups:20211025162928p:plain

はじめに

こんにちは。テックラボの松原です。

先日(2021年3月18日)に、「STARTUP DB サービスリニューアル & ENTERPRISE β版リリース」をしました!

 

startup-db.com

「国内スタートアップエコシステムのキャッシュフローの総量を増やす」というプロダクトミッションのもと、国内スタートアップとエコシステムビルダー、それぞれの信頼できるパートナーとの出会いを創出することを目指して、今回のサービスリニューアルを行いました。

サービスリニューアルでは、下記の機能が利用できるようになっています。

  • フリーワード検索機能
  • タグ検索機能
  • ENTERPRISE β版

※「 ENTERPRISE β版」について
スタートアップエコシステムにおける事業会社、投資家を中心としたエコシステムビルダーの方々と、国内スタートアップ、それぞれが信頼のできるパートナーとのマッチング機会の創造をサポートする機能です。

タグについて

上述しているように、リニューアルしたSTARTUP DBでは、「タグ」という概念が加わっています。

リニューアルしたSTARTUP DBをお使いの方はお気づきかと思いますが、タグが企業やサービスの説明文の下に付けられています。

以前のSTARTUP DBを使われていた方は、「あれ??付いていたような?」と、思われるかもしれませんが、以前のSTARTUP DBに付いていたのは「カテゴリ」です。
リニューアルに伴い、「カテゴリ」を廃止し、今回から「タグ」という分類を行なうようにしました。

STARTUP DBでの「カテゴリ」と「タグ」の定義の違いは、後ほど説明します。

「タグ予測機能」について

エンドユーザーには、今のところ関係のない機能です。

STARTUP DBのデータは、プログラムで自動的に収集している情報もありますが、人の手でこつこつと入力していっている情報が大半です。

完全に自動化してしまわないのは、人的に行う部分を挟むことで、データの品質を保つようにしているからです。

そして、タグ(前カテゴリ)の付与は、そんな人的な作業が大きくかかる作業でした。

企業名、企業の説明、企業の役員、企業への投資、企業が提供するサービス等、企業に関する様々な情報を確認し、これらに適したタグを100以上あるタグの中から選び出すのは、それなりに骨の折れる作業です。

タグ予測機能は、そんな運用の作業を改善するために、実装した機能です。
(今後、この機能をどのように展開していくかは、まだ未定です)

カテゴリ廃止の決断

前STARTUP DBで使っていた「カテゴリ」は、以下の図に示すように、ツリー構造で、企業のサービスに紐付くデータ設計になっていました。

そのため、「医療」カテゴリで「AI」というサブカテゴリを使いたい、でも「農業」カテゴリでも「AI」というサブカテゴリを使いたい、というような要望を満たすためには、同じ名前のサブカテゴリを用意せざるを得ませんでした。

また、検索も「カテゴリ」→「サブカテゴリ」という検索を行うように画面が設計されていたため、横串な検索を素直に行えない状態にありました。

もちろん、力技でもできなくはないですが、リニューアルに伴い、データの構造を見直し、自由度の高い検索を簡潔に行えるようにしましょう、ということで、「カテゴリ」を取っ払い、「タグ」という、多対多の形を取れる仕組みにする、という決断がされたわけです。

タグ予測(機械学習)を実装する決断

タグの実装が決まってすぐは、タグ予測を実装するなんて話はもちろんありませんでした。

タグの実装を進めながら、一方で、どのサービスにどのタグが紐付くのか、それらを一覧にしていく作業の中で、「まだ、あと、8,000件…」と、時間を掛けたにも関わらず、出来高が乏しく…「今の作業だけでなく、今後の運用も考えると、自動でタグが付いてくれる仕組みがいるんじゃないか」という、我らがPMのお言葉により、タグを自動で付ける仕組みをつくってみましょう…!となったわけです。

方針設定

STARTUP DBは、サービスをローンチしてから約3年の月日が経ち、内部のデータも相当のものになっています。

ただ、データがいかに溜まってて、学習をさせる材料があろうと、すべてのタグを、狂いなく、人間が想定するとおりに、完璧に付けることができる程、(少なくとも私は)機械学習での精度を保証できないので、「管理画面でレコメンドが行われるようにする」という方針を立てさせてもらいました。

はじめにのおわりに

長い長いはじめにでしたが、この記事では、そんな「タグ予測」を、どのように実装していったかをお話していこうと思います。

仕組み

現在、この下に記すような構成で、タグ予測を行っています。

タグの予測

現在、タグの予測はこのように行われています。

①運用ユーザーが管理画面で、「タグ予測」ボタンをクリックします。

②企業のサービスの説明文が、アプリケーションサーバー(Flaskで稼働)に送られます。

アプリケーションサーバーは、タグの一覧をマスタから取得し、タグ一覧と、分かち書きされたサービスの説明文を、SageMakerで作った推論用のエンドポイント(MLホスティングインスタンス)に送ります。

④MLホスティングインスタンスは、学習済みのモデルを用いて、タグと、分かち書きされたサービスの説明文をベクトル化し、それらのリストを、アプリケーションサーバーに返します。

アプリケーションサーバーは、説明文のベクトルをクラスタリングし、各クラスター毎に平均合成したベクトルの算出を行います。その後、コサイン近似を用いて、平均合成したベクトルとタグのベクトルの近似値を求め、近しいベクトルのタグを管理画面に返します。

もっとSageMakerに寄せられる部分もあるんじゃないかと思う構成ですが、検討を行った時は、アルゴリズムの日本語対応の状況や、使いたい種類のアルゴリズムがないなど、いくつかの課題に引っかかり、このような構成になりました。

これも詳しい話は後ほど。

学習モデルの作成

MLホスティングインスタンスで使っているモデルは、以下のようなフローで生成しています。

Wikipediaから学習を行うための圧縮されたデータを取得し、解凍します。

②解凍されたテキストの分かち書きを行い、ストレージに保存します。

③SageMaker上で分かち書きされたテキストを用いて、学習を行い、ストレージにモデルを保存します。

こちらの具体的な話は、後編にて。

検証開始

「企業で」機械学習を始めるとなった場合、まず、何から行えばいいのでしょうか?

このタグ予測の開発では、以下の優先順位で検証を進めていきました。

1. コグニティブサービス検証
学習済みのモデルが組み込まれており、値を与えると結果が返ってくる、機械学習のサービスを利用できるかどうか検証する。
2. 提供されているアルゴリズム検証
提供されているアルゴリズムを用いて学習を行わせ、モデルを作成し、そのモデルを利用して値を与えると結果が返ってくる仕組みを作り、想定の結果を得ることができるか検証する。
3. 独自でアルゴリズムから開発
目的に合致するアルゴリズム自体を開発し、学習を行わせ、モデルを作り、そのモデルを利用して値を与えると結果が返ってくる仕組みを作り、想定の結果を得ることができるか検証する。

今回の記事のミソになるのは、「企業で」というところだとも思っています。

優秀な機械学習のエンジニアは、やはり単価も安くはありませんし、社内にほいほい生まれてくるわけでもないので、「運用していく」ということを考えると、(インフラもそうだと思いますが)可能な限りマネージドなものを利用していくのが基本的には、是なのではないかなと思います。
(もちろん、会社のビジョンや、サービスの内容にも左右されるとは思います)

そういった理由で、タグ予測の検証を、上記した順に従って進めて行きました。

コグニティブサービス検証

昨今、AWSGCPもAzureも、その他あらゆるサービスも、ある程度のことは、機械学習の知見がなくても、お手軽にできてしまうような機械学習のサービスを出しており、ゴリゴリ頑張らなくても、目的さえ合致してしまえば、できてしまったりします。

例えば、AWSの場合、以下のようなコグニティブサービスが提供されています。

  1. Amazon CodeGuru(コードレビュー)
  2. Amazon Rekognition(画像解析・動画分析)
  3. Amazon Fraud Detector(偽アカウントオンライン不正の検知)
  4. Amazon Comprehend(テキスト内のインサイトや関係性を検出)
  5. Amazon Comprehend Medica(Amazon Comprehendのサービスを医療向けに特化したもの)
  6. Amazon Textract(画像化された文書からテキストとデータを抽出)
  7. Amazon Translate(テキスト翻訳)
  8. Amazon Transcribe(音声認識
  9. Amazon Polly(テキストを音声に変換)
  10. Amazon Lex(チャットボット)
  11. Amazon DeepComposer(GANによる作曲)※専用キーボードが必要
  12. AWS DeepLens(動画解析)※専用ハードウェアが必要
  13. Amazon Forecast(トレーニングデータから時系列予測モデルを作成)
  14. Amazon Personalize(トレーニングデータからパーソナライズと推奨のモデルを作成)

タグ予測においては、「単語や文章から、マッチするタグを見つけ出す」という処理を行いたいので、コードレビューや音声変換のサービスを利用する必要はないというのは言うまでもありません。

コグニティブサービスの説明に、さっと目を通した感じでは、「4. Amazon Comprehend」と、100歩譲って「14. Amazon Personalize」が使えそうかな、というアタリを付けて、この2つの検証をまず行いました。

Amazon Comprehend

AWSの説明を引用すると、「機械学習を使用してテキスト内でインサイトや関係性を検出する自然言語処理NLP)サービスです。機械学習の経験は必要ありません。」というサービスです。

2019年の11月にプレスリリースで日本語が追加された旨が記されており、もしかすると使えるのではという予感のもと検証を開始しました。

結論。目的とは得られる結果が、絶妙に合致しませんでした。

このサービスは、文章内の単語が人名なのか、数量を表すものなのか等の、各フレーズの属性を分析してくれたり(Entity)、文章内の主要なキーワードは何なのかを見つけてくれたり(Key phrases)、文章の感情分析をしてくれたり(Sentiment)するのですが、これらの結果を利用して、タグを導きだす…というのがどうにも難しいなと…

例えば、上の画像は某サイトのHTMLのTEXTに対して、Entitiesを実行した結果ですが、確かに、それぞれのフレーズのTypeは分かります。

ですが、このQuantity、OrganizationのようなTypeが分かったところで、如何にしてタグへと置き換えて行くか、私の頭では繋がらなくて…断念。

Key phraseならば、出てきたKey phraseとタグをマッピングさせて、想定と近しいことができるのではと思ったのですが…

何か、そうじゃない。

与えるデータが悪かったのは、もちろん、そうなのですが、文章の主要なワードがでてきたところで、文章全体を表すワードを出せるとは限らず、結局タグとの紐付けで、もう一段階何かしらロジックが必要になるなと、こちらも…断念。

他にも、Amazon Comprehendの中には、「Custom classification」という機能があり、学習データを用意して、モデルを作成することで、独自の解析を行うことができるようなるのですが、これは日本語の対応がまだできておらず…

上の画像にあるとおり、タグとテキストの学習データさえ用意すれば、うまくできるかなと思ったりもしたのですが、言語の壁はどうしようもないところでした。

できたとしても、フレーズとタグの分類はできるかもしれませんが、文章とタグの分類はできなさそうですし、これも…断念。

Amazon Personalize

AWSの説明を引用すると、「Amazon.com がリアルタイムのパーソナライズされたレコメンデーションに使用するのと同じ機械学習(ML)テクノロジーを使用してアプリケーションを構築できます。ML の専門知識は必要ありません。」というサービスです。

ECサイトの商品のレコメンドと同じようなロジックで、タグ予測もできないかと考え、検証を行ってみたわけです。

結論。インプットさせるデータがうまく合いませんでした。

というのも、レコメンドを作成するために、下の画像のような、データの定義が必要になります。

つまり、文章のような非構造なデータのインプットがそもそもできないので、今回のデータとは合わないということになります。

私自身、レコメンドの開発に関わっていたことがありましたが、商品の購入履歴やユーザーの行動履歴など、構造化されたデータをその時も使っていましたし、非構造なデータでレコメンドを行うためには、全く違うロジックが要りますよねぇと…断念。

検証の結果

GCP、Azureなどのコグニティブサービスも試してはみましたが、同様に、日本語未対応が問題になったり、結果やインプットが合わないなど、タグ予測をコグニティブサービスで行えるようにするのは、現時点では難しいなと判断し、次の検証を進めることになりました。

提供されているアルゴリズム検証

提供されているアルゴリズムと曖昧な書き方をしましたが、今回利用を検討したものは、Amazon SageMakerに組み込みで提供されているアルゴリズムです。

Amazon SageMakerは、AWSの説明を引用すると、「ML 専用に構築された幅広い一連の機能をまとめて提供することにより、データサイエンティストとデベロッパーが高品質の機械学習 (ML) モデルを迅速に準備、構築、トレーニング、およびデプロイするのを支援します。」というサービスです。

つまり、これだけ使えば、機械学習で必要なあれこれがすべてできますよ、というサービスです。

SageMakerは、デフォルトで以下のようなアルゴリズムを提供してくれています。
それ以外にも、AWS Marketplaceから、アルゴリズムを買うこともできるようになっています。

ベクトル化を行う「Object2Vec」もしくは、テキスト分類を行う「BlazingText」が、今回の目的に合致するのではないかと考え、この2つの検証を進めました。

Object2Vec

AWSのブログ(https://aws.amazon.com/jp/blogs/machine-learning/introduction-to-amazon-sagemaker-object2vec/ )の説明を読むのが正確ですが、簡単に例えると、「リンゴ」と「ミカン」をインプットにして、ラベルを「果物」として学習させれば、2つの情報から分類ができるモデルが作成でき、「ラーメン」と「蕎麦」をインプットしてラベルを「1」、「ラーメン」と「リンゴ」をインプットしてラベルを「0」として学習させると、2つの情報の類似度を推論するモデルが作成できる、というようなアルゴリズムです。

画像引用元: https://aws.amazon.com/jp/blogs/machine-learning/introduction-to-amazon-sagemaker-object2vec/

ラベルと2つのインプットが必要になるので、用意するデータはこのようなフォーマットになります。

{"label": 1, "in0": [774, 14, 21, 206], "in1": [21, 366, 125]}

タグ予測の場合だと、以下のような学習を行うことができるかと思います。

① Skip gram(https://towardsdatascience.com/skip-gram-nlp-context-words-prediction-algorithm-5bbf34f84e0cのように、「文」と、「その周辺の文」をインプットとして、「タグ」をラベルにする。
(参考: https://hironsan.hatenablog.com/entry/object2vec-training-by-japanese-dataset
②「タグ」と「文」をインプットとして、ラベルを「0〜1」(類似度)にする。
設定済みのタグと、企業のサービス情報をSTARTUP DBから抽出し、①②の方法で学習させ、検証してみました。

結論。精度が出ませんでした。

Object2Vec自体は汎用性の高い、良いアルゴリズムだと思います。
しかし、単語レベルなら精度も出たかもしれませんが、やはり、文章というのが多様すぎるためか、学習させるデータが圧倒的に足りない、という印象でした。

データをこつこつコツコツ作ってて精度を上げてくことも考えましたが、もっと上手く解ける方法があるのではないかと、他を模索することにしました。

BlazingText

BlazingTextは、word2vecを行う行うアルゴリズムです。

word2vecに関しては特に語る内容もないかなとは思うので、説明はこれだけです。

結論。これを採用してできるようになった、というわけではないですが、最終的にはこのアルゴリズムを全体の仕組みの中に組み込みはしました。

検証の結果

直接的に、企業の情報とタグを紐付けられる都合の良いものはないのだと思い知らされることになりました。
ただ、アルゴリズムが単に合わないということだけではなく、これらの検証をやる中で、目的に対して、データの総量が多いように見えて少ないことも、上手くいかない原因だということが見えてもきました。

STARTUP DB内部のデータだけで学習用のデータを作って推論させるというのは、少し無理があるのだと。

推論を行わせるためにどういうデータを準備すべきか、少ないなら少ないでどういうロジックを組めばいいか、もう少し検討する必要がありそうだ…という知見を得てからの、次の段階、独自での実装の始まりです。

前編のまとめ

運用を考えて可能な限りマネージドに…と最初に書きもしましたが、そうは問屋が卸してはくれず、完全に満足する結果が得られないから、結局、独自に実装しないといけなくなる、というのが、今なんだろうなと思わされました。

後編では、実際に今動いている仕組みの内容を、詳しく説明していこうと思います。

 

後編に続く

【フォースタ テックブログ】フォースタートアップスでやったチームビルディングを色々と挙げていく

f:id:forStartups:20211025164523j:plain

どうも、村林(@bayashimura)です。今回は私が入社してから開発チームで行われたチームビルディングの色んな手法を参加者の感想とともに紹介していこうと思います。

ドラッカー風エクササイズ

出典:アジャイルサムライ

 

shop.ohmsha.co.jp

10月に速水が参加したタイミングで実施しました。

  • 自分は何が得意なのか?
  • 自分はどういうふうに仕事をするか?
  • 自分が大切に思う価値は何か?
  • チームメンバーは自分にどんな成果を期待していると思うか?

というのをチームメンバーが各自答えて、チームメンバー同士の相互理解や期待値のすり合わせを促進します。

今回の実施では追加の質問として

  • 他のチームメンバー(各個人)に期待することは何か

というものも付け加えております。これはジョハリの窓で言う秘密の窓を開くだけではなく、盲点の窓を開くこともチームビルディングにおいて重視しているからです。新しく参加したメンバーに関しては期待値のすり合わせ、今まで一緒に活動していたメンバーに対してはフィードバックの作用が望めます。

ジョハリの窓とは

自己には「公開されている自己」(open self) と「隠されている自己」(hidden self) があると共に、「自分は知らないが他人は知っている自己」(blind self) や「誰にも知られていない自己」(unknown self) もあると考えられる。

これらを障子の格子のように図解し、格子をその四角の枠に固定されていないものとして、格子のみ移動しながら考えると、誰にも知られていない自己が小さくなれば、それはフィードバックされているという事であるし、公開された自己が大きくなれば、それは自己開示が進んでいるととる事が出来るだろう。

Wikipedia より引用

実際に実施した際には

  1. ホワイトボードに枠を作っておく
  2. 各々上記の質問を書いておく(まだ貼らない)
  3. 一人ずつみんなに説明しながら貼っていく
  4. 最後に発表しているその人に期待することをみんなが説明しながら貼っていく

というスタイルで行いました。

参加したメンバーの感想はこちらです

相手が得意だと思っていること,バリューを発揮しようとしていることと,周りが期待していることのギャップを認識できると,作業を分担するときのコミュニケーションの取り方により気を遣うことができるので重要だと思った
やっぱり個々人何が得意だと思っているのか自分の言葉で説明を聞けて面白い
自分が武器だと思っているもの、自分が大切に思っていることを周囲に無理なく伝えられるのでとても良い
 

16personalities

画像引用元:https://www.16personalities.com/country-profiles/japan

 

www.16personalities.com

いわゆる性格診断です。

深い自己開示や期待のすりあわせにはつながりませんが、時間をかけずにパッとできるのでお手軽に出来ます。
どちらかと言うとこれを実施し、共有したあとのコミュニケーションに役立てそうです。

各自上記のウェブサイトで答えてそれをSlackで共有するという形で実施しました。

参加した人の感想はこちらです

楽しいし,自分で読んでて当たっていると思う
とても細かくて正確なんだろうけれど,ちょっと長いので結局チームの他の人のパーソナリティを記憶できてない
個々人が勝手にできるので、会社全体など大きい枠組みでやると効果的かも。話をしたことのない人に対して「論理型なんですね、僕も論理型なんですよ」などといったコミュニケーションの糸口に使えそう

自己紹介LT大会

今年の2月にホさんが加入したため、自己紹介を兼ねてLT大会をしました。
単純に5分くらいで自分紹介するLT大会をしたというだけです。
各々の個性が出るようにフォーマットは特に指定しなかったところ
甲斐(@MeguruKai)の見たことないクオリティの宣材写真が出てきたり藤井(@yutafujii)が全編に渡りジントニックの作り方に終始したりとツッコミどころにあふれる会になりました。
とても楽しかったです。

ちなみに私の発表資料はこちら。

参加したみんなの感想はこちらです。

仕事以外の分野の話をたくさん聞けて、純粋に楽しかった。大切にしている価値観や、考え方に大きな影響を与えた経験など、広く人生に関わる話は、なかなか普段の中で聞くことができない。
自己紹介とはいえ、型式に囚われず様々な角度で発表していたので非常に面白かったです。個人的には発表のフォーマットを決めてなかったフランクな取り組みが良いと思っていて、発表内容のピックアップや進め方も含め、自己紹介になっていた気がします。また、純粋にチームメンバーを違う側面をみることができなたので、メンバー個人への興味もあがりましたねー
フォーマットと内容が自由だったことで,その部分にも個性が出た気がしており,初めて開催したからこその面白さがあった気がする。結果的には詳細まで記憶できないけれど、その人その人にキーワードが結び付けられるだけでもとても有意義だったと思う
自己紹介を改めてするというのは良いですね。会社にジョインしたタイミングが違うので、日が浅い人にとっても知るきっかけが出来ますし、逆に「今まで言ってなかったけど伝えておきたい」みたいなことも改めて伝えられるので、チームビルディングによいなと思いました!

webox values card

画像引用元:https://wevox.io/valuescard

 

井原(@tossy_yukky)が買って持ってきたので実施しました。

 

wevox.io

カードに「友情」「愛」「本能的」など価値観にまつわるカードが書かれており、それを引いたり捨てたりすることで自分自身の価値観を表す5つのカードを集めるというゲームです。

やり方としては以下の通り

  1. カードを切り、1人5枚ずつ配る
  2. 残ったカードは全て伏せた状態で中央に置く
  3. カードを引く順番を決める
  4. 順番になったら「山」または「テーブルの上」にあるカードから1枚カードを引く
  5. 手元にあるカードの中から自分の価値観に一番遠いカードを捨てる
  6. 次の人に進み、カードの山がなくなるまで4〜5を繰り返す
  7. 残った5枚のカードを使い、自分の価値観を参加者に説明する

ルールブックより引用

5人くらいが適正な人数かなと思い、うちでは2回に分けて実施しました。
一度目はシンプルに上に書かれたルール通り実施し、二回目は「誰がどんな価値観を捨てたかが面白い」ということに気付き、麻雀のように自分が捨てたカードは自分の前においていくようにしました。

 

個人的に面白かったのが藤井が「愛」と「友情」と「幸せ」を捨てて、最後に残った手札に「遊び心」が入っていたことと
竹内(@manbo34)がCTOの戸村(@KenjiTomura)の目の前で「計画」「努力」「勝利」をバンバン捨てていたことです。

楽しみ方ですが捨てる時に捨てるカードを宣言すること(e.g. 私は家族を捨てます)と、それに対して周りがやいのやいの言うと盛り上がります。

参加したみんなの感想はこちらです。

カードきれい,楽しい
5枚に絞るのが難しく,重要なもののなかで優先度をつけるのでそこに価値観が現れて興味深いし自分の思考整理にもなった
プレイ中に相手が捨てるカードを見て、強く相手に興味を湧いた記憶があります。愛(家族?)や幸せを捨てる人の残しているカードは何なんだとw中だるみせず、最後の結果確認まで楽しかったです。」
似ているがニュアンスが異なる言葉が出てくるので、自分の価値観表現として、この言葉が本当にベストか考えるキッカケになりました。

無礼講ースター

画像引用元:https://yonasato.com/column/teambeerding_bureiko/

よなよなエールで有名なヤッホブルーイングが出している(いた)チームビルディング用、ビアコースターです。
ビアコースターなので対面での飲みの場での使用を想定されていますが、リモート飲みでも、飲みの場じゃなくても使用可能です。

ルール

  1. 親はテーマコースターの山札から1枚引き、読み上げます
  2. 親はお題にYES,NOコースターで答えます。回答が見えないようにビアグラスで隠します。
  3. 親以外のプレイヤーは親の回答を予想し、YES,NOコースターで答えます。これもビアグラスで隠します。(親にガンガン質問してもOK)
  4. 親以外のプレイヤーが一斉に回答をOPEN!時計回りに自分の回答理由を話します。
  5. みんなが話し終わったら、今度は親がYES/NOコースターをオープン!
  6. 親は自分の理由に一番近い回答者に、テーマコースターをプレゼント。

これを親役が一周するまで繰り返し、コースターの枚数が一番多い人の勝ち!

https://yonasato.com/ec/product/burei_coaster/より引用

このコースターはみんながそれぞれその人に対する印象を述べるっていうのが自己開示だけではなく他人から見た自分を教えてもらえるというのが良いですね。
これもジョハリの窓で言うと、秘密の窓の開放だけではなく、盲点の窓の開放が含まれています。

現在は販売がされていないみたいなので、もしやりたかったら周りの人で持っている人を探してやりましょう。
それか私に声かけてもらえればやりますのでお気軽にお声がけください。

感想です。

意外な嗜好性がわかる。絶対この人はこう!って思ってたのに実はそうでもなかった。ずぼらだと思ってたのに意外とマメだったり
フォースタ祭りの打ち上げで使いました!10人くらい人数がいる中でも、全員が参加でき会話しつづけられるコンテンツだった気がします!
(これはかなり前に全社イベントで使用された時の感想ですね。私の入社前)

以上で紹介は終わりです。

世の中にはこれ以外にもたくさんチームビルディングの手法がありますので、これからも色々と探してやってみようと思います。

あ、そうそうフォースタでは良いチームで良いプロダクトを作りたいエンジニアを募集しています。
是非ご興味あれば下のフォームから応募してみて下さい!