pandazx's blog

Hadoop, データ分析など雑多な技術ブログ

Team AI Meetup #1に行ってきた

スライド写真は後でUP

mercari.connpass.com

アジェンダ

  1. 「What can image recognition & machine learning do for Mercari?」 by 山口 拓真
  2. 「メルカリにおける機械学習システム基盤について」 by @Hmj_kd
  3. Q&A

What can image recognition & machine learning do for Mercari?

  • DNNのInception-v3でerror rate 29.3%。AWS上で評価
  • 誤認識した例:デザインがほぼ同じだが、靴のサイズが違うだけでメンズとレディースで違う。ヒトでも困難
  • うまくいった例としては、詳細カテゴリは間違うが、キッズ用品かどうかは当たることが多い。
  • ブランド認識と認識で注目した領域の可視化
  • アイテム詳細情報の推定
    • 5000万枚学習
    • 推定した結果をユーザが商品登録時の初期カテゴリとして使用(ユーザの操作負荷軽減)
    • 推定した結果をユーザが検索する際の色指定にも対応できる。青いスカート、赤いスカートなど
    • 色推定する際に重要な領域は識別でアテンションの高い領域を利用
  • Image Recognition System Architecture
    • GAEを基盤にkubernetes, docker, spinnakerを利用
    • Mercari APIから上記GAE上のImage Recognition APIを実行
    • Image Recognition API内ではキューを挟んでワーカーが動作
    • 推定はCPUで運用。GPUは使っていない。350msec/req程度で処理できれば現状は十分
  • 画像検索
  • ネットワーク
    • ブランド判別や商品アイテムの詳細推定は1つのネットワークで実現している
    • 計算コストの低減はPCAで次元圧縮

メルカリにおける機械学習システム基盤について

  • 機械学習システム基盤のコンセプト
    • メインアーキテクチャはkubernetes
    • 特定ベンダー非依存
    • ローカルと本番で同一実行環境
  • Architecture Overview
    • 写真参照
  • Workflow
    • 写真参照
  • 2018年以降の予定
    • 2-4モデルが稼働中
    • 精度を監視して更新する機構
    • OSSに向けて(予定)
  • プロジェクト体制は3-4名

Q&A

  • 画像検索による商品検索の精度の現状と短・中期的な達成度合いの見通し
    • 画像検索は直近1,2ヶ月であれば対応できるが、全画像は1億枚以上あり、対応がインフラ的にもアルゴリズム的にも困難
  • 論文の手法そのままではなく、メルカリ独自の工夫はある?
    • そこまで最新アルゴリズムは使っていない。Inception-v3はパラメータ数が少なかったり、クセがわかっているので使っている
  • アカデミアとの関わりは?
  • 機械学習プロジェクトをどう進めている?
    • ビジネスサイドとの軋轢。コミュニケーション。デモをすぐに作ってイメージ共有を行う
    • コミュニケーションのための事例集を作っておく
  • 画像検索の新カテゴリ対応の課題はある?
    • 特にしていない。ユーザから得られたデータ次第

VBAで多次元配列を多次元辞書(連想配列)に変換

入力データが多次元配列でコメントと日付が入ったデータとする。

これを変換して、辞書のデータ構造が年→月→日→辞書(リスト風)→辞書というデータに変換する。

辞書(リスト風)はキーを0,1,2,3というようにして辞書を登録することを意味する。

VBAの設定として、辞書(Scripting.Dictionary)を使用可能にするため、 Visual Basic Editor画面からツール→参照設定でMicrosoft Scripting Runtimeにチェックをつける。

VBAのコードは以下のようになる。動作確認していないが、概ね以下のイメージ。

Function convertList2Dict(dataList) As Scripting.Dictionary
    Dim yearMonthDayDataDict As New Scripting.Dictionary
    Dim dataDict As New Scripting.Dictionary
    
    Dim idx As Variant
    For idx = LBound(dataList) To UBound(dataList)
        ' 日付を取得し、年月日を抽出
        Dim dateStr As String: dateStr = dataList(idx, 1)
        On Error GoTo Errorhandler
        Dim dateObj As Date: dateObj = dateStr
        Dim yearNum As Integer: yearNumAs = year(dateObj)
        Dim monthNum As Integer: monthNum = month(dateObj)
        Dim dayNum As Integer: dayNum = day(dateObj)
        
        ' 辞書の生成と値の設定
        Set dataDict = New Scripting.Dictionary
        dataDict .Add "comment", dataList(idx, 0)
        dataDict .Add "date", dataList(idx, 1)
        
        ' 該当年の辞書を取得。未登録なら作成
        If Not yearMonthDayDataDict.exists(yearNum) Then
            yearMonthDayDataDict.Add intersectionName, New Scripting.Dictionary
        End If
        ' 該当年、月の辞書を取得。未登録なら作成
        If Not yearMonthDayDataDict(yearNum).exists(monthNum) Then
            yearMonthDayDataDict(yearNum).Add monthNum, New Scripting.Dictionary
        End If
        ' 該当年、月、日の辞書を取得。未登録なら作成
        If Not yearMonthDayDataDict(yearNum)(monthNum).exists(dayNum) Then
            yearMonthDayDataDict(yearNum)(monthNum).Add dayNum, New Scripting.Dictionary
        End If
        ' 辞書を多次元辞書に登録
        Dim listIdx As Integer: listIdx = yearMonthDayDataDict(yearNum)(monthNum)(dayNum).Count
        yearMonthDayDataDict(yearNum)(monthNum)(dayNum).Add listIdx, dataDict
NextData:
    Next idx
    On Error GoTo 0
    Set convertList2Dict = yearMonthDayDataDict
    Exit Function
Errorhandler:
    ' エラーが発生すると、ここに飛ぶ
    ' 不正な日時はスキップ
    Resume NextData
End Function

DynamoDBストリームをLambdaで読み込むと24時間前から開始される

DynamoDBストリームを読み込んでLambdaで処理する実装を行った際に勘違いしたことがあるので、メモ。

DynamoDBにはストリームという更新情報をストリームで流す機能があり、 更新発生をトリガにLambdaで処理することが可能。

ストリーム機能を有効にした際に、有効にした時点からの更新のストリームが流れるのではないことに注意。 ストリームデータは24時間保持されるが、それは有効にする前から保持されているため、 ストリームを読み込んでLambdaが動く場合、Lambdaに入力として渡されるデータは24時間前から始まる。

24時間前のストリームから、追っかけ再生的にLambdaの処理が進んでいくため、 最初は書き込みキャパシティの値を大きくしないと、処理が追いつかないので注意すること。

参考: DynamoDB ストリーム を使用したテーブルアクティビティのキャプチャ - Amazon DynamoDB

csvをparquetに変換

Drillで変換する方法

CASE WHENの書き方

python2で実行スクリプト名の判定

以下のようにしておけば、sample.py が他のスクリプトから呼ばれた時に main()を実行することを避けられる。

# sample.py
import sys

def calc(val):
    x = val + 1

def main():
    calc(1)

if sys.argsv[0] == __file__:
    main()

これにより、前に作ったスクリプトのメソッドを流用したい時に、簡単にimportできるようになる。

VirtualboxでCentOS7を使う時にインターネットにつながらない

/etc/sysconfig/network-scripts/ifcfg-enp0s3 を開いて、ONBOOTをyesにする。

再起動でつながるようになる。

VirtualboxでRHELを使う時に共有フォルダが使えない

CUI環境を想定。

GuestAdditionsをインストールすればいいのだが、エラーが発生する場合がある。

GuestAdditionsのCDイメージを挿入した後

# Guest Additions CDをマウント
mkdir /mnt/cdrom
mount -o ro /dev/cdrom /mnt/cdrom

# 必要なソフトウェアをインストール
yum install gcc bzip2
yum install kernel-devel-XXX(バージョンを記載)

# Guest Additionsを実行
cd /mnt/cdrom
./VBoxLinuxAdditions.run

必要なソフトウェアが足りない場合は、Guest Additionsを実行した際にエラーメッセージが表示され、 そこに不足するソフトウェア名が書いてあるので、それをインストールすればよい。 上記のバージョンもそこで確認すればよい。