BASEプロダクトチームブログ

ネットショップ作成サービス「BASE ( https://thebase.in )」、ショッピングアプリ「BASE ( https://thebase.in/sp )」のプロダクトチームによるブログです。

テキストによる商品のカテゴリ分類でCutMixを試してみた

f:id:sugiiiii:20191216172502p:plain

この記事はBASE Advent Calendar 2019 17日目の記事です。

devblog.thebase.in

こんにちは、DataStrategyの杉です。

DataStrategyではデータを用いて問題解決を行なっていたり、より使いやすいサービスのための改善をしています。10日目の記事として類似商品APIについてがありましたが、このようにテキストや画像の特徴量からレコメンドの作成なども行なっています。今回は私がテキストの特徴量を用いて試してみたことについて書きたいと思います。

概要

Eコマースプラットフォーム「BASE」には様々なカテゴリが存在します。

例えばアパレルのショップであれば「トップス」「ボトムス」などショップごとに設定されているカテゴリもあれば、「アパレル」などといったショップ自身を表すカテゴリなど、多いものでは約1000種類の分類がされているカテゴリもあります。

これらのカテゴリを自動で分類できるようになることで、レコメンドの精度向上や入力項目の削減などができるようになります。

しかし、このカテゴリをテキスト特徴量を用いて分類しようと思うと以下のような問題が出てきました。

  • カテゴリによって偏りがでてきてしまう
  • 精度が上がりにくい

カテゴリによって偏りがでてきてしまうことはどのようなタスクでも存在する問題ではないかと思います。しかし、少ないカテゴリに数を合わせてしまうと全体の量が減ってしまい、より精度が悪くなってしまうということも考えられます。
この問題に対して、テキストのDataAugumentationを用いて解決できないかということを試してみました。

具体的には、CutMixと呼ばれる、主に画像のDataAugumentationで使用されている手法を試してみたので、その内容について書きたいと思います。
また、詳しくは下で書かせてもらいますが、このCutMixをテキストに使用するということはあまり推奨されていない手法な可能性もあります。そのため、こんなこと試してみたんだという気持ちで読んでいただけると嬉しいです。

テキストのDataAugumentationについて

画像のDataAugumentationといえば画像を回転させたりノイズをのせたりなど様々なことが考えられます。
しかし、テキストでは順序なども影響するため回転などは推奨されていません。

例えば

今日 は 良い 天気 です ね 。

という文章を回転させてしまうと

。 ね です 天気 良い は 今日

となってしまい、日本語として伝わらない文章になってしまいます。

そのため、テキストのDataAugumentationとしては - 類似の単語で置き換える - ルールベースで単語を置き換える

などの手法が使われることが多くなっています。
例えば

朝ごはん に パン を 食べ まし た 。

という文章は

朝ごはん に サンドイッチ を 食べ まし た 。

に置き換えても違和感がなく伝わる文章になります。
このようにしてテキストのDataAugumentationが行われています。

CutMixとは

今回試してみたCutMixはこれらのDataAugumentationの手法のひとつです。
論文: https://arxiv.org/pdf/1905.04899.pdf

MixupやCutoutを組み合わせたような手法です。
論文の図がとてもわかりやすいと思います。

f:id:sugiiiii:20191216172542p:plain:w450

画像でこれらのことを行うとふたつの画像を半分ずつ合成するMixupとある区間をカットしてしまうCutoutを組み合わせてある部分を違う画像で置き換えるという手法がCutMixです。
Mixupでは合成をすることで不自然になってしまうことや、Cutoutではカットした部分に重要な情報がはいっていたなどということがあるため、CutMixはそれらの問題を解決でき、精度も向上する結果を出しています。

これらは画像での紹介になっていますが、Mixupはすでにテキストでの実装例もあり
論文: https://arxiv.org/pdf/1905.08941.pdf
こちらではMixupを使うことで精度向上ができたとの記載があります。

では、CutMixをテキストで表現するとどうなるでしょうか?
例えば以下のふたつの文章があったとします。

文章1: 明日 は 遊園地 に 遊び に 行こ う と 思い ます 。
文章2: 動物 の 中 で は 犬 が 1番 好き です 。

これをCutMixすると
動物 の 遊園地 に 遊び に が 1番 好き です 。
となります。

これに対して混ぜた割合を出力とすることで学習することが可能となります。
文章としてよくわからない内容になってしまっているため、上で書いたような回転と同様の現象が起きてしまっている可能性があり、推奨されていない可能性があると書きました。

内容

今回は約1,000カテゴリを分類してみました。
データはBASEの商品データのテキストを使用しました。また、これらのデータに前処理を行いMeCabで形態素解析されたものを使用しました。
入力を400ワードで固定し、足りない部分は0埋めしてあります。

CutMixの実装は

  • どの範囲を切るのか
  • どのくらいの単語を切るのか

について考える必要がありますが、今回は0埋めしている部分などもあるため

  • 0埋めされていない部分で入れ替えを行う
  • 0-20 wordsでの中でランダムに入れ替えを行う
  • 出力の割合は0埋めを除いた部分で行う

としました。以下はkerasのgeneratorを使った場合の実装例です。embeddingを行いCNNで学習をしました。出力は1-hot-vectorです。

▼CutMix実装例

CATEGORY_NUM = 1000

def generate_input_cutmix(x_data, y_data, batch_size=32):
    max_len = x_data.shape[0]
    seq_len = x_data.shape[1]
    while True:
        x = np.zeros((batch_size,seq_len))
        y = np.zeros((batch_size, CATEGORY_NUM))
        cnt = 0
        while cnt < batch_size:
            try:
                r = random.randint(0, max_len-1)
                r_mix = random.randint(0, max_len-1)
                if y_data[r]!=y_data[r_mix]:
                    target_idx = np.where((x_data[r,:]>0)&(x_data[r_mix,:]>0))[0]
                    r_num = random.randint(0, 20)
                    r_idx = random.randint(0, len(target_idx)-r_num)
                    x[cnt,:] = x_data[r,:]
                    x[cnt,r_idx:r_idx+r_num] = x_data[r_mix,r_idx:r_idx+r_num]
                    rate = r_num/len(np.where(x_data[r,:]>0)[0])
                    one_hot_r = np_utils.to_categorical(y_data[r], CATEGORY_NUM)
                    one_hot_rmix = np_utils.to_categorical(y_data[r_mix], CATEGORY_NUM)
                    y[cnt,:] = (1-rate)*one_hot_r + rate*one_hot_rmix
                    cnt+=1
            except:
                # 単語数が足りていないこともあるため
                pass
        yield x, y

もしword数を変えたい場合には

r_num = random.randint(0, 20)

ここの数字をいじることで可能です。

また、ここを固定しない場合は

r_num = random.randint(0, target_idx)

でランダムに決めることができます

▼学習

model.fit_generator(generate_input_cutmix(x_train, y_train),
      verbose=1,
      steps_per_epoch=x_train.shape[0] // batch_size,
      validation_data = generate_input_cutmix(x_validation, y_validation),
      validation_steps = x_validation.shape[0] // batch_size, 
      epochs=30
      )

結果

(1) loss

なにもしていない場合とCutMixを使用した場合のlossは以下になりました。

f:id:sugiiiii:20191216172452p:plain:w400

lossを見るとCutMixよりも何もしないバージョンの方が良い落ち具合となっています。画像の場合のCutMixでは、CutMixを使うことでlossの落ち具合が早くなるなどあるため、想定と異なる結果となりました。

これだけをみていると何もしないバージョンの方がよく見えますが、もっと詳細な正答率について調べてみましょう。

※何もしないバージョンの方は11epochあたりからtestのlossが上昇してしまっているため
過学習をしている可能性も考え、10epochのmodelを使用していきます。

(2) カテゴリの正解率

まず、予測結果の中で最も高い値となったカテゴリが、正解としているカテゴリと一致しているかについてみてみました。

テストには1000データを使用しました。

import numpy as np

pred = model.predict(x_test)
pred_argmax = np.argmax(pred, axis=1)
print(np.sum(pred_argmax==y_test))

▼結果

何もしない: 21.8%
CutMix: 25.0%

カテゴリをどれだけ当てられたかで考えると、CutMixの方が良い結果となりました。
(全体的に精度は低いのでですが1,000クラス分類なのでおおめに見てください...)

また、何番目に正解データがでたかを累計してみた結果です。

f:id:sugiiiii:20191216172438p:plain:w400

この結果からも、CutMixを使用した方がうまく予測ができている結果となりました。
今回何もしていない方は過学習をしている可能性を考えて10epochを使用していますが、loss的にはとても落ちている20epochを使用しても大きく変わりはしませんでした。

(3) 新しい文章に適用してみる

私が架空の商品説明文を作ってみました。これに適用してみるとどのような結果となるでしょうか?
カテゴリ名はそのまま使用できないため、ふわっとしたカテゴリ名に置き換えています。

①ぬいぐるみ系

ペンギンのぬいぐるみ!

布から作っているペンギンのぬいぐるみです。
ほどよい綿の詰め具合でなんとも言えないもふもふ感を味わえると思います。
ペンギンの種類はアデリーペンギンをイメージしており、癒しの動物を目指しています。
大きさは30cmほどとなっているため部屋にちょっと飾るにもちょうどいいです。

また、安全に配慮して作成しているため
小さいお子様の遊び相手にもぴったりだと思います。

大きさ
縦: 30cm程度
幅: 10cm程度

また、大きさは手ではかっているため多少ずれていることもあります。

▼結果 なにもしないバージョン: キャラクタ CutMix: 手作り作品

②食品系

りんごのたくさんはいったアップルパイ20cm

りんごの収穫も当園で行なっています。
今年のりんごもとても美味しい出来上がりになりました。
そのまま食べても美味しいりんごですが
今回はお店でも販売をしているアップルパイが期間限定で登場しました!

コーヒーにも紅茶にも合う仕上がりとなっています。

贈り物としても選ばれるおすすめの商品です。
ぜひこの機会にいかがでしょうか。

▼結果 なにもしないバージョン: コーヒー CutMix: 食べ物

今回2作品を創作してみましたがどちらもCutMixではうまく特徴を捉えることができているのではないかという結果となりました。

(4) 可視化

CutMixでは可視化も行うとおもしろい結果をみることができます。可視化では、そのmodelが これが答え! とだした際にどこを判断してそのような答えになったかを確認することができます。

例えば犬と猫をCutMixしたものに対して出力"犬"として入力の可視化をすると犬の部分のみが判断できているなどが可能です。
同様のことがテキストでもできないかと思い試してみました。上の2作品を合体します。形態素解析後なので文章として読みにくいのですが、以下の文章を使用しました。

青が①ぬいぐるみ系の文章で赤が②食品系の文章です。

りんご たくさん いっ アップルパイ cm りんご ペンギン ぬいぐるみ よい 綿 詰め 具合 なんとも 言え ふも なり そのまま 食べ 美味しい りんご 今回 店 販売 し いる アップルパイ 期間 限定 登場 し コーヒー 紅茶 合う 仕上がり なっ い 贈り物 選ば れる おすすめ 商品 ぜひ 機会 いかが

今回modelとしてCNNを使用していたため、grad-camを使用して可視化を行なってみました。可視化では、それぞれ
①手作り作品
②食べ物
と出力した際に注目されていたwordを上位5つピックアップしてみます。

▼①手作り作品
りんご たくさん いっ アップルパイ cm りんご ペンギン ぬいぐるみ よい 棉  詰め 具合 なんとも 言え ふも なり そのまま 食べ 美味しい りんご 今回 店 販売 し いる アップルパイ 期間 限定 登場 し コーヒー 紅茶 合う 仕上がり なっ い 贈り物 選ば れる おすすめ 商品 ぜひ 機会 いかが

▼②食べ物
りんご たくさん いっ アップルパイ cm りんご ペンギン ぬいぐるみ よい 綿 詰め 具合 なんとも 言え ふも なり そのまま 食べ 美味しい りんご 今回 店  販売 し いる アップルパイ 期間 限定  登場 し コーヒー 紅茶 合う 仕上がり なっ い 贈り物 選ば れる おすすめ 商品 ぜひ 機会 いかが

①手作り作品では綿を"詰め"るという部分に注目されていますが②食べ物といれると"りんご"に反応しています。

これらの結果からも、CutMixで学習ができているのではないかという結果となりました。

今回はデータも少なく、学習もepoch決め打ちでやっているので条件を変えていくことでCutMixの良さを引き出せる可能性もあるかもしれません。

まとめ

今回はテキストでのカテゴリ分類に対してCutMixを使用してみました。
様々な工夫をすることでテキストにCutMixを使用するということは効果がある可能性がわかりました。

明日はOwners Marketingの栗田さんとProduct Managementの藤井さんです!