nakamura244 blog

所属団体とは関係なく、個人的なblog

2020年振り返りと2021年にむけて

2020年はどんな事をしていこうかとというのは下記の2019年振り返りの記事の最後に書きました

2019年の振り返り - nakamura244 blog

で2020年はどうだったか?

お仕事

仕事はまぁそこそこ頑張っております。もう直ぐ機械学習を活用した機能をリリースできるる所まできたかと思います。

機械学習を活用した機能といってもカバーすべき技術は結構広かったと思います。

利用するアルゴリズムの理解や特徴を十分に理解して使い所を定めたり、アンサンブル学習でうまく組み合わせたり、学習データを収集する仕組みを作ったり、ETLを構築したり、評価の為の仕組みを構築したりと一通りあります。

ほぼSageMakerを中心にクラウドをフル活用させてもらいました。

リリースまで無事に行ったらまた改めて振り返りたいと思います。

プライベート

大学院での学習を加速させた。2020年1月から科目履修を通じて学習を続けた。同時に自分の興味のあるformal verificationの分野の学習を続けた。

受講した大学院の講義は下記

一つ不合格だったが、それ以外は合格した。且つ100点を取れたものもあって良かった!!

本科生と同様の数の授業を受けました。これで仕事をしながらでも勉強が進められる自信につながったと思います。

そして、2021年は北陸先端科学技術大学院大学の本科生になって、formal verification分野の研究を本格的にやることになった

2021年に受けた講義は単位認定されるように申請する予定で、全部認めてもらうことが出来れば、ほぼほぼ修士論文に集中できる状況で2年間をフルに研究に没頭したいと思います。

といっても社会人学生なので平日は仕事に集中しつつ、夜と土日に研究していきます。

国立大学に進むことで費用的に最小限に抑えらる事が何よも良かった。

さらに振り返ると

2019年の11月にある教授に面談してもらった時の事を強烈に覚えています。

それはもう、久しぶりに技術で知識でボコボコに殴られて何もできなかった事です。その出来事が2021年の学業の活力になりました。

100点をとった科目はその教授が担当している講義で自分は少しでも認めてもらいたいと思い、フルコミットしました。講義資料を何度も読み直し、一字一句意図する意味を理解するように努めましたし、質問もたくさんさせてもらいました。

100点とった後に「素晴らしいです」ってお褒めのメールをいただいたのをとても覚えています。

その教授の研究室に配属予定です

2020年最大の出来事

第二子が誕生した!!🎉

第二子が生まれたばかりで大変な中、学業の時間を確保させてもらって家族には感謝です。

少し早く生まれてしまい、ずっと入院していたが、コロナ感染予防で病院に入る事ができず、1ヶ月ぐらい歯痒い思いをしていましたが無事に退院してくれて良かった。

で2020年はどうだったか

コロナという想定外の状況になりましたが、自分としては自分自身をパワーアップさせる良い期間として過ごす事ができたかと思います。

2019年に思った目標を確実に進められていると思っています。

2021年に向けて

  • 仕事と学業を引き続き頑張ります。
  • 英語をもう少しマシにします
    • 講義が英語オンリーでおこなれたり、講義資料が全て英語だったり、関連論文が全て英語だったり、必要性を十分に感じています
    • 院の入試の際にあなたの研究計画を英語で発表してみてって唐突に言われてほぼ答えられずに悔しい思いをしたのが残っている

大学院での学習を3ヶ月してみて

はじめに

去年の年末の振り返りと2020年に向けての記事で触れておりました。2020年の1月からとりあえず3ヶ月間、JAIST(北陸先端科学技術大学院大学)で科目履修生をしてみるというチャレンジが終わったので一応まとめておこうと思います

2019年の振り返り - nakamura244 blog

何を履修したのか?

3科目を履修した。ざっくりは下記のような感じ

  1. プロジェクトマネジメントに関する科目
    • PMBOKやSWEBOKが教科書となる分野の話
  2. IoTシステムアーキテクチャ
  3. コデザイン
    • ハードウェアの開発とソフトウェアの開発を初期段階から協調して行う手法の話

自分はソフトウェアエンジニアしかやってこなくて、3と1は全く未知の分野の科目。あとの1科目はわりと自分の中で知見があると思っていた分野

紙にペンで回路図を書いたりしたの初めてやった...。

一応、テストやレポートの提出もあり、単位取得の合否もでる

で、テストの結果

プロジェクトマネジメントに関する科目コデザインは単位取得できた。が、IoTシステムアーキテクチャ論は13点足りず落とした....。

結果として知見がある科目を落とすという結果になってしまった。恥ずかしい

未経験分野はそれなりの心構えで挑むが、知見のある分野は少し構えていた感じが、結果となったのだろう。

科目の内容以外で学んだ事

もちろんその科目の中での話で知らない事がたくさんあり勉強なりましたが、

それよりも内容を一字一句自分の中でちゃんと消化させて、自分の言葉で語れるぐらいまでならないと本当の理解になっていなくて、結果単位を落とすことになると感じた。

この辺は知識をつける所ではなくて、今までの知見なりを使って研究をする場という感じを痛感したのかな。

そして4月以降

さらに6科目を追加して12月まで科目履修を続けます。

4月以降はその大学院の基幹科目がたくさんあり、いわばメインストリームのことろの講義がたくさんある。本来ここを体験したかったので延長申請して許可してもらった。

1-3月までの経験を活かして5月からも頑張っていきたい。

ただ、コロナの影響で全オンラインで受けることになったが、致し方ない。

改めてMachine Learningの基礎を手に入れたので残しておく

はじめに

業務でも使うし、使っているし、研究を進める上でもMachine Learningを組み合わせた論文とか結構あるし、基礎を今一度やっておいて損はないなーと思って年末年始の時間を使って授業を受けてました

受講したコース

www.coursera.org

そして、パスした f:id:tsuyoshi_nakamura:20200114142920p:plain

少し振り返り

  • Pythonのライブラリを多用するとその中でどんな計算をしているかなど気にしなくってしまうが、そのあたりを改めて学べてよかった
  • Andrew Ng先生はとても丁寧で且つとてもわかりやすい授業で助かった
    • コースの途中で励ましてれたりする
  • 少しの数学知識と少しのプログラミング知識(Octave)があれば誰でも内容がわかると思うのでエンジニア以外でも為になる授業じゃないかと思う
  • 日本人でも多くの方が受講されているようで、さらに詳しい情報がググるとあるのでより勉強しやすいと思う

もちろんこの授業を受けたからと言ってすぐに機械学習が扱えるほど甘くはないが、入り口としてはとてもよく、ここで学んだ事をKaggleで試したり、業務の一部に適用してみたりして自分のものにするのが良いと思う。

GNU Octave

Kaggle: Your Home for Data Science

2019年の振り返り

今年も終わろうとしているので一応残しておこうかと思います

2018年からの振り返りから2019年にやりたいとしていた事

2018年の振り返り - nakamura244 blog

色々と外のコミュニティに参加する中で下記の勉強会は結構印象に残っている

"GO GLOBAL" meetup #1 - connpass

また全然レベルの違う感覚があった気がしている。

自分のエンジニアリングのレベルの低さを感じた気がした。

改めてエンジニアとしてもっと高いレベルに視点を持っていきたいなと感じた

グローバルレベルを意識しないとエンジニアとして先がなくなっていく危機感を感じた...


自らの意思を持って行動して得た経験や技術というのが最終的には残るのだなと感じた。

人から言われた事だったり、まぁ仕事だからやるかとか、でやった事は一つも自分の中に残っちゃいない。ある一定期間残っても最後は消える。

なので自分の中での積み上げをするにはやはり自らの意思を大切にしたいなと思っている。

来年はこの辺りを大切にしてエンジニアとして技術の鍛錬をしていきたいと思います。

自分のエンジニアリングを見つめ直して、再構築して、今後エンジニアとしていきていく道筋を模索する年にしようとしていた。らしい。


では時系列に振り返ってみる

1~3月

なんだかんだ昨年の6月頃から社内のpaymentチームに移動して色々あったが、テックリードとして仕事をしていた

自らの意思でプライベートな時間で年末年始もずっと会社の集中ルームや自宅にこもって、より良いシステムになるようにアーキテクチャ、コーディングを頑張っていた。この時はサブタスクも個人的な開発もしていなかったので全身全霊かけてた記憶がある

がしかし、最終的に自らの意思を上長に伝え、受け入れてもらいこのチームから離脱することになった。

この時の反省点

温度差を許容できなくなってしまった

自分だけ上限なく熱量あげてコミットしても周りとの温度差がどうしても出来てしまい、進捗具合や熱量の差にガッカリする事が多々あり、ツラくなった。

自分は創業時のように許す時間の多くを使って開発していた。他の人は当然契約に則りやっていた。当然色々なところでギャップが生まれる(契約に則り働くことは当然正しい事)

一番、心に残ってるのは少しでも良いシステムにしようと思い、アーキテクチャに関してメンバー、PMの合意を得ようと色々と提案や仮実装、書籍の紹介等をしていた。が結局のところ大して目も通してくれず、まともな議論もなく、却下された事。切なかった。辛かった。(キャッチアップの時間はちゃんと取ったんだが...)

その後2週間は何も仕事が手につかなかった記憶がある

時間はなんとか作り出して、少しでも理想高く、少しでもモダンな開発をしていきたい自分と、良くしていきたい気持ちは当然あるが、限られた時間の中で現実的な落とし所を見つけたいメンバーとうまく合わなくなってしまったという事だと思う。

どちらも間違っていなくてミスマッチングだったのかもしれない。誰も責め立てる気は全く無いです。

新しい取り組み

そんな出来事があり、この頃から業務とは別に自らの技術力を向上させたいと思い、1日の業務の20%を仕事と関係のない開発をすることを許してもらった。いわゆる20%ルール

今までは自分の時間でなんとか時間作ってやっていたが、業務の一部の時間を使ってokとして頂いたのでありがたかった。

自分の場合は時間を器用に使い分けが下手なので1日の20%分を1週間(5営業日なので x 5で)貯めて1週間のうちの1日を自己研磨の時間として活用した。

4月~8月

  • 検索システムのリプレイス案件を一人で担当した
  • 単純な検索システムを作るのではなく、可能な限りmicroserviceの流れに乗った独立したシステムと機械学習の要素をうまく活用したものが作れないか試行錯誤してた
  • Goを取り入れたりもした
    • 初めてGoカンファレンスに参加したのもこれがきっかけだった

社内勉強会で最近やってる機械学習についてちょっとLTした - nakamura244 blog

TFIDFを検索に活かせるかを考えてみた - nakamura244 blog

ML前のデータ前処理系の学習メモ - nakamura244 blog

Goのdatabase周りのテストではinterfaceを最大限に活用しようという話 - nakamura244 blog

Go Conference Fukuoka 2019から刺激を受けてanalysis toolを作った - nakamura244 blog

8月ごろには開発は終えて社内調整が色々と時間がかかり10月にやっとリリースできた

tsuyoshi-nakamura.hatenablog.com

引き続き改善をしています

キーワード検索システムにnDCGを導入~現状分析の話 - nakamura244 blog

9月 ~ 12月

レコメンド開発を行っている。サンプルは何個かできているが、結局はMLOpsの部分をどう組み立て回すかに一番時間をかけている感じ。

SageMakerやGCPのプロダクトのプラットフォームに乗る前提で考えるとその部分はあまり課題はなくて、どうOpsを組み立てるかが、ポイントになっている

第一弾は年明けになると思うが、リリースできるかと思います

業務外の成果

1日の業務の20%を頂いて学習したもののアウトプットは下記

アルゴリズムの学習

Hacker Rankを教材にして学習したアウトプット - nakamura244 blog

一通りのアルゴリズムの課題をGoで解いたり、Pythonで解いたりを続けてGoldメダルを取れた(メダルはどうでもいいんだが、ある程度継続して学習できたという証なのでよかった)

当然全然わからない問題とかもあってその時はgeeksforgeeksさんに大変お世話になりました GeeksforGeeks | A computer science portal for geeks

コーディング試験とかでよく出る問題とかも解いてみたりしてた

コンピューターサイエンスを少しかじった

CourseraでMathematical Thinking in Computer Scienceというビギナーコースが終了したので残しておく - nakamura244 blog

内容的には基礎の基礎な感じだったのでそこまで時間はかかっていない。むしろ英語スピーキング(ロシア訛り)で字幕も英語しかなかったので英語読解に苦労した

MLの授業を受けてる

Machine Learning | Coursera

この授業を今受けてて、来年1月のどこかでは完了予定!

Coqのような証明支援開発をかじった

正しさとは何かと色々と調べる中でCoqに出会い、学習した

Coq - Wikipedia

何となくわかった気がして、大学の教授にアポを取ってこの領域の話を聞きに行ったが、そこで自分の無知さを思い知らされた。何もわかってはいなかった。

その教授が行っている授業のスライドを手に入れて、理解したつもりでそれを元に話をしたのだが、質問に何も答えられず、久しぶりにとても衝撃を受けた。

アカデミックな研究室でやっているプログラミングの違いを知った。

この辺から数学をちゃんと学ばなければいけないと感じたキッカケかもしれない

数学やり直してる

機械学習にしろ、大学でやっているようなコンピューターサイエンス系の授業をオンラインで学ぶにつれて数学の知識の必要性をここでも感じたのでやり直している。

数I、II、III。

やり直しているというよりは全く記憶にないので普通に学習している。

特に微分積分、行列の計算のところとか結構でてくる

今のところ、Youtubeや書籍でなんとかなっているが、厳しくなってきたら学習塾通おうか迷ってるぐらい。受験生に紛れ込んで...

番外編

12月にIPOを経験した。特に自分が何かをしたわけでは無いが、創業からエンジニアとして参画して6年目にして迎えることができました。創業から加わっててIPOまで経験できる事は人生においてもそうあるものでは無いので良い事だったと思います。

会社的にはここからまた再スタートですね!!頑張って行きます

www.makuake.co.jp

まとめ

この年も色々とありました。今年は勉強会や技術カンファレンスにはだいぶ絞って参加となった。CfPすら出していない。それよりも今年はinputの時間を大切にしたかったのが主な理由です。

自分のこれからのエンジニアキャリアを考えた時に

  1. 自分に新たな付加価値を付けないと今後、ジリ貧になるという危機感
  2. グローバルで活躍できるエンジニアになっていきたい。それを新しい付加価値にしていきたい
  3. グローバルに活躍しているエンジニアと今の自分を比較して何か不足しているのか?
  4. 言語、FWやライブラリ、クラウドに関する知識や使いこなし等はまぁまぁ対抗できると思ってる
  5. しかし、まだここに無いものを生み出す能力(originalを生み出す能力)は圧倒的に劣る
  6. なぜそんな事ができてるのだろうか?
  7. 彼らはコンピュータサイエンス系の学位のベースがあるのが普通でエンジニアとしての土台(積み上げ)が違う
    • 日本は文系出身でもエンジニアになれる国だが、それは普通では無い事を再度理解
    • この国のおかげで文系の自分はエンジニアになれたので感謝はしている
  8. じゃまずはその土台にテコ入れが必要でしょう

という事で来年からはcourseraに加え、JAIST(北陸先端科学技術大学院大学)でまずは科目履修生としてスタートします

なぜJAISTを選んだかというと土日開講で品川で受けることができ、現職に影響なくチャレンジができるため。(お休みはなくなりますけどね)

2020年へ

年の初めにやっていこうと感じた事を確実に進められているなと感じれたので、これをスピードアップさせて行きたい

キーワード検索システムにnDCGを導入~現状分析の話

はじめに

キーワード検索をリプレイス&独立した検索サービスを立ち上げた - nakamura244 blog

上記のエントリーで 今後の予定検索に評価指数の導入がありました。

これが完了したのでまとめてみたというのが話の主旨です

そもそもnDCGに関して

正しくはこちら

Discounted cumulative gain - Wikipedia

SEOが存在するように検索結果の順位によってクリックされる確率が大きく異なります。

簡単に言うと、その検索順位を考慮した評価指標がnDCGと言えるかと思います。

もうちょっと具体的に

下記の画面は時計というキーワードで検索した時の結果画面にクリックやCVの数をプロットしたものになります f:id:tsuyoshi_nakamura:20191129012236p:plain

  • 検索順位が4位のものは1位と比べてクリックは少ないものの、CVRの値は良いです。
  • 検索順位が1位になれば、クリックされる数は増えるのは普通の出来事だと思います。
  • もし、検索順位4位のものが、1位に表示されて入れば、クリックの値は必然的に増えて、CVRは一番良いので購入の数は一番増えていた可能性があります。

ユーザにとって4位のものが一番求めてたものになるので1位に表示してあげるべきだと考えられます。

こういった検索結果の順位のアドバンテージを考慮して定量的に計測できるのがnDCGの特徴かと思います

適合度に応じた価値を利得 (gain) として考え、ランクが下位になるほどその価値を下げる減損利得 (discounted gain)というような仕組みです

設計や構成

キーワード検索結果からのリンク設定

キーワード検索の結果画面からリンクをクリックした時、下記のようなURLになっています

https://www.makuake.com/project/perfect_beer04/?from=keywordsearch&keyword=%E3%83%93%E3%83%BC%E3%83%AB&disp_order=1

GETパラメータでfrom=keywordsearch&keyword=ビール&disp_order=1となっている。

これはキーワード検索ページからビールというワードで検索して1番目に表示された結果をクリックして遷移してきたという意味になります

アクセスログからどんなキーワードで検索した時に、何番目のリンクをクリックしたかを集計する為、このような設定にしています

集計システム

f:id:tsuyoshi_nakamura:20191129012946p:plain

  • 検索されたキーワードはAPI Gatewayのlog = CloudWatchに出力されて、lambda経由でElasticsearchの専用のindexに格納されます
    • 水色のラインの部分です
  • アクセスログGoogle Analyticsを利用します
    • Load BalancerのアクセスログをETL(AWS Glue)で取ってきて利用する方法もありますが、ここではより簡単な方をチョイス
  • Google AnalyticsからBigQueryへ定期的にデータをエクポートします
  • スキャンするバイト数を考慮して新しいテーブルに必要なデータを定期エクスポートします
  • CloudWatch eventから定期的にlambdaを起動し、BigQueryから検索システムを経由したアクセス数を抽出します(Getパラメータでアクセスログを絞り込む)
    • オレンジのラインの部分です
    • 適切な粒度のlambdaにしてstep functionsで連結します
      • jobを動かす度にBigQueryにアクセスが走り、都度課金される事を防ぐ為にjobを分けています
  • 購入(CV)トラッキングGoogle Analyticsで行っているのでBigQuery経由で取得します
  • オレンジのラインのjobで検索されたワードを取得して、PV、CVをBigQueryから取得してDCG計算してElasticsearchの専用のindexに格納します

全て、Elasticsearchのindexに保存している理由はKibanaのCanvasでまとめて可視化しているからです

nDCGの計算式に関して

式で表すとこんな感じ f:id:tsuyoshi_nakamura:20191129014346p:plain

  • p は検索順位の何番目までのDCGを対象とするかという意味
  • reliはGETした利得スコア
  • iは検索順位

これで導いた数値と本来の理想系のDCGで導いた値で割り算して x 100 で100%に近いほど精度が良いとする

式にするとこんな感じ f:id:tsuyoshi_nakamura:20191129021925p:plain

具体がないとわからないと思うのであげてみる

ビールというワードで検索した時の結果が下記だった場合

検索順位1位 A   click:240, cv:10
検索順位2位 B   click:244, cv:7
検索順位3位 C   click:249, cv:9
検索順位4位 D   click:100, cv:4
検索順位5位 E   click:100, cv:4

利得スコア = (click + cv ) * 100

実際に利得スコアしてみると

検索順位1位 Aの利得スコア : (240 + 10) * 100 = 25000
検索順位2位 Bの利得スコア : (244 + 7) * 100 = 25100
検索順位3位 Cの利得スコア : (249 + 9) * 100 = 25800
検索順位4位 Dの利得スコア : (100 + 4) * 100 = 10400
検索順位5位 Eの利得スコア : (100 + 4) * 100 = 10400

DCG5の計算式に当てて見ると

DCG5 =  25000 + (25100 / log_2(2)) + (25800 / log_2(3)) + (10400 / log_2(4)) + (10400 / log_2(5)) = 76057.0238461069

ここいうlog_2(x)は2を底とした対数の意

しかし、利得スコアから理想を導くと

本来は下記のように検索順位が望ましい

検索順位3位 Cの利得スコア : (249 + 9) * 100 = 25800
検索順位2位 Bの利得スコア : (244 + 7) * 100 = 25100
検索順位1位 Aの利得スコア : (240 + 10) * 100 = 25000
検索順位4位 Dの利得スコア : (100 + 4) * 100 = 10400
検索順位5位 Eの利得スコア : (100 + 4) * 100 = 10400
  • 実際には検索順位が3だったCが1位で結果表示されるべきだった
  • 実際には検索順位が1だったAが3位で結果表示されるべきだった

DCG5の計算式に当てて見ると

iDCG5 =  25800 + (25100 / log_2(2)) + (25000 / log_2(3)) + (10400 / log_2(4)) +  (10400 / log_2(4)) = 77073.24383928644

nDCGにしてみると

nDCG5 = 76057.0238461069 / 77073.24383928644 * 100 = 98% (小数点切り捨て)

理想の状態に98%近い状態であるという意味。

とってもいい結果ですね。

なぜnDCG10にしているか

正しい情報元がどこだったか、忘れてしまいましたが、検索を行うユーザのほとんどが検索結果ページの1ページ目しか見ないという事実があります。

1ページ目に表示する検索結果はだいたい10件程度になるという事でnDCG10にしています

計測対象

  • 全ての検索キーワードでnDCG10を計算するのはちょっと非効率なので、検索キーワードの多いTOP30件に対してnDCG10計算を行うようにしています
  • desktop,mobile,tabletというデバイスごとに集計して見ております
    • 検索アルゴリズムだけでユーザの求めるものに改善するというアプローチだけでは不十分です
    • アルゴリズムを変えずにUIだけを変えるだけで改善する事例は多々あります
    • バイス間で検索アルゴリズムを変える事は当分行わないので(今後もやらないとは言っていない)、デバイス間比較をする事はUI / UX 比較に間接的になる為です

実際の可視化

可視化はKibanaのcanvasを使ってます

全体サマリー

f:id:tsuyoshi_nakamura:20191201130911p:plain

  • まずは全体のサマリー
  • 一番上にあるのが全体のaverage
  • 下に各デバイスごとのaverage
  • アイコンを用いて可視化もついでにしてる
    • コーヒーアイコンは単に私がコーヒー好きであるというだけです
  • x 100 をしていないので0.xxxみたいな数値になっています
    • 細かい数字は出せないけど...

詳細サマリー

f:id:tsuyoshi_nakamura:20191201131126p:plain

  • もうちょっと細かくバージョン
  • 上のグラフは日毎のnDCGをピポットしてる
    • だいたいmobileデバイスのがnDCGの値が良いのでちょっと大きめの○になってたりする
  • 下のグラフはnDCGのワースト
  • ここで言うとペットというワードでdesktopで検索した時の結果が一番よくない
    • このデータからペットというワードで検索した時にどのような検索結果になっているのか
    • UX的にはどうなのか等々を掘り下げて調査をし、改善をはかります
    • そーすると、もともと検索回数の多いワードでnDCGを計測しているので、他に比べて大きいボトルネックの改善に繋がります。なので改善したときの効果も相対的に高くなります
    • あとはこのサイクルを繰り返すだけ

リプレイス前後比較

検索システムのリプレイスの前後1ヶ月で比較しました。

詳しい数値は書けませんが、結論から言うとnDCG10の指標からすると悪化してしまいました...😰😱

どういう事か詳しくみてみると...

リリース前の検索はmysqlのLIKE検索。リリース後はElasticsearch。Elasticsearchでの検索はngram検索ではなく、形態素解析したフレーズで検索するようにしています。

なので当然、検索ロジックは異なります。

その中でもリリース後は同じキワードでも検索ヒット数が多くなるようにパラメータをチューニングしました。

そのことにより、1ページ目の検索結果にノイズが混じり過ぎた結果だと思います

今後の改善ポイントです。

しかしもっとよくみてみると..

検索システムからのクリックに関しては倍以上に増えました。

これは、Elasticsearchに切り替えてから検索スピードが格段に良くなり、その結果たくさん検索を使ってもらった様子。

検索結果の2ページ目も良く使ってもらったようで2ページ目からのクリック(送客)がたくさんあったようです。

アクセスログを見ると検索結果の2ページ目からの送客の数値がリリース前に比べて桁が一つ違うほど増加していました。

トータルで考えると

  • nDCGの値は悪化してしまい残念であった
  • ただし、サジェストも含めると検索システムからの送客は2倍ほど増加した
    • 今後nDCGを改善を測るとさらに送客の価値が上がると思われる!!

あえてやっていない事

適合率、再現率、F値という部分はあまり気にしていません。これらのKPIを高める事が、より良い方向に行くとはあまり思えていない為です。

(今の所ね。今後も気にしないとは言っていない)

今後

  • とりあえずnDCGの値をもうちょっと良い数値に改善をしたい
  • 検索アルゴリズムだけでなくてUI / UXだけで改善できる部分もあるので進めたい
    • もちろん、合わせ技で改善していくべきところもあるので見極めて進めたい
    • 同じ検索アルゴリズムでデバイス間でnDCGが異なるのはUI / UXの影響であると言えそう
  • 曜日や時間帯によっての検索キーワードの分析、傾向を把握して、傾向があればその時間にあったアルゴリズムで検索できるようにして行くと良いかなと思ったりしたす

最後

定量評価できることの価値を改めて感じてる。検索と言っても色々な使われ方も存在するし、それぞれの視点での良し悪しがあります。

定量評価指標がない中で改善施策を考えるのはかなり偏った方向に進む可能性が高いです。

一つの物差しを用いて改善の議論をできる事は良いですね!!

nDCGはレコメンド等の評価指標にも使えるので今後も活かしていきたいと思います

Hacker Rankを教材にして学習したアウトプット

はじめに

自分は理系出身ではなく、エンジニアになりました。そして早10年ぐらいは経ちましたかね。。。つまり、仕事を通して必要になった知識等を都度学習してきました。

0 -> 1 系の事業にエンジニアとして参加することが多かった為(言い訳だな...)、エンジニアリング自体に集中する、徹底的に向き合うことが少なかったと感じています。

なので、自分の基礎部分を少しでも見直して再構築し、今後のエンジニア人生に活かしていきたいと思ったのが元々のきっかけです。

何を題材に学習したか

なんとなく、データ構造とかアルゴリズムの学習がしたいなぁーと思ったので探してみた結果Hacker Rankはちょっと良さげな感じがしたのでそのサービスを利用しました

HackerRank

このサービスの中で競技プログラミングもあるのですが、まずは一通り学習したいと思ったので、Practiceメニューの中でData Structures,Algorithmsの所を題材にしました

なぜこのサービス(Hacker Rank)を選んだのか?

お題に対して、自分でcodingして、submitして、良かったか悪かったかのレスポンスが瞬時にある点が良いなと思いました。

例えば、sortであれば、sortに関する説明はネットや本でたくさんあります。それを読み書きすれば一定の理解ができると思います

だけど、頭だけの理解だと気づかないうちに自分の都合の良い理解にしてしまったり、本当に身についたかは微妙になる事が多いと思います。(今までの自分の経験上)

実際にcodingを通して理解が深められる事はいいなと思って選びました

学習方法とか

与えられた問題に対して、任意のプログラミング言語を選択してcodeで表現し、submitするとhackerrank側で様々なテストケース(大量データのinputからinputデータパターンまで)でテストが行われ、性能を満たせれば合格といった流れになります。

これをひたすらやり続けた感じです。

でも途中で全くわからない問題もあるし、英語の読解力不足も重なって苦しい時間もたくさんあった。

まぁそんな時は geeksforgeeks というサイトを覗きに行けば、丁寧に解説をしてくれる

なんならYoutubeで動画で解説してくれる。(ただし全て英語だけど)

GeeksforGeeks | A computer science portal for geeks

自分の場合は一回きりで全て理解などできないので、繰り返しcodeを書いてはsubmitしたり、geeksforgeeksの該当情報をなんども読み返したりと地道な方法で進めていった

Goで書いてみたり、Pythonで書いてみたりもして、深い理解に繋がるように努力しました。

その結果

全ての問題を解いた訳ではないですが、全てのカテゴリの問題は一つ以上は解くことができたかと思います

問題を解いていくと都度ポイントをGetできます。そのGetしたポイントによってスコアリングされます

Scoring| HackerRank

自分は割と長いこと、根気強く続けたので5 Starのゴールドメダルまでいきました。さらに上をみると6 Star のゴールドメダルになります。

f:id:tsuyoshi_nakamura:20191109182811p:plain tsuyoshi nakamura - tsuyoshin | HackerRank

まぁ自分の場合は別にメダルの色やStarの数を競っている訳ではないので継続して学習が進められた事に満足をしています。

最後

何かを学ぼうとした時に座学だけになってしまうと本当に理解ができたのか、身についたものになったのかと心配になります。自分の場合は座学だけでは絶対身につきません。

なので、少なからず何かテストがあるものだったり、実際にcodeを書いてレビューしてもらえたりと手を動かす系のものがセットになっている題材かどうかを大切にしています。

今はまた違う課題を設定してチャレンジをしています。また一区切りついたらまとめようと思います

類似レコメンドシステムとしてのElasticsearchの活用検討

はじめに

キーワード検索システムに続いて、レコメンドシステムも担当になりました

キーワード検索というのはキーワードというヒントをくれたレコメンドシステムみたいなものといえばそんな感じなので両方を担当しています。

キーワード検索システムの方はこちらの記事を参考にしてください

キーワード検索をリプレイス&独立した検索サービスを立ち上げた - nakamura244 blog

という流れでキーワード検索システムに加えてレコメンドシステムの立ち上げを行っています。(まだひとりチームです)

立ち上げにあたりどんなレコメンドシステムを検討中か

大きく分けて、1:コンテンツベースの類似度レコメンド と 2:支援データを元にした協調フィルタリングをもちいたレコメンド の開発を進めています

1は この商品と似ている商品はこちらです みたいなレコメンドです

2は この商品を購入しているユーザはB商品も購入していますみたいなレコメンドです

で、今回は1のレコメンドの話です

コンテンツベースのレコメンドはググると色々出てくると思います。昔からあるものなので。

で先日、検索システムがリリースされました

キーワード検索をリプレイス&独立した検索サービスを立ち上げた - nakamura244 blog

実はElasticsearchの中でも類似度検索というものがあります。 ... More like this query

More like this query | Elasticsearch Reference [7.4] | Elastic

More like this queryの中身はluceneのTFIDFSimilarityというものでした。TFIDFがベースなんでしょうね

TFIDFSimilarity (Lucene 4.9.0 API)

More like this queryを使ってのコンテンツベースの類似レコメンド機能の実装案を残しておこうかと思います

実現したい具体的なを仮決め

Aというプロジェクトを見ている時にAに似たプロジェクトを表示させたい。

下記はイメージです

f:id:tsuyoshi_nakamura:20191021101506p:plain

デザインやUI / UXは別のチームが担当していて自分に決定権はありません。だけど、具体的な機能をイメージしないととても作りづらい...

仮でも良いのでmockまでできると、色々とアイディアを出してくれる人が増えて、一気にproductionレベルのものになっていく事はよくある事です。

なので、XXという機能を開発すると仮定義して開発を進めています。もちろん仮なのであとで180度変更されても良い心持ちでいます。

どうやって実現していくか

基本はElasticsearchの機能に乗っかるので下記のエントリーで構築したシステムのAPI-Gatewayにエンドポイントを新設してMore like this query 検索を実行する流れになります

キーワード検索をリプレイス&独立した検索サービスを立ち上げた - nakamura244 blog

そして次に類似させたい元のAというPJの特徴語を抽出します。特徴語抽出は基本的にTFIDFを活用する事になると思います

tf-idf - Wikipedia

1. 類似させたい元になるAというPJの特徴語を抽出する

方法は何通りかあるだろうけどここでは2つあげておく

方法A:事前に特徴語を抽出しておく

f:id:tsuyoshi_nakamura:20191015202726p:plain

  1. 自前で形態素解析機を揃えて文章を解析します
  2. 名詞・形容詞以外の文字は捨てます
    • サービスによってはどの品詞を使うかは異なると思います
  3. scikit-learnを使ってtf-idf計算をサクッとします
  4. 最後に集計して特徴語を抽出します

方法B:Significant Terms Aggregationの活用

Significant Terms Aggregation | Elasticsearch Reference [7.4] | Elastic

このクエリーを投げるだけでも特徴語が取れるようです

2. 前の工程で取得できた特徴語をストレージに格納

まぁRDBで良いんじゃないでしょうか

3. 類似レコメンドを取得したい時にElasticsearchのMore like this query検索を実行する

類似させたい元のPJの特徴語を取得して、ElasticsearchのMore like this query検索を実行すれば、見事簡単に類似レコメンド機能が完成する

ここではAというプロジェクトの特徴語を類似検索に投げていますが、別に特徴語を使わなくても良いと思います。

特徴語を使わなくても良いかも?!

単純に類似させたい元のタイトルをそのまま類似検索に投げても思った結果が得られる場合もあります。

それぞれのタイトル名は練りに練った言葉を選択している傾向があるのでこのまま活用するのも良いと思います。

あとは、More like this queryのパラメータ設定でも当然結果が異なるので色々と設定値を探索する必要があります。

More like this queryの検索フィールド(=fields)を本文にするのか、別に作成した文章にするのか等々でも色々と変わってくると思います。

それぞれの特徴を捉えてサービスに合わせたベストな組み合わせを選ぶことになりそうです

難しいのは評価

いわゆる教師なし系のレコメンドは事前に検証が出来ないので、社内でDog Foodしたり、本番にカナリアリリースして様子をみるしかありません。

カナリアリリースの場合は一定期間もしくは、N%のユーザだけに機能を提供して、CTR、CVRで比較して評価してあげると言う感じになると思います。

今回はまだ類似レコメンドシステムが存在しないので社内で下記のようなDog Food環境を作りました

f:id:tsuyoshi_nakamura:20191015210844p:plain

  1. 公開していないclosedなchromeエクステンションを開発し、使ってもらえるユーザに手動でinstall
  2. chromeエクステンションが動いて、More like this queryを実行する一般公開前のエンドポイントへアクセス
  3. 類似データを取得したらここは無理くりhtmlをinner writeする

そうすると特定の人だけに下記のような画面表示になる

f:id:tsuyoshi_nakamura:20191015211653p:plain f:id:tsuyoshi_nakamura:20191015212536p:plain

このchromeエクステンションを使って一般公開前のエンドポイントにアクセスしてコンテンツを形成して追加してしまうという方法の利点は何と言っても本番データでそのままdog foodできる点です。

なのでエンジニアに限らず、いろんな職種の人でテストができる点がGoodだと思っています

最後に

コンテンツベースの類似レコメンドはこの他にItem2vecを元にしたもの、K-meansの教師なしクラスタを活用したものの開発を予定しています

これらの情報共有はまた別の機会にしようと思います

[1603.04259] Item2Vec: Neural Item Embedding for Collaborative Filtering Unsupervised learning: seeking representations of the data — scikit-learn 0.21.3 documentation

まぁともあれキーワード検索でElasticsearchを活用している事で既存資産を活かして最小コストで類似度レコメンドが実装できる点、社内で試せるDog Food方法を示しました

リソース上、お一人で開発を頑張っている方の少しでも足しになる情報になれば幸いです

補足

今後はItem2vecとK-meansの教師なしクラスタでの類似レコメンドを開発し、良さそうな方を採用してリリースまで実装しようと思います