機械学習の最近の記事

ご挨拶

AWS全冠エンジニアの小澤です。
今年の目標はテニスで初中級の草トーナメントに優勝することです。よろしくお願いいたします。

本記事の目的

本記事では、生成AIでVOC分析を行うことで得られた知見を共有したいと思います。

昨今、生成AIの登場など機械学習の進歩は目覚ましいものがあります。一方、足元では自社データの利活用が進まず、世の中のトレンドと乖離していくことに課題感を持たれている方も多いかと思います。また、ガートナーの調査(2024年1月)によると、日本企業でデータ活用の成果を得られている企業は3%にとどまっているようです。

特に顧客の声(Voice Of Customer)は、大量の非構造化データで、内容も多様かつ複雑なため特に分析が難しい領域です。また、効果的に分析できれば実りの大きい領域でもあります。

早速やってみた

VOC分析のデモ対象としてCSVファイルを用意しました。こちらは「都内に展開する高級ハンバーガーチェーンのカスタマーフォームのデータ」という設定で、生成AIで顧客の声を99件作成しています。

上記のCSVファイルを生成AIで前処理して、BIツールに取り込むことで下記デモのように手軽にVOC分析が始められます。


今回のやってみたで得られたポイントは以下の3点です。

  • テキストマイニングの専門的知見がなくても大量データを分析してインサイトを創出できる
  • GPT-4で一つの顧客の声から複数のカテゴリと感情分析を抽出できる (GPT-3.5だと物足りない)
  • どのようにカテゴリを組成するかが分析の肝であり、その目的に応じてカテゴリの再構築が必要


それでは、具体的な手順に入っていきます。

1.データの前処理

デモデータに含まれるお客様申し出内容を生成AIでカテゴライズ、感情分析、要約します。
今回はカテゴリ一覧も生成AIで用意させました。最終的に利用したカテゴライズ用プロンプトは記事の最後に参考情報として記載しています。

当初、前処理にはGPT-3.5を利用しましたが、カテゴライズの精度に少し物足りなさを感じたためGPT-4を利用するように変更しました。
GPT-4を利用して、一つの顧客の声から複数のカテゴリ、異なる感情分析を生成できたのは興味深い結果でした。人間だと一つカテゴライズしたら手を抜いてしまいがちとなるので、GPT-4と同程度の精度で大量のデータを以下のようにカテゴライズするのは難しいと思います。

INPUT

今日、プレミアムバーガー赤坂店でランチセットを利用しました。バーガーのサイズは満足できるものでしたが、サイドメニューのポテトが少なく感じました。
また、ドリンクの種類がもっと多ければ嬉しいです。価格に見合った量と質を期待していたので、少しガッカリしました。
しかし、店員さんの対応はとても良く、快適なランチタイムを過ごせました。今後、ランチセットの内容を見直し、コストパフォーマンスを高めることをお勧めします。

OUTPUT

[
  {
    "大カテゴリ": "店舗",
    "カテゴリ": "サービス",
    "サブカテゴリ": "スタッフの態度",
    "感情分析": "Positive",
    "要約": "店員の対応が良く、快適なランチタイムを提供"
  },
  {
    "大カテゴリ": "商品企画",
    "カテゴリ": "メニュー開発",
    "サブカテゴリ": "その他",
    "感情分析": "Negative",
    "要約": "サイドメニューの量とドリンクの種類に不満"
  },
  {
    "大カテゴリ": "商品企画",
    "カテゴリ": "フィードバック管理",
    "サブカテゴリ": "商品改善",
    "感情分析": "Neutral",
    "要約": "ランチセットの内容とコストパフォーマンスの改善を提案"
  }
]

それでは、これらの分析結果をBIツール(QuickSight)に取り込んで、どのようなインサイトが得られるか見ていきます。

2.全体把握

まずは円グラフとヒートマップで顧客の声をざっくり視覚化します。

スクリーンショット 2024-01-26 12.07.22.png

ヒートマップでは店舗のネガティブな声が目を引きますが、これは全体に占める「店舗」への声、ネガティブな声の割合を考慮すると自然な結果です。ここは更に細かく分析をしていく必要がありそうです。
一方で、「商品企画」への声はポジティブである比率が高く、商品力に優れたハンバーガーチェーン店であることが伺えます。

今回はエリアマネージャーになったつもりで店舗にフォーカスして分析を進めていきます。

3.店舗にフォーカスした分析

引き続き、店舗の声について全体把握するために円グラフとヒートマップでざっくり視覚化します。

スクリーンショット 2024-01-26 12.51.17.png

店舗へのネガティブな声の割合は、全体と比較すると少し高めであることが分かります。
ヒートマップを見ると、「待ち時間」や「スタッフの態度」に課題がありそうです。一方で、「雰囲気」はポジティブな声が多く、店舗の強みとなっていることが分かります

スクリーンショット 2024-01-26 13.03.08.png

店舗別のヒートマップを見ると、「プレミアムバーガー新宿」に多くのネガティブな声、「プレミアムバーガー赤坂」にポジティブな声が集まっていることが分かります。これらの情報を元に分析を深掘りしていきましょう

4.分析の深掘り

詳細分析はピボットテーブルを利用して行い、店舗横串で改善すべき項目を確認していきます。

スクリーンショット 2024-01-26 13.31.56.png

ここで、エリアマネージャーとしての私は店舗改善の指標として強みとなっている「雰囲気」に着目しました。
顧客からポジティブな評価を集めている赤坂店などはマネージャーとしての経験とも合致するところがあり、その要素を分析して他店舗に横展開する施策はイメージが湧きました。

一方で、クレーム件数の多い「待ち時間」はモバイルオーダーなどのシステム起因であったり、時間帯やプロモーションのピーク性など要因が絡まり合っており、クイックウィンが難しいことは自明だったので、今回はスコープから除外することにしました。

またVOC分析では「その他」を洗うことも重要です。ここには認知できていなかった課題が埋もれています。

スクリーンショット 2024-01-29 9.45.11.png

店舗改善で更にインサイトを得るためには、ユニフォームが「その他」に組み込まれないようカテゴリの再構築が必要でしょう。

やってみた振り返り

顧客の声という非構造化データをカテゴライズ・感情分析し、そこからインサイトを創出するデモをやってみました。

しかし、本当に価値があるのはインサイトから仮説を構築し、検証するための分析プロセスだと感じました。そのためには、カテゴリの再構築を繰り返すことで次々とインサイトを創出するインタラクティブな分析が必要です。
今回の例で言えば、店舗の雰囲気に「スタッフの態度」が大きく影響している可能性でないか?などの仮説が立ちますし、それに合わせてカテゴリの再構築が必要でしょう。

そして現場を分かっている人ほど、これらの顧客の声から精度の高い仮説を立てられると思います。また改善施策を実施後、適切に可視化されたダッシュボードでデータの時系列をトラックし、効果測定を行うことも重要です。

そのためにはデータ分析の専門性を持たなくても、担当者がインタラクティブにデータ分析と視覚化を行えるシステムが必要です。そのようなシステムは生成AIをデータ分析に組み込むことで、自然言語を介して実現出来ると思います。

AWSのマネージドサービス活用

AWSのマネージドサービスを組み合わせることで、VOC分析をセキュアにスモールスタートできます。

VOC分析構成図.drawio.png

Amazon Bedrockはエンタープライズ向けの生成AIでセキュアに利用できますし、QuickSight には自然言語でBIを構築する新機能も発表されています。今後もAWSで生成AIを活用するマネージドサービスは増えていくと思いますので、私としてもAWS全冠にあぐらをかかず最新技術をキャッチアップしていく所存です。

当社について

当社は顧客中心主義を掲げ、お客様にとって本当に価値があるソリューションの提供を目指しています。
本記事に関連するところで言えば、システム企画からピュアな機械学習によるデータ分析、クラウドコールセンターの構築や問合せ情報管理システムの開発までワンストップで提供できます。

私自身はSRE(サイト信頼性エンジニアリング)を主戦場に、お客様が抱えるITの課題抽出から企画、実行まで行っています。最近では「サイト」ではなく、「顧客」に信頼性の対象を置くCREという概念も出てきており、今後は顧客の声をKPIに設定する取り組みもチャレンジしていきたいと考えています。

もし当社に興味を持たれましたら、こちらのお問い合わせフォームよりご連絡いただければ幸いです。

参考(カテゴライズで利用したプロンプト)


下記の問い合わせ内容をカテゴライズ表に厳密に従って大カテゴリ、カテゴリ、サブカテゴリに分類してください。
また該当カテゴリのトピックサマリも30字以上50字未満で記載ください。

## 問い合わせ内容
{{お客様お申出内容}}

## 出力形式
JSONで該当するカテゴリを1〜3個出力してください
[
  {
    "大カテゴリ": "",
    "カテゴリ": "",
    "サブカテゴリ": "",
    "感情分析": "",  // Negative or Neutral or Positive
    "要約": ""
  }
]

## カテゴライズ表
大カテゴリ,カテゴリ,サブカテゴリ,サンプルシナリオ
店舗,サービス,待ち時間,注文から30分以上待たされた
店舗,サービス,スタッフの態度,スタッフが無愛想
店舗,サービス,アレルギー対応,アレルギー情報の不足
店舗,サービス,注文間違い,ヴィーガンバーガーの注文間違い
店舗,サービス,その他,該当なし
店舗,環境,雰囲気,店内のインテリアが洗練されている
店舗,環境,清潔さ,店内の清掃が行き届いていない
店舗,環境,騒音レベル,店内がうるさくて食事が楽しめない
店舗,環境,照明,店内の照明が暗すぎる
店舗,環境,その他,該当なし
店舗,設備,アクセシビリティ,車椅子でのアクセスが困難
店舗,設備,座席の快適さ,座席が狭くて快適でない
店舗,設備,Wi-Fiの利用,Wi-Fiが遅くて使い物にならない
店舗,衛生管理,手洗い設備,手洗い設備が不足している
店舗,衛生管理,清掃の頻度,トイレの清掃が不十分
店舗,衛生管理,その他,該当なし
店舗,顧客体験,訪問のしやすさ,店舗までのアクセスが困難
店舗,顧客体験,情報提供,メニュー情報が不明瞭
店舗,顧客体験,特別な要求への対応,特別な食事要求に対応できない
店舗,顧客体験,その他,該当なし
店舗,その他,該当なし,該当なし
商品企画,メニュー開発,新商品の提案,新商品のアイデアが不足
商品企画,メニュー開発,健康志向のオプション,健康志向メニューが少ない
商品企画,メニュー開発,季節限定メニュー,季節限定メニューが魅力的でない
商品企画,メニュー開発,その他,該当なし
商品企画,フィードバック管理,顧客の意見集約,顧客の意見が反映されない
商品企画,フィードバック管理,商品改善,商品の改善が見られない
商品企画,フィードバック管理,トレンド分析,最新トレンドの分析不足
商品企画,フィードバック管理,その他,該当なし
商品企画,その他,該当なし,該当なし
モバイルオーダー,システムパフォーマンス,アプリの安定性,アプリがクラッシュする
モバイルオーダー,システムパフォーマンス,注文処理速度,オンライン注文の遅延
モバイルオーダー,システムパフォーマンス,ユーザーインターフェース,アプリの操作が複雑
モバイルオーダー,システムパフォーマンス,その他,該当なし
モバイルオーダー,機能性,カスタマイズオプション,カスタマイズオプションが限られている
モバイルオーダー,機能性,アレルギー情報,アレルギー情報が不足している
モバイルオーダー,機能性,ナビゲーション,アプリのナビゲーションがわかりにくい
モバイルオーダー,機能性,その他,該当なし
モバイルオーダー,その他,該当なし,該当なし
オンラインストア,商品在庫,限定商品の在庫状況,限定グッズがすぐに売り切れる
オンラインストア,商品在庫,商品情報の更新,商品情報が最新でない
オンラインストア,商品在庫,その他,該当なし
オンラインストア,注文システム,システムの使いやすさ,オンライン注文がしにくい
オンラインストア,注文システム,注文の処理速度,オンライン注文が処理されない
オンラインストア,注文システム,注文の正確性,オンライン注文が間違っている
オンラインストア,注文システム,その他,該当なし
オンラインストア,その他,該当なし,該当なし
ポイントシステム,利用体験,ポイント加算の明確さ,ポイントが予想より少ない
ポイントシステム,利用体験,利用方法,ポイントの利用方法が分かりにくい
ポイントシステム,利用体験,利用可能商品,ポイントで交換できる商品が少ない
オンラインストア,利用体験,その他,該当なし
ポイントシステム,システム性能,システムの安定性,ポイントシステムのエラー
ポイントシステム,システム性能,アクセスの容易さ,ポイントシステムへのアクセスが難しい
ポイントシステム,システム性能,情報の透明性,ポイントの計算が不透明
ポイントシステム,システム性能,その他,該当なし
ポイントシステム,その他,該当なし
プロモーション,宣伝,SNSでの告知,SNSでのプロモーションが見つからない
プロモーション,宣伝,メールマーケティング,プロモーションメールが届かない
プロモーション,宣伝,店内告知,店内でのプロモーション告知が目立たない
プロモーション,宣伝,その他,該当なし
プロモーション,オファー,限定メニュー,限定メニューの魅力
プロモーション,オファー,その他,該当なし
プロモーション,その他,該当なし,該当なし

## 特記事項
カテゴライズ表に厳密に従ってください。存在しない項目を生成しないでください。
大カテゴリ、カテゴリ、サブカテゴリを異なる組み合わせにしないでください
そしてJSONのみ出力してください

なぜ機械学習で双対問題を学ぶのか

結果から述べるのであれば、SVM(サポートベクトルマシーン)の原理で双対問題を使いたいからです。

これから実際どのように双対問題が使われているのか、また、双対問題の簡単な具体例を交えて説明していきたいと思います。

まずSVMについて簡単に説明したいと思います。

予測には過去のデータを使います。

しかし、外れ値のような余計なデータまで使ってしまうと、予測精度が下がるかもしれません。

そこで「本当に予測に必要となる一部のデータ」だけを使います。

「本当に予測に必要となる一部のデータ」のことをサポートベクトルと呼び、

サポートベクトルを用いた機械学習法がサポートベクトルマシン(Sapport vector machine:SVM)です。


双対問題とは

数学において、最適化問題における主問題の補問題のことです。

どちらか一方の解法が両方の問題の解法となります。

最適化理論における双対原理とは、最適化問題を主問題と双対問題のどちらの観点からも見ることができます。

ここで、双対定理についても簡単に説明したいと思います。

双対定理(英: duality theorem)は次のように定義される。

主問題と双対問題のいずれか一方が最適解を持つなら、もう一方も最適解を持ち、主問題の最小値と双対問題の最大値は一致するというものです。

今回はなぜどちらか一方の解が両方の解として良いのかという点についても説明をしたいと思います。


双対問題の具体例

今回あげる具体例は元の主問題だけでも解を求めることができますが、双対問題を使うパターンと主問題を直接解くパターンを紹介したいと思います。

主問題が以下だとします。

\[ \max f(x_{1},x_{2})=-(x_{1}^2+x_{2}^2) \\ s.t. x_{1}-1≧0 , x_{2}-1=0 \] これは領域を考えると解は明らかに求まります。
\((x_{1},x_{2})=(1,1)\)の時、\(f\)は最大値\(-2\)をとります。
以上が双対問題を使わない解き方です。
次に、双対問題を使った解き方を紹介します。
まず双対問題の導出します。 \[ L(x_{1},x_{2},\lambda,\mu)=-(x_{1})^2-(x_{2})^2+\lambda(x_{1}-1)+\mu(x_{2}-1) \\ =-\left(x_{1}-\frac{\lambda}{2}\right)^{2}-\left(x_{2}-\frac{\mu}{2}\right)^{2}+\left(\frac{\lambda}{2}\right)^2-\lambda+\left(\frac{\mu}{2}\right)^2-\mu (*) \] つまり、 \[ \displaystyle d(\lambda,\mu)=\max_{(x_{1},x_{2})} L(x_{1},x_{2},\lambda,\mu) \\ =\left(\frac{\lambda}{2}\right)^2-\lambda+\left(\frac{\mu}{2}\right)^2-\mu \] となります。 (\(-\left(x_{1}-\frac{\lambda}{2}\right)^2-\left(x_{2}-\frac{\mu}{2}\right)^2)\)は\(0\)以下だから)
従って、双対問題は以下になります。 \[ \displaystyle \min d(\lambda,\mu)=\max_{(x_{1},x_{2})} L(x_{1},x_{2},\lambda,\mu)~~ s.t. \lambda≧0 \] これを\(\lambda,\mu\)に関して平方完成すると、 \[ d(\lambda,\mu)=\frac{1}{4}{(\lambda-2)^{2}+(\mu-2)^{2}}-2 \] 以上から双対問題の最適解は\((\lambda,\mu)=(2,2)\)となり、\(d(2,2)=-2\)
また、(*)から \[ x_{1}=\frac{\lambda}{2}, x_{2}=\frac{\mu}{2}  \] だったので、 \[ (x_{1},x_{2})=(1,1) \] の時が最適解となる。
このように、主問題と双対問題の最適解と最適値は一致することがわかりました。


鞍点定理

\((x^*,λ^*,μ^*)\in \mathbb{R}^n×\mathbb{R}^l×\mathbb{R}^m\)が鞍点

任意の\(x\in \mathbb{R}^n\)および\((\lambda,\mu)\in \mathbb{R}^l×\mathbb{R}^m\)に対し、 (\(\lambda\)の各成分が0以上) \[ L(x,\lambda^*,\mu^*)≦L(x^*,\lambda^*,\mu^*)≦L(x^*,\lambda,\mu) \] を満たす


鞍点定理

(1)\((x^*,\lambda^*,\mu^*)\)が鞍点である時、以下の性質が成り立つ
 (a)\(x^*\)は主問題の最適解
 (b)\((\lambda^*,\mu^*)\)は双対問題の最適解
 (c)\(f(x^*)=d(\lambda^*,\mu^*)=L(x^*,\lambda^*,\mu^*)\)
(2)•\(f\)が上に凸,\(g_{i}\)が上に凸
   かつ
  •\(g_{i}(x)>0 (i=1,\cdots,l)\)かつ\(h_{j}(x)=0 (j=1,\cdots,m)\)を満たす\(x\in\mathbb{R}^{n}\)
が存在する
  かつ
 •主問題に最適解\(\hat{x}\)が存在する\(\Rightarrow (\hat{\lambda},\hat{\mu})\in\mathbb{R}^l×\mathbb{R}^m\)が存在して、\((\hat{x},\hat{\lambda},\hat{\mu})\)が鞍点となる。
証明は(1)についてのみ書きたいと思います。
\(F=\{x\in\mathbb{R}^{n} | g_{i}(x)≧0 , h_{j}(x)=0 (i=1,\cdots,l) (j=1,\cdots,m)\}\)とする。
(a)\(x^{*}\)は主問題の最適解
  鞍点の条件から任意の\((\lambda,\mu)\in \mathbb{R}^l×\mathbb{R}^m\)に対し、 \[ L(x^*,\lambda,\mu)=f(x^*)+\sum_{i=1}^{l} \lambda_{i}g_{i}(x^*)+\sum_{i=1}^{m}\mu_{j}h_{j}(x^*)≧L(x,\lambda^*,\mu^*) \]  もし \(g_{i}(x^*)<0\)または\(h_{j}(x)≠0\)ならば\(L(x^*,\lambda,\mu)\)は下界を持たないので矛盾。
背理法から\(g_{i}(x)≧0 , h_{j}(x)=0 \)が満たされるので\(x^*\in F\)となる。
さらに、\(\lambda=0,\mu=0\)のときの不等式から\(f(x^*)≧L(x^*,\lambda^*,\mu^*)\cdots➀\)
一方で、 \begin{eqnarray} L(x^*,\lambda^*,\mu^*)&≧&\max_{x} L(x,\lambda^*,\mu^*) (∵鞍点) \\ &≧&\max_{x\in F} L(x,\lambda^*,\mu^*) \\           &=&\max_{x\in F} f(x^*)+\sum_{i=1}^{l} \lambda_{i}g_{i}(x^*)+\sum_{i=1}^{m}\mu_{j}h_{j}(x^*) \\           &≧&\max_{x\in F} f(x)\cdots➁ \end{eqnarray} ➀,➁より、\(f(x^*)≧L(x^*,\lambda^*,\mu^*)≧\max_{x\in F} f(x) \\  x^*\in F\)だから上式の不等号は等号となる。
つまり、\(x^*\)は主問題の最適解かつ\(f(x^*)=L(x^*,\lambda^*,\mu^*)\)
(b)\((\lambda^*,\mu^*)\)は双対問題の最適解 \begin{eqnarray} d(\lambda,\mu)&=&\max_{x\in \mathbb{R}^{n}} L(x,\lambda,\mu) \\ &≧&L(x^*,\lambda,\mu)   (∵x^*\in \mathbb{R}^{n}) \\     &≧&L(x^*,\lambda^*,\mu^*)    (∵鞍点) \end{eqnarray} また、 \begin{eqnarray} d(\lambda^*,\mu^*)&=&\max_{x\in \mathbb{R}^{n}} L(x,\lambda^*,\mu^*) \\      &≦&L(x^*,\lambda^*,\mu^*) \end{eqnarray} よって、任意の\((\lambda,\mu)\in \mathbb{R}^{l}×\mathbb{R}^{m}\)に対し、 \[ d(\lambda^*,\mu^*)≦L(x^*,\lambda^*,\mu^*)≦d(\lambda,\mu) \] これより\((\lambda^*,\mu^*)\)は双対問題の最適解かつ\(d(\lambda^*,\mu^*)=L(x^*,\lambda^*,\mu^*)\)
以上で証明部分を終わりにしたいと思います。


まとめ

双対問題を考えることで、対象の最適化問題を簡単に解くことができることが多いため双対問題を扱うことがわかりました。

また、なぜ双対問題を考えることが主問題の解を求めることと同値であることをメインに紹介してきました。

さらに、鞍点定理についても紹介しましたが、証明についてはかなり難しくなっているため定理の主張だけ抑えておくのがいいのかと思います。

2022年卒大学生の皆さん!

コロナウイルスが流行していることで就活にどういう影響があるのか、とても不安ですよね。

今回は業界ごとに採用人数を予測し、「どの業界が狙い目なのか」機械学習を使った分析手順を紹介します!

目次

  1. 概要
  2. 手順
  3. 今後の課題


1.概要

データセットの内容

スクリーンショット 2020-08-25 9.47.11.png


分析対象の7業界・各4企業

  1. 化粧品
  2. 電子機器
  3. 商社
  4. 不動産
  5. 金融
  6. サービス
  7. IT・情報


説明変数と目的変数

特徴量
年初の株価、決算報告書提出翌日の株価、一株あたりの純資産額、従業員数、業界番号
決算報告書翌日の株価が出ていないところは提出後直近の株価を使用する。また、純資産額に関しては決算報告書が7/1の時点で未提出の場合に限り、昨年の値を使用する。


目的変数
採用人数
新卒採用人数は、リクナビorマイナビorキャリタスのデータを使用する。  

2.手順

今回は方法の紹介を行う。


欠損値の補完

従業員数
過去2年分の従業員数の変化率を使う。
例えば、2018年と2019年の従業員数の変化率を使って2020年の従業員を補完する。


株価
①複数企業での、同じ年代の1月株価と通期決算報告翌日の株価の変化率の平均を使う。
 例えば、リクルートの2018年の1月株価と決算翌日の株価の変化率をA、東京海上日動の2018年の変化率をBとする。ミクシィの2018年の決算翌日の株価を求めたい時(1月株価は既知)、AとBの変化率の平均値を1月株価に掛けて補完する。
②1月株価の値と決算翌日の株価の値、どちらも未知の場合は行を削除する。


純資産
直近の純資産で補完する。


モデル

回帰分析
回帰分析して、業界ごとの採用人数の平均値をとる。
説明変数:従業員数、株価(決算報告翌日)、業界、純資産
目的変数:採用人数


クラスタリング
①従業員数、純資産を複数の範囲に分けて数字or文字に置き換える。
 例えば、従業員数3000以下は「1」、3001〜5000を「2」で置く。
②①で数字に置き換えた二つのカラムを使い、純資産÷従業員数で得た結果を新しいカラム[value]に入れ込む。
③株価と採用人数も①同様に複数の範囲に分けて数字or文字に置き換える。
④数字で複数個の範囲に分けた採用人数を「down」「stay」「up」の3つのグループにまとめる。
説明変数:「value」「株価(決算報告書提出翌日)」
目的変数:採用人数


今後の課題

今回は5つの特徴量のみで行ないましたが、もっと良い特徴量があるかもしれません。 また、データ数が少なく欠損値が多かったため、期待する制度に満たない可能性があります。

精度を向上のためには、特徴量・企業のデータ数を増やすこと、欠損値の補完方法を変えるなど、様々な方法があります。今後はモデルの実装も含め行います。

目次

  • 機械翻訳とは
  • 機械翻訳の手法
  • 現在の機械翻訳の欠点
  • 欠点が改善されると
  • 今後の展望


機械翻訳とは

機械翻訳という言葉を理解するために2つ言葉を定義する。

系列 : 記号の列のことで自然言語処理の世界だと文を構成する単語の列になる。
系列変換モデル : 系列を受け取り、それを別の系列に変換する際の確率をモデル化したもの。系列変換モデルはseq2-seqモデルとも呼ばれている。

この2つの言葉から機械翻訳は、ある言語の文章(系列)を別の言語の文章(系列)に変換する方法論の総称のことをいう。例えば、日本語の文章という系列を英語の文章という別の系列に変えることである。特に、系列変換モデルの考えを使った機械翻訳をニューラル機械翻訳と呼ぶことがある。


機械翻訳の手法

歴史的には、以下のような翻訳方法がある。


ルールベース翻訳

登録済みのルールを適応することで原文を分析し、訳文を出力する機械翻訳の方法。ここでいう「ルール」は、各言語の「文法」に置き換えられる。定めたルールに則っていなければ翻訳ができないが、則ってさえいればしっかりと翻訳可能である。現在は、旧時代的な機械翻訳方法として認識されている。 ルールに基づく機械翻訳の基本になるのはルールである。ルールによる構文解析の仕組みを、ツリーによる機械翻訳の例を挙げる。

まず以下のルール

NP → ART N (名詞句 は 冠詞 名詞 で構成される)
VP → V NP (動詞句 は 動詞 名詞句 で構成される)
S → NP VP (文 は 名詞句 動詞句 で構成される)


を使って以下の英文を解析してみる。

A client sent the form


ルールベース機械翻訳では、辞書もルールとして扱う。理論を考える場合だけでなく、実用的な機械翻訳システムを設計する場合にも辞書をルールとして扱うほうが良いとされている。ここでは、辞書として以下のルールも用意する。

ART → a (冠詞 は a で構成される)
ART → the (冠詞 は the で構成される)
N → client (名詞 は client で構成される)
N → form (名詞 は form で構成される)
V → sent (動詞 は sent で構成される)


まず、原文にある単語それぞれの品詞を判定する。

ART - a
N - client
V - sent
ART - the
N - form


次に、当てはまるルールを探して順次適用する。左端のARTとNに

NP → ART N (名詞句 は 冠詞 名詞 で構成される)


が当てはまるため、左端のARTとNからNPを作れる。

MT_01.png


同様に、右端のARTとNからもNPを作れる。

MT_02.png


次に、

VP → V NP (動詞句 は 動詞 名詞句 で構成される)


を当てはめることができ、VとNPからVPを作れる。

MT_03.png


最後に以下のルール

S → NP VP (文 は 名詞句 動詞句 で構成される)


が当てはまるため、NPとVPからSを作れる。

MT_04-1.png


これ以上適用できるルールはなく、最終的な目標としていた文 (S) を検出できたので、これで解析成功である。最終的に、原文の構造を表すツリーを作ることができる。


用例ベース翻訳

入力文の各部分に対して類似した用例を選択し、それを組み合わせて翻訳を行う。
この方法はほかの方法よりも自然な翻訳文の生成が可能であると考えられている。理由としては、人間も翻訳する際に様々な用例から翻訳をしているからである。また、用例の追加により容易にシ ステムを改善可能である。

しかし、用例ベース翻訳は入力文や用例を解析するのに高精度なものを必要としているが、十分な精度をもつものが存在しなく、用例ベース翻訳は実現されていなかった。現在は木構造により用例ベース翻訳は研究されている。

原文を解析して木構造を作り、その木を置き換えながら翻訳する。
下図のように木構造を作る。

原文: OK button sends the form to the remote server.
訳文: [OK] ボタンはフォームをリモート サーバに送信する。

MT_05.png


このようにして、様々な用例パターンを抽出している。この方法は、日本発祥である。

必ずしも文法に従って原文を解析する必要はないが、ツリー構造を使うと柔軟な翻訳が可能である。
この方法の長所は先ほどのルールベース翻訳のように膨大な量のルールを機械に覚えさせる必要がない点である。


統計翻訳

コンピュータに学習用のコーパスを与え、統計モデ ルを学習させることで訳文を出力させる方法。ルールベース機械翻訳の弱点をカバーするとして、注目された方法である。

具体的には、対訳コーパスという、例えば日本語でよくある言い回し

0001
日: Xではないかとつくづく疑問に思う
英: I often wonder if it might be X.
中: 难道不会是X吗,我实在是感到怀疑。
1000
日: 私はXを視野にしっかり入れています
英: I put more focus on X.
中: 我非常重视X。
2000
日: 彼がレストランで昼食をとる
英: He eats lunch at a restaurant.
中: 他在餐馆吃午饭。


を英語や中国語に翻訳した大量のコーパスから学習をし、評価対象の文を翻訳する方法である。 統計翻訳において統計的モデルを学習するアルゴリズムは、言語に依存しないため、大量の対訳データがあれば多言語化が容易であり、開発コストを抑えることが可能である。


現在の機械翻訳の欠点

系列変換モデルに基づくニューラル翻訳システムの弱点の1つに、語彙数の問題がある。扱う語彙数を多くすると計算量が大きくなりすぎて現実的な速度での学習や評価ができなくなる。
また、語彙数が多くなるということは、語彙選択問題がより難しくなるため、不用意に語彙を増やしても翻訳精度が低下するだけということも起こる。

さらに、イベント名など時間とともに新語が出現するので、本質的に未知語を完全になくすことは不可能である。機械翻訳タスクでは未知語をどのように扱うかは永遠のテーマとなっている。
統計翻訳時代の考え方から、未知語と判定されたものを後処理で何かの語に置き換えるという方法が用いられている。いくつかの論文の実験セクションでは「RnkRep」のような用語を使ってその結果を示して いる。

一方、ニューラル翻訳に移行してからは、新しい考え方も使われるようになった。
1つは、入出力の単位を「単語」ではなく「文字」にしてしまう方法である。「文字」であれば使われる文字集合は事前に網羅できかつ、新語に比べて新文字の出現は限りなく低いことから、増えることはないという仮定ができる。一方、個々の文字選択問題が簡単になっても、系列長は単語の時と比べて圧倒的に長くなるので、そちらで予測誤りが多くなる問題が発生する。

次に、文字単位はあまりにも細かすぎるという考え方から、文字単位と単語単位の丁度中間に相当する方法論として、バイト対符号化という方法も提案されている。この方法はニューラル翻訳を行う前処理とし て、与えられたデータを使い出現頻度が最も大きい文字ペアを1つの文字としてまとめるという処理を事前に決めた語彙数まで繰り返し処理する。これで得られた文字の結合ルールは、未知の文に対しても、得られた順番で適用していけば、必ず一意に同じ符号化された文を獲得するこ とができる。

文字単位、単語単位、バイト対符号化の 3 種類のうち、どれが総合的に優れているかは決着がついていないが、最近はバイト対符号化が良いのではないかということが言われている。


欠点が改善されると...

未知語に関しての欠点が改善されると、扱う語彙数をうまくコントロールした翻訳が可能になる。

扱い語彙数が多くなると計算量が多くなるため、現実的な速度で計算が不可能であったが、語彙数をうまくコントロールし翻訳をすれば、計算速度が速く、語彙選択問題も簡単になることから高精度に翻訳が可能であると考えられる。
さらに、翻訳をするために高性能なコンピューターを必要としていたが、計算量を減らすことで、安価なコンピューターを用いても高性能な翻訳が可能になるだろう。


今後の展望

機械翻訳タスクは、現在の自然言語処理分野の深層学習/ニューラルネットワーク研究の中心的な位置を占めていると考えられている。

多くの研究成果が報告されており、どの技術が最終的に生き残るか現状見極めるのが難しい。しかし、2015年、2016年で、系列変換モデルによるニューラル翻訳の基礎的な理論が出来上がり、統計翻訳よりも有意に良いと認められるに至っている。研究の余地は非常に多く残されている研究領域であり、独自技術を開発する必要があると考えられている。
機械翻訳がさらに発展すると以下のことが実現するだろう。

コストを抑えてスピーディーな翻訳が可能
機械翻訳の最大のメリットとして、よりスピーディーに、コストを抑えた翻訳が可能になったという点が挙げられる。翻訳速度が速い翻訳家に依頼しても、英文の日本語訳の場合、1日1500〜2000語が目安といわれている。しかし、人間が8時間かけて翻訳する作業を、Google翻訳は数十秒足らずで処理してしまう。さらに、翻訳家に翻訳サービスを依頼すると、一文字5円の場合、2000文字の英文の翻訳に10,000円かかるのに対し、Google翻訳なら、100を超える言語を無料で翻訳が可能である。


翻訳結果を文書として残せる
ビジネスの世界では、文書の配布や、保管、管理を行うために記録として残す必要があり、正確さも求められる。こうした場合、文書から別の言語の文書に翻訳できる機械翻訳が適している。ポストエディットという言葉があるが、これは機械翻訳を利用した後に行われる人間の翻訳者による修正作業のことである。機械翻訳が発展したらポストエディットの作業も徐々に減っていくと考えられ、人間が行う作業を効率的に減らすことが可能である。


参考文献

深層学習による自然言語処理 坪井祐太/海野裕也/鈴木 潤・著
ニューラル機械翻訳以前を支えた「ルールベース機械翻訳(RMT)」と「統計的機械翻訳(SMT)」
ルールベース機械翻訳の概要 (4)
用例ベース機械翻訳の概要 (1)
機械翻訳と自動翻訳に違いはある?使い分けはどうすればよい?

こんにちは。

皆さんはFXでお金を稼ぎたいと思ったことはあるでしょうか?もしFXでこれまでの生活を一変させるような額のお金を稼ぐことができたら夢のようですよね?

今回はそんな夢を目指して、為替の値動きを機械学習で予測してみたというお話をしたいと思います。


目次

  1. 概要
  2. 手順
  3. 結果
  4. 今後の課題


1 概要

  • 使用したデータセット:OANDA APIを用いて取得
    https://www.oanda.jp/fxproduct/api
    (デモ口座を開設することにより、無料でAPIを利用することができます)

  • 使用したモデル:LSTM

データセット
米ドル円の2016年9月22日から2020年7月20日までの1000個の日足データを取得し利用します。

スクリーンショット 2020-07-21 14.27.04.png
今回は、open(始値)、close(終値)、high(高値)、low(安値)、volume(取引量)という基本的な特徴量を用います。

LSTMとは?

 LSTMは時系列予測をするためのライブラリです。
LSTM(Long short-term memory)は、RNN(Recurrent Neural Network)の拡張として1995年に登場した、時系列データに対するモデル、または構造の1種です。その名前は、Long term memory(長期記憶)とShort term memory(短期記憶)という神経科学における用語から取られています。 ニューラルネットワークは過去の出来事を考慮することができず、RNNは長い記憶に対応できないという欠点があります。そこで長い過去の記憶を考慮できるように、LSTMが開発されました。 今回は5日分のデータを1セットとしてLSTMで予測をしました。
つまり、5日間の為替レートのデータを1セットとして、それを何セットも学習することで、新しい5日間のデータからその次の為替レートを予測していきます。


2 手順

 今回為替予測をするにあたって行った手順について簡単に説明します。  

  1. データセットの準備
       OANDA APIを用いて取得する

  2. データの加工
      ・データセットの「time」の部分が特殊な形(「ISO 8601」)を日本時間に直す
      ・データを学習データと訓練データに分割する
      ・LSTM用にデータを変換する
       絶対的な為替価格ではなく、どのように為替価格が変化し、どの程度価格が変動するかを見る変化率に直す
      ・PandasのデータフレームからNumpy配列へ変換する

  3. LSTMのモデル構築と学習・予測
      ・機械学習ライブラリのKerasを利用してモデル構築を行う
    (Kerasについてはこちらをご覧くださいhttps://keras.io/ja/
      ・モデルの訓練を行う
      ・作成したモデルを用いて、予測をする


3 結果

 2のところで紹介した手順で為替の予測を行ってみました。結果をチャートにしたものがこちらです。

スクリーンショット 2020-07-31 8.54.42.png
青のラインが実際の為替の値動き、赤が今回予測した為替の値動きです。

どうでしょうか。それっぽいものができていると思いますが、チャートをみてみると最初の方で大きく外しているほか、気になるのが、実際の値動きの後に遅れて予測したものが動いている点です。実際にレートが動いてから予測結果が出るため、エントリーのタイミングを逃してしまう可能性があり、各個人での判断が必要となってしまいます。


4 今後の課題

 今回は一日の為替価格のみのデータで分析をしました。為替の値動きは、様々な経済指標やトランプ大統領の発言、1日の中の時間帯によっても変わっていくので、そのようなニュースの情報やTwitterなどの情報も取り入れたらさらに精度の高いものが出来上がるのではないかと思います。
 FXトレーダーは、自分なりにチャートを分析し、何らかの基準を持ってトレードをしています。彼らのノウハウや経験をうまく機械学習に落とし込めれば、同等、またはそれ以上の精度で予測できるのではないかと個人的には思います。
 引き続き機械学習を用いた為替予測を頑張っていきたいです!

このブログはそもそもパラメータという言葉をよく耳にするが、どのように決定しているのか知りたい人(機械学習の初歩的な数学の理論を知りたい人)向けです。少し数学的な計算も入ってきます。

学習とは、仮定から導き出した誤差関数を最小に,あるいは尤度関数や事後分布を最大にするパラメータを求めることでした。そのうち今回は尤度関数と勾配法について説明していきたいと思います。

パラメータとはどういう設定値や制限値で機械学習の予測モデルを作るのかを示すものです。イメージとして、あとで定義する尤度関数が下のグラフのようになっている時、尤度関数の最大値を取るθを求めるという作業です。

download.jpg

目次

  1. 最尤推定法

  2. 勾配法

  3. 最尤推定法と勾配法の問題点


1.最尤推定法

確率分布は既知ですが、ある母数(パラメータθ)が未知な母集団を考えます。

この場合、この確率分布が連続型であるならば、確率分布はθに依存する関数と考えられ、f(x,θ)と表します。

この母集団から独立にn個標本を抽出した時のデータがx1,x2,....,xnの値をとる確率は、L(θ)=f(x1,θ)f(x2,θ)....*f(xn,θ)と考えられ、L(θ)を尤度関数といいます。

まず具体例を見てみましょう。

正規分布の平均、分散の最尤推定

X~N(μ,σ^2)とします。(N(μ,σ^2)は平均μ、分散σ^2の正規分布)

すると以下のように平均と分散の最尤推定値が求められます。
正規分布の確率密度関数を以下のように与えられます。

正規分布1-1-1.png

(x1,.....,xn)というデータが与えられたとすると、尤度関数は次のようになります。

正規分布1-2.png

なので両辺に自然対数を取ると、以下のように対数尤度関数が導かれます。

正規分布1-3.png

これから平均μを最尤推定法により推定します。対数尤度関数をμに関する関数と見て偏微分し、その結果が0となる値を求めます。

正規分布2.png

次に、分散σ^2を最尤推定法により推定します。対数尤度関数をσ^2に関する関数と見て偏微分し、その結果が0となる値を求めます。

正規分布3.png

以上が最尤雨推定法の概要です。


2.勾配法

勾配法は最小値や最大値を求めるためのアルゴリズムで、解析的に解くことが困難な問題に用いられます。

「解析的に解けない」とは、ある関数に対してうまく微分ができない状態や実際に数値として表すには禁じせざるを得ない状況のことです。

勾配法は解析的に解くのが困難な時に有効なアルゴリズムで、最適化問題などに用いられます。 具体的な方法を解説していきます。

  1. 適当に初期点を決める

  2. 今いる位置における関数の値が最も小さくなる方向を計算する

  3. その方向に微小単位で移動する

その後は、2,3の手順をひたすら繰り返し、収束した場合、この繰り返しを終了します。

download.png

この例は解析的にも解けますが、勾配法を使って説明するとまずはじめにx0という点を初期値として選択します。

次に、今いる位置における関数が小さくなる方向を計算します。これは図からわかる通り、x1の方向に近づく方向になります。

ここからは今までの操作の繰り返しです。

すると、図からX*という点で今まで同様左側に移動すると関数の値が大きくなってしまいます。

つまり、図の範囲でパラメータとして最も良いものはx*ということになります。


3.最尤推定法の問題点

データ数が少ない時に偏りがあることです。

この例としてコインの裏表を3回投げるという試行を考えます。 もし、表が三回連続で出てしまった時、表の出る確率は最尤推定法で求めると1となりますが、本来表の出る確率は1/2であるはずです。 これがデータ数が少ないことによるパラメータの偏りです。

サンプルから構造を推測する モデルにおいては適していません。

例えば、混合正規分布、混合2項分布、神経回路網、ベイズネットワーク、 隠れマルコフモデルなどのもウール構造を持つモデルについては最尤推定法は適していません。 つまり、「尤度関数が最尤推定量の近傍でだけ 大きな値になる」という条件が最尤推定が安全に使えるための条件です。

また、尤度関数は常に解析的に解けるものではないので、最尤推定以外の方法でパラメータを求める必要があります。(勾配法など) 必ずしも全ての試行が確率分布に従うとは限らず、確率密度のある点における接線の傾きを測る勾配符が用いられるケースがあります。

皆さんはレポートを作成する際、どのような方法で作成していますか?

膨大な量のデータを読み解き、文章を考えて、何かうまくまとまらない...... もっと簡単にできたらいいのに!と思ったことはありませんか?

この記事では、Arria NLG PLCのデータから文章を生成する技術について紹介します。


1 ARRIA NLG PLCとは?

ARRIA NLG PLCは2009年に設立した企業です。しかし、その技術は30年間の科学的研究に基づいたもので、ARRIA NLG PLC ホームページではこのように紹介しています。

『ARRIA NLG PLCは、自然言語生成(NLG)として知られる人工知能(AI)分野におけるグローバルリーダーです。Arriaは、Arria NLGプラットフォームを介して利用可能な、特許取得済みのコアNLGテクノロジーを所有、開発、およびライセンス供与しています。Arria NLGプラットフォームの中心は、世界で最も先進的な自然言語生成エンジンであるArria NLGエンジンです。』(ARRIA NLG PLC ホームページより)  


2 NLGとは?

 NLGとは、自然言語生成(Natural Language Generation)のことであり、自然言語処理の一種で、文・画像など様々な表現を入力として、最終的に自然言語文を出力とする処理のことです。


3 ARRIA NLGエンジンの仕組み

Raw Dataを取り込み、Narrative Explanationを出力します。

Untitled Diagram.jpg

Raw Data
構造化および非構造化の両方のさまざまなデータソースから取り込む

Data Analysis and Interpretation
データを処理し、重要な事実を抽出、解釈する

Document Planning
データから派生したメッセージを受け取り、メッセージに含まれる情報を含む上手な文章を構築する方法を考え出す

Micro-Planning
流暢さと一貫性を最大化するために情報をまとめ、文章化する方法を考え出す

Surface Realisation
正しい文法、単語の選択、形態、句読点を用いた文章構成となるようにする

Narrative Explanation
さまざまな形式(HTML、PDF、Wordなど)で出力することができ、必要に応じてグラフィックスとの組み合わせや音声での配信も可能


4 ARRIA NLGの利用方法

  • レポート作成の自動化
  • データの可視化による意思決定支援
  • レポートの作成と送信の高速化


5 ARRIA NLGの活用

 ARRIA NLGのテクノロジーは天気の分野や金融分野をはじめ、様々な分野に利用されています。

 NLGシステムで使用されるデータは、株価、会社の利益、降雨量、気温、雇用統計などの時系列データです。データは空間的である場合もあり、場所による変動(異なる地理的領域での降雨など)を示したり、時空間で両方の次元の変動(たとえば、異なる地理的領域での時間による降水量)を組み合わせたりします。NLGの目的は、生データのコンテンツをユーザーがよりアクセスしやすくすることにより、付加価値を与えることです。まず、データのパターンと傾向を検出することで、何が起こっているのかについて、生データを見るよりもユーザーが捉えやすくなります。 


6 ARRIA NLGの活躍

 Arria NLGは様々な企業と提携し、そのテクノロジーを社会のために活かしています。以下は最近ニュースになった話題について紹介します。  

『自然言語生成(NLG)テクノロジーの有力プロバイダーであるArria NLGは20日、Glemser Technologiesと提携し、医療・製薬企業にスケーラブルな自動化ソリューションと大幅な効率性を提供すると発表した。GlemserはArriaのテクノロジーで駆動されるNatural Language Generationソリューションによって、世界で展開する同社のライフサイエンス業務を強化する。』(ニューヨーク2020年5月20日PR Newswire=共同通信JBN)


『自然言語生成(NLG)テクノロジーの有力プロバイダーであるArria NLGは6日、バンク・オブ・ニューヨーク・メロン・コーポレーション(BNY Mellon)と提携し、アセットマネージャーおよびアセットオーナーがデータをアクショナブルアナリティクスに変換することを支援すると発表した。BNY Mellon Data and Analytics Solutionsのクライアントは今、自然言語生成の能力を通じてデータからより良い知見を引き出すことが可能になる。』(ニューヨーク2020年5月6日PR Newswire=共同通信JBN)


『Arria NLGは17日、BBCニュース・ウェブサイトが同社のSemi-Automatic Local Content(Salco)プロジェクトを通じて、Arriaの自然言語生成(NLG)プラットフォームの使用を拡大し、英国で行われた総選挙のニュース報道を自動化したと公表した。 BBC News Labの目標は、総選挙の夜にそれぞれの契約者向けに地元の開票集計・結果が入った地域ごとに編集されたニュースを報道する能力を拡大することだった。Arria NLGによって、この巨大メディアは英国歴史上最も多忙なニュースの夜に、それぞれの人口動態に関する地方データを提供してその目標を達成するとともに、多数の記事の報道に成功した。』(モリスタウン(米ニュージャージー州)2019年12月17日PR Newswire=共同通信JBN)

引用:プレスリリース/ニュースリリース配信の共同通信PRWire(https://kyodonewsprwire.jp/author/H100002)


7 おわりに

今回は、機械学習海外活用事例としてARRIA NLG PLCの自然言語生成技術を紹介しました。この技術は文章作成という個人的な身近な問題を解決するだけではなく、様々な分野で人々の役に立つ技術だということがわかりました。この技術はもっと社会に広がっていくと考えられます。今後のさらなる活躍が楽しみですね!


出典:

『TECHNICAL OVERVIEW: THE ARRIA NLG ENGINE
『Arria NLG』


Twitter・Facebookで定期的に情報発信しています!

概要

 今回は、以前ブログで紹介したText-to-Text Transfer Transformer(T5)から派生したWT5(Why? T5)を紹介します。

 Text-to-Text Transfer Transformerとは、NLP(自然言語処理)のタスクをtext-to-text(テキストを入力して、テキストを出力する)形式として考えたもので、様々なタスクでSoTA(State of the Art=最高水準)を獲得しました。こちらの記事で詳しく紹介しています。Googleが発表した自然言語処理モデルText-to-Text Transfer Transformer(T5)とは?

 このT5を改良したWT5のポイントは、"Why T5?"という名前にもある通り、予測に対してその予測の根拠となる説明を与えるということです。

 近年、大規模な事前学習モデルをはじめとするニューラルネットワークをNLPタスクに使用することで、人間を超えるような性能を達成するようになってきました。しかし、ニューラルネットワークの問題点として、なぜモデルがそのような予測をしたのかが分からない、いわゆる「ブラックボックス」になっているということが挙げられます。この問題を解決するためにWT5では、タスクの答えに加えて根拠を説明する文も与えています。この背景には、人間も意思決定の理由もブラックボックスになってはいるが、求めると理由を説明できるため、機械にも同じことを求めています。


手法

解釈可能性と説明生成

 予測の根拠を与える方法として採用されている3つを紹介します。

ルールベース
予測をするルールをあらかじめ与えて、そのルールの基づいて予測をする手法です。たとえば、「ひどい」という単語が入っていたらnegativeと判定するとしたら、「あの選手のプレーはひどかった」という文はnegativeと判定されます。この方法はあらかじめルールがあるので、予測の根拠は明らかになっていて解釈可能性は高いです。ただ、「あの選手のプレーにひどく感動した」のような文までnegativeと返してしまうことがあるので性能としてはあまりよくありません。

説明抽出
判定の根拠となる説明を入力の文字列からそのまま抽出してくる手法です。上の例でいうと「ひどかった」「ひどく感動した」を説明として抽出するイメージです。この手法だと、英語での"they"や日本語での「あれ」というような単語を含む文を抽出すると、単語が何を指しているのかわからないという問題が起こる可能性があります。

説明生成
言葉の通り入力を受けて判定する根拠を「説明抽出」のような制限なしに生成します。直感的に分かるような説明生成を正確におこなうことにより、人間に近い判断ができるようになります。


  WT5では、基本的に説明生成を行いますが、説明抽出のタスクにも対応できるようにしています。

 ここで解釈可能性と性能について、ルールベースの手法・従来のニューラルネット・WT5(提案手法)・人間で比べた図を見てみます。上で紹介したようにニューラルネットワークは性能は高くても解釈可能性は低く、ルールベースは性能が低くも解釈可能性は高いことが分かります。説明生成のWT5は人間と同等の解釈可能性を持ちながら、人間を超える性能を出しています。この図を見るだけでWT5の良さが分かります。

Interpretability.png


モデルのフォーマット

 WT5モデルがテキストを入力してテキストを出力する様子を図を使って説明します。WT5のもととなったT5の入出力を見てみます。

T5.png

入力では先頭に"translate English to German"などタスクを表すテキストが与えられて、その後ろに"That is good."などのタスクを行う入力を与えています。出力は、単に入力に対しての答えのみを返します。

wt5.png

 それに対してWT5では、説明文を生成したい場合、入力の先頭に"explain sentiment"など、"explain"+タスクという形式のテキストを与えることで、出力では"negative explanation"+説明ような、タスクの答え+"explanation"+根拠となる説明という形式のテキストを返して、タスクの答えとともに根拠となる説明も同時に返します。  また、説明は出力せずにタスクの答えのみを出したい場合には、図の青い部分のように、入力の先頭にタスク名のみを与えればその答えのみを与えられるようにモデルを構築しています。

 説明生成だけでなく説明抽出のタスクにも対応でき、その場合は入力の先頭の"explain"の部分を"explanation"変えることで、説明文を抽出するように訓練されています。


訓練

訓練に使用するデータセットは次の4つです。

e-SNLI
SNLIデータセット(前提と仮説が与えられて、前提に対して仮説が正しいのかを判定。それぞれのデータに対して正しい(entailment)、矛盾(contradiction)、どちらでもない(neutral)の中からいずれかがラベルとしてついている)について、それぞれのラベルに対する根拠となる説明テキストをアノテーションしたデータセット

Cos-E
Commonsense Question-Answering(CQA)データセット(一般常識についての質問応答セットで、質問に対して選択肢とその中から回答が与えられている)に、選択の根拠となる説明テキストをアノテーションしたデータセット

Movie Reviews
映画レビューの感情分析データセット(一つの映画レビューに対して、positive/negativeのラベルがついている)に、判定の根拠となるテキストを説明抽出によりアノテーションしたデータセット

MultiRC
MultiRCデータセット(文章が与えられて、その文についての質問と答えの候補が与えられていて、候補それぞれTrue/Falseのラベルが与えられている)に、説明抽出による説明がアノテーションされている

モデルの学習は、2種類のT5モデルを使ってファインチューニングを行います。一つは2億個のパラメータを持つBaseモデルで、もう一つが110個のパラメータを持つ11Bモデルを使います。ファインチューニングの方法としてはT5モデルの際と同様のダウンストリームタスクにより行っています。

学習率・バッチサイズ等、訓練の詳しい設定については論文をご覧ください。


評価

評価に使用する指標は、分類精度に対してはMultiRCのみF1スコアを採用して、それ以外はAccuracy、生成された文に対しては量的な評価として、説明抽出を行うタスク(Movie Reviews, MultiRC)についてはF1スコア、説明生成を行うタスク(e-SNLI, CoS-E)についてはBLUEを使用しています。 また、量的は指標だけでは説明の質についてが十分に評価することができないので、質的な評価として人間による評価も行っています。NLPのタスク、特に対話や今回のような文章を生成する際には人間の評価が重要になることがあるので、そこも注意深く見ていく必要があります。


実験

まずは、それぞれのデータセットでどうなるのかを見ていきます。

table1.png

結果を見ると、WT5-11Bがかなり高い性能を出しており、分類精度では2つ、説明文の評価では3つのタスクでSoTAを獲得しています。また、WT5-Baseでもそれなりのスコアを出せています。この結果はT5のときと似たような感覚です。

説明文の評価を見てみると、説明生成というタスクの性質を考えると量的なスコアが低めに出るのは必然なのかなと思います。ただ、論文中でも述べられているように、Cos-Eタスクの値は他と比べてもかなり低くなっていて、これはアノテーションした説明文の質があまりよくないことが原因ではないかとされています。人間が生成した説明文に対する人手による評価も低めに出ているので、そもそも人による説明がブレるようなタスクに対しては、性能が上がりにくいのかもしれません。

MultiRCでも、人による評価については同じような傾向があるようにも見えるので、個人的には、一般常識や読解など人により考えが変わるようなタスクでは、説明が難しくなってくるのかなと思います。ただ、この辺の評価はどう捉えるのかが難しい部分も出てくるので一概には言えないと思います。

実際にWT5(11B)が生成・抽出した説明文です。

table2.png


説明文を減らしての実験

次に、教師データとなる説明文を減らした場合にモデルの性能がどうなるのかを評価しています。

目的は、アノテーションをして説明文を付与する手間が省けるのかどうかを確認するためです。もし性能が変わらなければ、他のデータセットも簡単に使うことができる可能性があります。

fig3.png

結果を見ると、e-SNLIについては、Accuracyはほとんど変わらず、BLUEに関しては説明文を減らしていくと値が低下するものの、100まで減らしても従来のSoTAよりも高い数値を出しています。

Cos-Eについてもほとんど値は変化せず、説明文を減らしても影響は見られません。

それに対して、Movie Reviewsに関しては説明文を減らしていくとかなり性能が落ちていることが分かります。

また、グラフにはないですが、MultiRCもMovie Reviewsと同じような性能の低下があることから、説明抽出を行うタスクには説明文の教師データがそれなりに必要であることが分かります。


データセット間での転移

説明生成のタスクでは説明文の教師データ説明文が少なくても性能が下がらないことが分かったので、同じタスクの説明文を持たない他のデータセットを合わせて使用してうまくいくかを見ていきます。

具体的にはe-SNLIデータセットとMNLIデータセットを合わせて使用した場合と、Movie ReviewsとIMDb、Amazon Reviewsを使用した場合を見ます。MNLIとIMDb、Amazon Reviewsはそれぞれe-SNLIとMNLIよりもより多くのドメインを含んでいます。

それぞれの場合について今までと同様に学習させて、タスクの分類精度は上と同様の評価で、生成した説明文については人による評価を行います。 分類精度は、MNLI:91.5%・IMDb:97.2%・Amazon Reviews:98.1%とかなり良く、説明文の評価もMNLI:82%・IMDb:94%となっていて説明文生成もうまくいっていることが分かります。このことから、ドメインの異なる文章に対しても対応できることが分かります。 このような説明文が生成・抽出されます。   table3.png


タスク間での転移

最後に、異なるタスクのデータセットに対して学習を行ってもうまくいくのかを見ていきます。

具体的には、説明文ありのe-SNLIデータセットと説明文なしのe-SNLIデータセット、説明文なしのCoS-Eデータセットを使ってファインチューニングして、CoS-Eに対して説明文が生成できるかを見ます。e-SNLIとCoS-Eは全く違うタスクで、CoS-Eについては説明文を一つも与えていないので"zero-shot"になっています。

結果としては、完全にうまくいったとは言えないようですが、下のようにうまくいったものもあるのでタスク間での転移も可能だろうとしています。この辺は残った課題としていますね。 また、詳細については述べませんが、"bean-search decoding"を使うと説明の信頼性が改善されたようです。

table4.png

まとめ

 今回はText-to-Text Transfer Transformer(T5)をもとにした、予測と説明文を生成するWT5(Why? T5)について紹介しました。

まだ改善の必要があるものの、説明文生成などができればブラックボックスなものが解消されますし、アプローチはかなり異なってきます。将来的にはNLPだけでなく、他の分野のタスクでも説明文生成することができれば説明可能なAIの開発につながっていくかもしれません。 これからもtext-to-textの広がりに注目したいです。

参考文献

WT5?! Training Text-to-Text Models to Explain their Predictions
WT5?! Text-to-TextモデルでNLPタスクの予測理由を説明する手法!


Twitter・Facebookで定期的に情報発信しています!

新型コロナウイルス感染症とは?

2019年12月より中国で 新型コロナウイルス ( COVID-19 )による肺炎が発生し、2020年4月現在では日本国内でも急速に感染が拡大しています。

新型コロナウイルスは、感染症法における「 指定感染症 」、及び検疫法における「 検疫感染症 」に指定され、感染が確認された患者に対して入院措置などの法的処置を取ることが可能となりました。

今回は、まず感染の拡大等を予測できる感染症モデルについていくつか紹介していこうと思います。また、感染症拡大の指標である基本再生産数・実効再生産数についても、実際のコロナウイルスのデータを用いてみていきます。


感染症モデルと基本再生産数・実効再生産数

これまで私たちは、新型コロナウイルスをはじめとする様々な危機にさらされてきました。それを機に感染症の流行を抑えるべく、感染者の隔離による感染個体との接触回避や、ワクチン接種による免疫力の向上など様々な対策を講じてきました。一方、感染症の流行のメカニズムを定式化することにより得られる、感染症の数理モデルによる感染症の流行規模の予測も注目されています。

感染症の数理モデルとは、簡単に言うと「感染症がどのように伝播し、感染した人がどの程度の期間で発症し、どの程度の期間で回復するのか」といったプロセスを、数式によって記述したものです。

感染症モデルにも、そのプロセスをどのように仮定するかにより様々なものが存在します。今回はその中のいくつかを紹介していきます。


SIR model

SIRモデルは、感染症モデルの中で基本となるモデルで、原形はKermack-McKendrick(1927)によるモデルです。

 このモデルは、対象とする全人口を

  • 感受性保持者(Susceptible):感染症への免疫がなく、これから感染する可能性がある人
  • 感染者(Infectios):感染症に現在感染している人
  • 免疫保持者(Recovered):感染症から回復して免疫を持った人もしくは死亡した人


の3つの状態に分かれると仮定し、集団に感染症が広がる様子を表したモデルで、時間経過によるそれぞれの状態の個体数の増減を考えています。

ここでは感染症にかかった少数の人が、感染症にかかる可能性のある大きな集団と接触した場合を想定しています。

SIR.png

SIRモデルは以下の微分方程式により定式化されます。

スクリーンショット 2020-04-30 9.30.08.png

ここでS(t)、I(t)、R(t)はそれぞれ時刻tでの感受性保持者数、感染者数、免疫保持者数を表していて、微分方程式のそれぞれの式は微小時間での個体数の増減を数式化したものです。感受性保持者から感染者となる推移は両者が接触することを想定していることから、感受性保持者の減少及び感染者数の増加を表す式は、感受性保持者数と感染者数の積を用いて表現されています。

また、βは感染伝達係数、つまり感染率を意味するパラメータで、この値が大きいほど人から人へと感染しやすいこと表しています。

γは回復などで感染者でなくなる割合を表していて、感染症が治りやすければこの値も大きくなります。 ここで感染症が流行するというのは、モデル中のI(t)が増加することで、その条件は上のI'(t)の式から求めることができます。 初期値をI(0)、S(0)として、

sir2.png

が正のとき、つまり
スクリーンショット 2020-04-30 9.50.45.png

のとき、I(t)は初期時刻からの微小時間では単調増加で、ある時刻で最大値を取ります。最大値に到達した後は単調減少で0に収束していきます。 この値は基本再生産数と呼ばれます。ここで、基本再生産数について実効再生産数とともに簡単に説明したいと思います。


基本再生産数と実効再生産数

 基本再生産数とは、1人の感染者が感染力を失うまでに平均して何人の感受性保持者に直接感染させるのかという人数で、どの程度感染を広げる可能性があるかを示しています。 これは、

基本再生産数 =(単位時間あたりの2次感染者数) ×(平均感染期間)
       = 1次感染者が感染期間中に生み出す2次感染者数 と表すことができます。 またSIRモデルの式から、基本再生産数は
R0.png
と表せます。

この値が
スクリーンショット 2020-04-30 9.44.44.png
のとき感染症の流行が発生します。

基本再生産数を計算する一例を紹介します。

r0_cal-1.png

この図は、赤い丸が一人の感染者を表しています。一番左の時点を第1世代とし、その感染者が新たな感染者(第2世代)を生み出すとし、ここでは第6世代まで広がるとしています。一人の感染者が生み出す新たな感染者数は異なり、これが多いほど感染力の高い感染症であるとも考えられます。 ここで基本再生産数は

(全世代の新規感染者数)÷(世代数) で求めることができます。

ここで注意しなければならないのは、一般に基本再生産数の値は、一切対策を取らなかったときに感染症がどの程度感染を広げていく可能性があるのかを示すということです。

実効再生産数とは、感受性固体の一部が免疫化された集団の再生産数のことで、簡単に言うと、感染拡大しないように対策を取ったときの実際の再生産数のことです。感染症の流行を抑えるために、拡大防止対策を講じ、理論的には実効再生産数の値が1を下回れば感染の流行を収束に向かわせることができます。収束に向かわせるといっても、その期間の新たな感染者数が減少するということで、感染症が収まってなくなるというわけではありません。感染症の最終的な収束には、実効再生産数が大きくなりすぎないように対策を講じながら、集団免疫を獲得するかワクチン等の開発を待つ必要があるそうです。

基本再生産数の取る値により感染者数の増減はどのように異なるのでしょうか。

まず、基本的なSIRモデルの挙動は以下のようになります。

sir_g.png

ここで注目するのは基本再生産数の値を40(β=0.2)のときと、4(β=0.02)のときの感染者数I(t)の推移を見てみます。

またγ=0.05、S(0)=10、I(0)=10とします。

I_beta.png

このグラフから、基本再生産数の値が大きくなると感染症の広がりが速くなり、そのピーク時の感染者数の最大値も大きくってしまうことが分かります。つまり、何も対策を取らなければ、感染症は急激に広がり、同時期に多くの感染者が発生してしまうのです。

次にSIRモデルから派生したSEIRモデルについて紹介します。


SEIRモデル

SEIRモデルとは、SIRモデルの3つの状態に加えて、潜伏期感染者(Exposed)を考えたモデルです。

つまり、対象とする全人口を

  • 感受性保持者(Susceptible):感染症への免疫がなく、これから感染する可能性がある人
  • 潜伏期感染者(Exposed):感染症に感染したが潜伏期間で、感染力がない人
  • 感染者(Infectios):感染症に現在感染している人で、感染力がある人
  • 免疫保持者(Recovered):感染症から回復して免疫を持った人もしくは死亡した人


の4つの状態に分かれると仮定し、集団に感染症が広がる様子を表したモデルで、時間経過によるそれぞれの状態の個体数の増減を考えています。 今回のコロナウイルスを簡単に見るときにはSEIRモデルがよく使われているような印象です。

SEIR.png

SEIRモデルは以下の微分方程式により定式化されます。

SEIR_equ.png

ここでS(t)、E(t)、I(t)、R(t)はそれぞれ時刻tでの感受性保持者数、潜伏期感染者数、感染者数、免疫保持者数を表していて、微分方程式のそれぞれの式は微小時間での個体数の増減を数式化したものです。ここでSIRモデルで無かったパラメータσは潜伏期間から感染状態へ移行することを表す係数で、単位時間あたりの発症率を表します。

SEIRモデルの挙動は以下のようになります。

SIR_graph.png

次にSISモデルについて説明します。


SISモデル

SISモデルは、感受性保持者(Susceptible)と感染者(Infected)の2つの状態のみを考えます。感受性保持者から感染者へ移行するのはSIRモデルと同じですが、SISモデルでは感染してから回復した後に免疫を獲得せずに、再び感受性保持者になり、感染の可能性がある状態へと移行すると考えています。

SIS.png

SISモデルは以下の微分方程式により定式化されます。

SIS_equ-1.png

ここでS(t)、I(t)はそれぞれ時刻tでの感受性保持者数、感染者数を表していて、微分方程式のそれぞれの式は微小時間での個体数の増減を数式化したものです。また、ここで出てくる係数はSIRモデルと同じです。SIRモデルと比べると、感受性保持者から感染者へと移行する様子が良く分かると思います。

SISモデルの挙動は以下のようになります。

SIS_graph.png

グラフを見て分かるように、ある程度まで感染者が増えると、感受性保持者と感染者の数が一定になります。つまり一定になってからは、感受性保持者と感染者の状態を一定数が行き来しているということになります。

これらの感染症モデルを見ていると、感染症による状態の遷移をどのように仮定するかでモデルが決まることが分かると思います。これら以外でも、違う仮定をすることで感染症モデルは提案がされていますし、感染症ごとにモデルを検討されることもあると思います。

感染症モデルを用いることで、感染症が出てきた段階では、どの程度広がっていくのかスピード等も考慮しながら予測することができ、対策を講じる際に利用することができます。また、対策を講じた後もどの程度効果があったかや、その先対策を講じながらの感染者の推移について予測する際にも用いることができます。

また実際に感染がどの程度抑えられているかは、実効再生産数を算出することで確認できます。


コロナウイルスデータの実効再生産数の推移

実際のコロナウイルスの感染者数データから、実効再生産数の推移を見ていこうと思います。実効再生産数については上で紹介しましたが、計算法についてはいくつかあるようで、今回はCoriらの論文にあるエクセルシートを使いました。データについてはsignateのCOVID-19 Challengeで与えられている都道府県ごとの感染者数データを使っています。本来、実効再生産数を計算する際には検査数等も考慮する必要があると思いますし、実際に専門の方が計算するのとは差があり、あまり正確な値ではないので、参考程度に考えてください。

ここで推移を見るのは、北海道・東京・大阪・愛知としました。愛知県のみ、5月14日で緊急事態宣言が解除されています。(5月19日時点)

hokkaido.png

tokyo.png

osaka.png

aichi.png

グラフを見るポイントは、実効再生産数が1未満に抑えることができているかということです。それぞれ見ると5月19日時点で、すべて実効再生産数1を下回っているので、感染の広がりをうまく抑えられているように思います。

推移の中で、実効再生産数が1を下回り安定し始めたの日は、北海道が5月5日ごろ、東京・大阪が4月21日ごろ、愛知が4月15日ごろとなっています。一足先に緊急事態宣言が解除された愛知が、少しですが他よりも早く実効再生産数が下がった印象です。また東京・大阪にくらべて、北海道は実効再生産数が1未満に下がるのが遅い印象なので、緊急事態宣言の解除等に影響してくるかもしれません。

あくまでも参考値であるものの、今回見た地域では実効再生産数が5月19日時点で1を下回って少し落ち着ているので、少しずつ自粛緩和 は進んでくるとは思います。ただしグラフを見て分かるように、少し前の時期には実効再生産数が1を大きく上回っています。また、今の状況というのは強めに自粛を呼び掛けての結果ですので、実際に少し前の時期には実効再生産数が1を上回っていた事実をデータから受け止め、簡単にその状態に戻ってしまうことを肝に銘じておく必要があると思います。


まとめ

今回はコロナウイルスの流行により注目されている感染症モデル等について紹介しました。日々状況が更新される中で、実効再生産数等はこれからも対策をとる一つの指標となるので、正しく理解することが大切です。


Twitter・Facebookで定期的に情報発信しています!

世界で猛威を振るうコロナウイルスの抑制に向けて、AI・機械学習はどのような貢献ができるでしょうか。

政府、研究者、保健機関を支援するための早期警告、および検出アルゴリズム、患者の旅行履歴に基づく分析、そして最終的にはコロナウイルスワクチンの作成および開発まで、AIはおそらく鍵となるテクノロジーになるでしょう。今回はAI・機械学習での貢献にチャレンジしている事例を紹介します。


機械学習によるウイルスの検出と追跡

たとえば、カナダに本拠を置く病気の分散予測プラットフォームBlueDotが実際にコロナウイルスの発生を特定したのは、米国疾病対策センターからの公式警告があった5日前の 2019年12月31日でした。BlueDotのアルゴリズムは、自然言語処理と機械学習を使用して、65か国語のニュースレポートを、航空会社のフライトデータと動物の病気の発生レポートとともに分析します。システムはこれらのレポートをふるいにかけることにより、感染した住民がどこに、いつ移動する可能性が高いかを特定し、ウイルスが武漢からバンコク、ソウル、台北、東京に広がるのではないかと予測しました。

機械学習は、コロナウイルス曝露の可能性について旅行者をスクリーニングするためにも利用されています。
マレーシアの電子サービス会社MY EG Services Berhadは、中国の旅行会社であるPhoenix Travel Worldwideとともに、入国しようとしている中国観光客ががコロナウイルスに曝された可能性があるか、またはその危険性があるかどうか判断するため、AIがリスクを分析するソリューションを展開しています。このソリューションの機械学習アルゴリズムは、いくつかのデータポイント(以前いた場所、心拍数、血圧など)を利用して分析・予測をしています。


治療計画の作成

ウイルスの追跡以外にも、AIはワクチンの開発や治療に利用されています。
Insilico Medicineは、香港に本拠を置くAIを活用した創薬会社で、コロナウイルスと戦うことができる可能性がある分子化合物を無料公開しています。このテクノロジーは機械学習を使用して特定の分子の特性とそれらがウイルスと相互作用する方法を分析しています。結果に対して薬学者からのフィードバックを求め、ワクチン開発機関の短縮に貢献することを目指しています。


おわりに

貢献の成果が出るのはこれからかと思いますが、複数のソリューションがスピード感を持って開発されています。中国で話題になった「マスクマップ」に続くソリューションが今後も生み出されていくでしょう。

KaggleやSIGNATEでもコロナウイルス分析へのコンペが開催されています。当社インターンでも結果を公開できるように進めています。


Twitter・Facebookで定期的に情報発信しています!

0. 背景

特徴量の自動抽出 」を行うのがDeep Learningの強みの1つですが、与えられたデータに対する推論の過程が ブラックボックス化 され、なぜその特徴量を抽出したのか説明できないという問題点もあります。

例えば、自動運転技術が搭載されている車で事故が起こった場合、「 なぜ事故が起こったのか 」という原因の究明が難しく、実用化にあたり大きなハードルになっています。

最近の機械学習関連の学会では「 Explainability (説明可能性)」についての話題が増えています。この説明可能性については大きく2つ、「 法的な側面 」と「 技術的な側面 」があります。


法的な側面

先の自動運転の例で言うと、起きた事故について「 誰に責任の所在があるのか 」という問題が発生します。「AIを作った人間」に責任があるのか、それとも「AI本体」にあるのか説明出来なければなりません。 外部的な要請として「 AI利活用原則案・AI開発ガイドライン案 」などがあり、他にも「機械学習における公平性・説明責任・透明性」ワークショップFAT/MLが2014年から毎年開催され、国際的な議論もなされています。


技術的な側面

再び自動運転の例を挙げると、事故が起こる直前に、なぜその判断を下したのか「 判断の根拠 」をユーザーに分かりやすく提示しなければなりません。 技術的な面については米国のDARPAが XAI(Explainable AI) 研究開発投資プログラムを開始しており、機械学習に解釈性を持たせつつ精度を上げることを目的としています。


1.Explainable AI(XAI)のアプローチ

A Survey Of MethodsFor Explaining Black Box Modelの論文によると、XAIのアプローチは次の4つに分類できます。

  • Black Box Explanation(解釈可能モデルの抽出) : AIをブラックボックスとして同等の解釈可能なモデルの生成
  • Model Output Explanation(出力に対する説明の生成) : AIの出力に対し、予測の根拠を説明
  • Model Inspection(ブラックボックスの中身の検査) : ブラックボックスの中身の説明
  • Transparent Box Design(透明性のある学習器の設計) : AIの学習過程や構造を人間が解釈しやすくモデル化


それぞれのアプローチの概要を図示すると以下のようになります。

XAI_1.png

Explainable Artificial Intelligence (XAI): Concepts, Taxonomies,Opportunities and Challenges toward Responsible AIより引用

ではそれぞれのアプローチにおける代表的な技術を紹介します。


Black Box Model Explanation(解釈可能モデルの抽出)

代表的な例としてTrepan、G-Rexがあります。

Trepan
ニューラルネットワークbからからこれと等価な決定木を抽出します。具体的にはbに対して人工的なデータを流し、bの出力を得ながら決定木を構築します。

G-Rex
ニューラルネットワークbに対して、学習データである入力と出力の組み合わせからルールを出力します。学習データに少し摂動を加えたデータに対する出力もルールに組み込むことにより、学習データ以外の入力に対するbの振舞いも抽出できます。

Model Output Explanation(出力に対する説明の生成)

最も盛んに研究が進められているアプローチで、代表的な例としてLIME、Grad-CAM、SHAPがあります。

LIME(Local Interpretable Model-Agnostic Explanations)
データ一つに対する機械学習モデルの分類器による予測結果に対して、どの特徴に注目して分類が行われたかの説明をします。例えば、猫の画像認識を行うブラックボックスモデルにおいて、正しく判定されたデータに対して、入力データの特徴に該当する部分を少しずつ変更して結果を比較することで、どの特徴が判定に寄与したかを明らかにします。

Grad-CAM
まずCNNにおいて、入力データの画素の位置情報を最終畳み込み層まで保持させます。そして最後の判別出力への位置情報の影響度を得ることで、元画像上にホットスポット(影響の強い部分)を表示します。

SHAP
結果に対する特徴の貢献度を定量化します。これにより、ある特徴変数の値の増減が与える影響を可視化することが出来ます。例えば、口座が引き落とし不能になる確率を70%としたとき、"年齢=20歳"が25%、"職業=フリーター"が40%、"既婚"であることは-20%などのように、属性値ごとに予測値への数値としての寄与度に分解します。

Model Inspection(ブラックボックスの中身の検査)

代表的な例としてVEC、Prospectorがあります。

VEC
ブラックボックスの中身を見て、出力に対し入力がどのように影響を与えるかを、グラフを用いて可視化します。

Prospector
インタラクティブに入力を変えると、出力がどのように変わるかを示すアプリケーションをユーザーに提供します。

Transparent Box Design(透明性のある学習器の設計)

代表的な例としてFRLがあります。

FRL(Falling Rule Lists)
そもそも説明性のあるルールによる分類や診断技術に対して、各々のルールに正しさの確率を付与したり、ルールに優先順位を付けることにより、透明性がありかつ性能の高い学習器を設計します。


2.総論

ディープラーニングを使う機械学習では、「 特徴抽出の自動化 」により与えられたデータに対する推論の過程が「 見えない 」という問題があります。

ディープラーニングを用いた製品やサービスで事故や判断ミスなど重大な問題を引き起こした場合、原因の究明、改善が要請されます。その際に先述したようなブラックボックス化されているモデルの「説明可能性」に関する話題が増えています。

しかし、XAIには対象や目的に応じて上記のような様々なアプローチがあるので、個別企業だけでは研究開発をカバーしきれないという問題もあります。各国は、XAIを協調領域として国家プロジェクトとしても取り組んでいます。前出のDARPAのXAIのプロジェクトの他にも、国内ではNEDOの「次世代人工知能・ロボット中核技術開発」(人工知能の信頼性に関する技術開発)があり、2019年度は「説明できるAI」に関する7件が採択されました。

このような取り組みを皮切りに、私達もAIに関する問題を解決していきたいと考えています。


参考文献

AI白書2020
AI利活用原則案(総務省)
AI開発ガイドライン案(総務省)


Twitter・Facebookで定期的に情報発信しています!

最近、「機械学習って何が出来るの?」「AIとなにが違うの?」という質問を多くいただくようになってきました。それもそのはず、5年間で機械学習の検索ボリュームは約3倍になりました。


picture_pc_acac8dea3e6eddac84c73fa1e8673294.png


機械学習の概要やどんな課題解決ができるのか、事例をご紹介します。


目次

  1. 人工知能(AI)とは
  2. 機械学習とは
  3. 機械学習の種類
  4. 機械学習の歴史
  5. 解決したい課題別 機械学習の活用事例
    コスト削減/人依存の解消/生産性向上/品質向上
  6. 導入検討フロー


人工知能(AI)とは

人工知能のイメージは人によって大きく違います。人工知能が「推論・認識・判断など、人間と同じ知的な処理能力を持つ機械(情報処理システム)」であることは大多数の研究者たちの意見も一致していますが、それより細かい定義については専門家たちの間で共有されている定義はありません。「人間と同じ知的な処理能力」の解釈がそれぞれ異なるからです。

専門家の定義が定まらないため、一般のイメージはなおさら曖昧です。イメージしやすいものは、お掃除ロボットや自動運転のようにシステムが自ら考えて行動しているように見える、周りの環境に応じて自らの行動を変えられるものでしょう。

なにができるか、といった視点から人工知能を分類し、解説します。


picture_pc_01038c560b5f79fb84172f99dc3846d5.png


1.ルールベースでの制御

エアコンの温度調整など、予め行動が決まっている製品が当てはまります。制御工学やシステム工学と呼ばれ、人工知能には当てはまりません。

2.古典的な人工知能

掃除ロボットや診断プログラムなど、探索・推論・知識データを活用し、状況に応じて振る舞いを変える製品です。既に広く実用化されており、機械学習・深層学習の研究の先駆けです。

3.機械学習

検索エンジンや交通渋滞予測など、大量のサンプルデータを元に入力と出力の関係を学習した製品です。古くから研究され、2000年代に入り、ますます発展しています。

4.深層学習(ディープラーニング)

機械学習では、学習対象の「どのような特徴が学習に影響するか(特徴量)」を見極めることは非常に重要で難しいです。例えば、売上予測をする際にその日の天気が重要、と分かっていると効率的に学習が進められます。 この特徴量を自動で学習するシステムが深層学習です。画像認識、音声認識、自動翻訳など、従来のコンピュータで実現が難しいとされてきた分野での応用が進んでいます。


機械学習とは

機械学習とは、コンピュータにデータを与え、アルゴリズムに基づいた分析をさせる手法のことです。事例となるデータを反復的に学ばせて、特徴やパターンを見つけ出します。見つけた特徴を新しいデータに適用することで分析や予測を行います。 解きたい課題によってそのアプローチは様々です。機械学習にも得意不得意があり、どのような課題であれば機械学習で解決できるのかを知っておくことが重要です。

機械学習が対象とする課題の種類は次の3つにまとめられます。

教師あり学習

与えられたデータを元にそのデータがどんなパターンになるか予測・識別するものです。例えば

  • 過去の受注データから未来の受注を予測したい
  • 写真がどの動物か識別したい
  • 英語の文章を日本語に翻訳したい


といった活用ができます。つまり、与えられたデータ(入力)と返す答え(出力)にどんな関係があるかを学習する手法です。
また、受注予測のように連続したデータの予測は回帰、写真の識別のようにカテゴリを予測するものは分類といいます。

教師なし学習

教師あり学習では、入力データと出力データが対になっていましたが、教師なし学習は出力データがありません。教師=出力データですね。例えば

  • 顧客層がどのようなものか知りたい
  • 膨大なデータの項目間の関係性を知りたい


このようにデータに意味をもたせたい時に活用されます。

強化学習

強化学習は教師あり・なし学習とは少し異なり、「行動を学習する仕組み」とよく表現されています。ある環境下で、目的とする報酬を最大化するための行動はなにか、を学習していきます。例えば

  • パックマンの行動最適化
  • プロ囲碁棋士を破ったコンピュータ囲碁(Aipha Go)


が挙げられます。学習内容の表現が教師あり学習より難しいため、ビジネス活用は上の2つよりは遅れています。

機械学習の歴史

機械学習の歴史は深く、始めて人工知能という言葉が使われたのが1956年のダートマス会議においてでした。世界初の汎用電子式コンピュータが開発されたちょうど10年後です。

人工知能はブームと冬の時代を何度も繰り返しています。

第1次AIブーム(1950年代後半〜1960年代)

コンピュータによる推論・探索の研究が進み、特定の問題に対して解を導けるようになったことが始まりです。東西冷戦中のアメリカでは英語ーロシア語の機械翻訳が注目されました。 しかし、数学の証明のような簡単な問題は解けても、現実の複雑な問題は解けないことが明らかになり、1970年代には冬の時代に入りました。

第2次AIブーム(1980年代)

コンピュータに知識を入れると賢くなるというアプローチが全盛となり、データベースに大量の専門知識を入れたエキスパートシステムが多数登場しました。しかし、その知識を管理・蓄積させることの大変さから1995年頃にまた冬の時代に突入しました。

第3次AIブーム(2010年〜)

ビッグデータを用いることで、人工知能が自ら知識を獲得する機械学習が実用化されました。また、特徴量(学習の際に注目すべき特徴を定量的に表したもの)を自ら発見して学習する深層学習(ディープラーニング)が登場したこともブームの背景です。

3つのブームは関係しあっています。
例えば、1990年にインターネット上にWebページが出現し、データが蓄積されるようになったことで、データ活用が進み、機械学習が発展しました。その機械学習も急に出現したわけではなく、第1次ブームや第2次ブームの時も機械学習は研究されています。

解決したい課題別 機械学習の活用事例

ここからは具体的に機械学習で解決できることを紹介していきます。よく聞く課題をピックアップしています。
(タイトルのリンククリックで事例ページに遷移します。)

コスト削減

点検作業の自動化
カメラで撮影した建物画像からひび割れ等の老朽化箇所を検出します。人からシステムに役割を変えることができ、人件費削減だけではなくかかる時間も短縮することができています。

倉庫内配置の最適化
倉庫内にカメラを配置し、撮影することで作業社の行動や物の位置を把握し分析します。倉庫内の動線や配置の最適化によって業務を効率化し、コスト削減を実現します。

特定箇所への農薬散布
企業が農業へ参入したことで、日本では集約農業から大規模農業へと転換が進んでいます。広大な農地で作物を育成する際に、ドローン等で空撮したデータから必要な箇所を割り出して、病害虫が発生している箇所ピンポイントに農薬を散布します。農薬使用量を削減できるだけでなく、他作物へのダメージを減らすことができます。

無人レジ
人がレジ打ちをする作業をなくしシステムが自動計算します。パンやドーナツ、ケーキなどラベルが付いていないものへのアプローチとして有効です。

人依存の解消

受注量予測
過去の受注量のメカニズムからどれだけの発注があるか予測します。ベテランにしかできなかった発注業務の敷居を下げることで、限られた人しかできなかった業務を分配することができます。

野菜収穫の自動化
ノウハウが重要な収穫時の見極めをAIがおこないます。AIが判断した後にロボットに信号を送ると自動で収穫をおこなうマシンも検討できます。

生産性向上

問合せへの自動応答
社内からの問合せ件数は日にかなりものです。その問合せをチャットボットで自動応答にすることができます。質問者も作文に時間をかけずに気軽に質問することができます。

居眠り検知
同じ作業が続く検品等で、うとうとしそうになってしまうことがあります。目の開きがあまくなるとアラートが鳴り、目を覚ましてくれるシステムも構築できます。

品質向上

高解像度画像の作成
最新のAI技術では荒く見づらい画像を高解像度に直すことができます。品質で失注していた案件に、より良い提案が出来る可能性が上がります。

コンベア内の品質チェック
コンベアを流れる物体が良品か不良品かを判定します。不良品可能性のある物は人が見るまでもなく振り分けることで、人の疲労による見落としを減らすことができます。

口コミ分析
集まった口コミを分析し、改善点を明確にします。その口コミが「ポジティブかネガティブか」を分類し、ネガティブな口コミの原因抽出をします。

導入検討フロー

導入検討が成功した事例はまだまだ公開数が少なく、何から手を付けてよいか...。と相談を受けることもあります。(もちろん例外も多々ありますが)一般的な機械学習導入検討フローを紹介します。


picture_pc_8a78dc2140d079f15eac054a9fdf3eba.png


1.企画

機械学習は手段であり、活用が目的ではありません。「解決すべき課題はなにか」を深堀りし、実現したい世界を明確にすることが大切です。手段として機械学習が適切かどうか、費用対効果の試算も必要です。 また、機械学習活用にはデータが必要です。必要なデータが揃っているのか、収集できるのか、どれほど欠損があるのか(すぐに機械学習に使えるキレイなデータはほとんどありません。)の確認もこの段階で重要です。

2.検証(PoC)

企画した計画の実現可能性を確かめる段階です。 機械学習アルゴリズムの選定→データの前処理(整形)→機械学習モデルの選定・構築→評価 のプロセスを実行し、求める結果に達する可能性と工数を確かめます。 求めたい精度に達するまで、別のアルゴリズムを試したり、モデルを変更したりとチューニングします。 機械学習は魔法ではありません。特性上、試してみないとどのくらいの精度が出せるか分かりません。そのため、まずは小さく試して実現可能性を確認することが必要です。

3.本開発

検証段階で実現性が確認できたモデルを実運用に向けて拡大していきます。 検証段階では限られた条件のため、作成したモデルをそのまま横展開しても思うような結果(精度)が出ないことも多々あります。その場合は、検証段階のモデルやノウハウを活用しつつも、モデルを再チューニングします。 また、目的に立ち返り、「本当に必要な精度」を再検討することで、チューニングにかかるコストを削減することもできます。

4.運用

いよいよ業務で活用します。機械学習を業務に取り入れると、業務フローが少なからず変わります。現場で使われるシステムにするために業務フローを再設計することが必要です。

機械学習はこれからビシネス活用が進んでいくフェーズです。そのため経験豊富なベンダーと二人三脚の検討が成功のコツでしょう。

アクセルユニバースの紹介

私達はビジョンに『社会生活を豊かにさせるサービスを提供する。』ことを掲げ、このビジョンを通して世界を笑顔にしようと機械学習・深層学習を提案しています。

  • ミッション(存在意義)
    私達は、情報通信技術を使って万物(全ての社会、生物)の暮らしをよりよくすることに貢献し、 それを加速させることを使命とします。

  • ビジョン(目標とする姿)
    社会生活を豊かにさせるサービスを提供する。

  • バリュー(行動規範)

    1. 変化を求め、変化を好み、変化する
    2. 自分の高みを目指してどんどん挑戦する
    3. お客様と一蓮托生でプロジェクトを進める


会社概要はこちら


Twitter・Facebookで定期的に情報発信しています!

フェイクニュースは珍しいものではありません。
コロナウイルスの情報が凄まじい速さで拡散されていますが、その中にもフェイクニュースは混ざっています。悪意により操作された情報、過大表現された情報、ネガティブに偏って作成された情報は身近にも存在しています。
これらによって、私たちは不必要な不安を感じ、コロナ疲れ・コロナ鬱などという言葉も出現しました。

TwitterやInstagramなどのソーシャルメディアでは嘘みたいな衝撃的なニュースはさらに誇張な表現で拡散され、フェイクニュースは瞬く間に広がります。嘘を見破るのは難しく、見破られないまま多くの人に「正しい情報」として届けられています。
2017年に『Journal of Economic Perspectives』誌に掲載された記事では、アメリカの成人の62%がソーシャルメディア上でニュースを得ており、フェイクニュースサイトへの訪問は41.8%がソーシャルメディアのリンクを経由していることが示されています。

フェイクニュースの無い世界ではじめて、私たちは正しい情報に触れ健全な判断をすることができます。
しかし、膨大な情報が混在するソーシャルメディア上でフェイクニュースを発見する作業は人間が行うにはコストがかかりすぎるため現実的ではありません。

AIはフェイクニュースを発見できないでしょうか。


AIはフェイクニュースを発見できる?

ソーシャルメディアの登録者数が世界的に増えているにも関わらずソーシャルメディアのプラットフォームもこの新興市場に投資していないようで、技術検証に留まっています。

革新的なスタートアップが出現するかどうかは出資の有無にかかっているでしょう。 今後、ソーシャルメディアの世界を牽引するためにフェイクニュース検出への投資が出現するのではないでしょうか。

商品化はされていませんが、技術検証は進んでいます。


FEVERによる情報の正誤判定

マサチューセッツ工科大学では、Facebookが支援している研究者がフェイクニュースを発見するためにFEVER(Fact Extraction and Verification)を利用しています。 ※FEVER:大規模なファクトチェックのためのデータベース

しかし、FEVERでさえもバイアスがあり思うようにフェイクニュースを発見できていません。

FEVERは機械学習の研究者たちによって、ウィキペディアの記事を元に、情報に対して正誤を判定するために利用されてきました。しかし、そのデータセットにバイアスがありそれで学習したモデルが誤った結果を導いてしまったと研究チームは分析しています。

例えば、'did not''yet to'のような否定のフレーズが含まれた文章は「偽」の場合が多いため、FEVERで訓練されたモデルは、これらの文が実際に真実であるかどうかに関係なく、偽と判定してしまう可能性が高いことが課題です。

真実である"Adam Lambert does not not hide publicly his homosexuality "は、AIに与えられたデータから真実と導けるにもかかわらず、否定のフレーズが入っているので偽とされる可能性が高いです。

判定の根拠に主張の言語(どんなフレーズが入っているか)に焦点を当てており、外部の証拠(実際はどうであるか?)を考慮に入れていないことが問題でしょう。

証拠を一切考慮せずに主張を分類することのもう一つの問題点は、全く同じ主張が今日は真であっても、将来的には偽であると考えられる可能性があるということです。 例えば、女優のオリビア・コルマンがオスカーを受賞したことがないというのは2019年までは本当でしたが、現在では違います。情報は常に更新されていくのです。

これらの課題解決のため、研究チームはFEVERのバイアスを解消し一部を修正するデータセットを作成しています。


計算言語学と機械学習のハイブリッド手法

2018年に発表されたミシガン大学とアムステルダム大学の論文は、効果的にフェイクニュースと戦うために、計算言語学とファクトチェック(事実検証)を組み合わせるアイデアを発表しました。

計算言語学では、自動化された方法でフェイクニュース発見を実施できます。 本物と偽物のニュースを区別するために、言語学的特徴に注目してニュース内アイテムの語彙的、構文的、意味的なレベルを見て判断します。

開発されたシステムの性能は、このタスクにおいて人間の性能に近く、最大76%の精度でフェイクニュースを発見することができました。

しかし、考慮するのは言語学的特徴だけではなく、事実検証の要素も含めるべきと指摘されています。 例えば、記事へのリンク数やコメントなどのメタ特徴や、ニュースページの見栄えなどのモダリティ的な特徴のことです。これらは機械学習でアプローチすることができます。

これらを踏まえて今後の研究では、計算言語学や事実検証(AI・機械学習)のアプローチをハイブリッドにした予測と意思決定が必要だと考えられます。


実現に向けた課題

これらの例を見ただけでも課題があることがわかります。
イノベーターたちは様々な角度から問題を考えてきましたが、思うような改善には至っていません。

どちらの例でも言及されていない課題があります。
フェイクニュースがどのように作られているかご存知ですか。現在はAIがかなり精巧に作成していますが、問題は人間の作るフェイクニュースです。AIはルールに従ってフェイクニュースを作成するため、私たちも対抗することができますが、人間が作成したニュースを見破るためには難易度が一気に上がります。


たとえば、Twitter。


多くの情報を拡散したい時にTwitterは効果的なツールです。
Twitterでフェイクニュースを拡散したい時、複数のBotで自動投稿するでしょう。Botは単に「いいね!」や「フォロー」数を増やしたり、リンクを拡散したり、トレンドに入るために多くの投稿をしたり、反対派を荒らしたりするために構築されます。このように自動化されたアカウントの大部分は非常に単純なもので発見しやすく現在の技術でも対応できるでしょう。

これだけの対策でも、拡散されるフェイクニュースの効果を弱めることができます。 悪意のある情報の拡散は私たちの気持ちを落ち込ませるだけでなく、健全な判断をも奪います。

スクリーンショット 2020-03-26 16.52.10.png


フェイクニュース発見に尽力すべきは誰?

このようなソーシャルメディア上のフェイクニュースの発見は誰が行うべきでしょうか。

FacebookやGoogleなどは暴力やテロリストグループの情報を含むコンテンツの発見には投資していますが、フェイクニュースの発見にはそれほど熱心ではないようです。理由は先程のようにオンライン上には様々な表現、文脈で存在し、AIが独自に発見するは難しいためでしょう。 しかし、今後さらに大量のコンテンツが溢れ、有益な情報のみ吟味するためにはフェイクニュースを発見することは必須ではないでしょうか。


市場のチャンス?

今後、ソーシャルメディアのプラットフォームを牽引する企業は出現するでしょう。
利用ユーザー数を増やし、市場を獲得しするためにはユーザーの安全が確保されることが大切です。子供には使わせられないソーシャルメディアは大人も使いたくないですよね?

ソーシャルメディアの登録者数が世界的に増えているにも関わらず、どのソーシャルメディアのプラットフォームもフェイクニュースの発見に積極投資はしていないようで、技術検証に留まっています。

しかし、より安全で健全な世界のためにこの技術は凄まじい進歩を遂げていくのではないでしょうか。


Twitter・Facebookで定期的に情報発信しています!

ディープラーニングを使って、人の顔の画像を入力すると 年齢・性別・人種 を判別するモデルを作ります。
身近な機械学習では1つのデータ(画像)に対して1つの予測を出力するタスクが一般的ですが、今回は1つのデータ(画像)で複数の予測(年齢・性別・人種)を予測します。


実装方法

学習用データ

まず、学習用に大量の顔画像が必要になりますが、ありがたいことに既に公開されているデータセットがあります。 UTKFace というもので、20万枚の顔画像が含まれています。また、年齢(0-116歳)、人種(白人、黒人、 アジア系、インド系、その他)、性別はもちろんですが、表情や画像の明るさ・解像度も多種多様なものがそろっています。
utkface.png

モデル

次に予測モデルについてですが、Efficient Net という2019/5月に Googleが発表したモデルを使います。このモデルは従来よりかなり少ないパラメータ数ながら、高い精度を誇る優れたモデルです。Kaggleのようなコンテストでも既に多用されていて、上位の人たちの多くが使っています。(参考:このコンテストでは上位陣の多くがEfficient Netを取り入れていました 詳しくは元論文や、その解説記事を参考にしてください。

efficientnet.png

加えて、今回のタスクは1つの入力(顔画像)から3つの出力(年齢・性別・人種)を返す、いわゆる複数出力型(Multi Output)にする必要があることにも注意します。


実装例

プログラミング環境 いくらEfficient Netの計算コストが小さいとはいっても、学習データの数も多く普通のCPUでは時間がかかりすぎてしまいます。専用GPU付PCがあればそれで良いのですが、私はないのでGoogle Colaboratoryのような外部のGPUを使う必要があります。実はKaggleにもGPU提供の機能があり、しかもKaggleの場合、あらかじめデータセットがNotebookに読み込まれている場合があります。つまり、配布元のサイトからデータをダウンロードしてくる必要がありません。今回使うUTKFaceも既に用意されているので、ありがたくこれを使っていきます。

まず、ここに行き、右にあるNew Notebookをクリックします。

how1.png

今回はPythonで実装するので、そのまま createを選択します。しばらくするとデータが読み込まれた状態のNotebookが使えるようになります。これで環境構築は完了です。

この時、図のように、【Settings】の項目のうち、 Internet を On に、Accelerator を GPU に設定 しておきましょう。

how2.png


コード全文

それではいよいよ実装していきます。ここでは、最初にコード全文を載せ、後で詳細に解説していきたいと思います。

# This Python 3 environment comes with many helpful analytics libraries installed
# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python
# For example, here's several helpful packages to load in 

import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)

# Input data files are available in the "../input/" directory.
# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory

import os
for dirname, _, filenames in os.walk('/kaggle/input'):
    for filename in filenames:
        print(os.path.join(dirname, filename))

# Any results you write to the current directory are saved as output.


###### EfficientNetをインストール
! pip install -U efficientnet


###### 必要なライブラリを読み込む
import glob
import matplotlib.pyplot as plt
import seaborn as sns
from PIL import Image

from efficientnet.keras import EfficientNetB4  # Bの後の数字を変えれば別のスケールのモデルを使える
from sklearn.model_selection import train_test_split
from keras.utils import to_categorical

from keras.layers import Input, Dense
from keras.models import Model
from keras.callbacks import ModelCheckpoint


###### 定数を定義
DATA_DIR = '../input/utkface-new/UTKFace'
IM_WIDTH = IM_HEIGHT = 198
TRAIN_TEST_SPLIT = 0.01  # 全体の8割を訓練データ、残り2割をテストデータにする
TRAIN_VALID_SPLIT = 0.7  # 訓練データのうち3割はバリデーションデータとして使う
ID_GENDER_MAP = {0: 'male', 1: 'female'}  # IDから性別へ変換するマップ
GENDER_ID_MAP = dict((g, i) for i, g in ID_GENDER_MAP.items())  # IDと性別の逆引き辞書
ID_RACE_MAP = {0: 'white', 1: 'black', 2: 'asian', 3: 'indian', 4: 'others'}  # IDから人種へ変換するマップ
RACE_ID_MAP = dict((r, i) for i, r in ID_RACE_MAP.items())  # IDと人種の逆引き辞書


###### ファイル名から正解ラベルを取り出す関数
def parse_filepath(filepath):
    # 年齢(int)、性別(str)、人種(str) を返す
    try:
        path, filename = os.path.split(filepath)  # 相対パスからファイル名を取り出す
        filename, ext = os.path.splitext(filename)  # 拡張子を除く
        age, gender, race, _ = filename.split("_")  # _は無名変数
        return int(age), ID_GENDER_MAP[int(gender)], ID_RACE_MAP[int(race)]

    except Exception as e:  # いくつか欠損値があるので例外処理をしておく
        print(filepath)
        return None, None, None


###### 年齢、性別、人種、ファイル名からなるDataFrameを作成
files = glob.glob(os.path.join(DATA_DIR, "*.jpg"))  # 全ての画像ファイル名をfilesという変数にまとめる
attributes = list(map(parse_filepath, files))  # 上で作成した関数にファイル名を一つずつ入力

df = pd.DataFrame(attributes)
df['file'] = files
df.columns = ['age', 'gender', 'race', 'file']
df = df.dropna()  # 欠損値は3つ
df['gender_id'] = df['gender'].map(lambda gender: GENDER_ID_MAP[gender])
df['race_id'] = df['race'].map(lambda race: RACE_ID_MAP[race])

# 10歳以下、65歳以上の人の画像は比較的少ないので使わないことにする
df = df[(df['age'] > 10) & (df['age'] < 65)]
# その中での最高年齢
max_age = df['age'].max()

###### train, test, validationデータの分割
p = np.random.permutation(len(df))  # 並び替え
train_up_to = int(len(df) * TRAIN_TEST_SPLIT)
train_idx = p[:train_up_to]
test_idx = p[train_up_to:]

# split train_idx further into training and validation set
train_up_to = int(train_up_to * TRAIN_VALID_SPLIT)
train_idx, valid_idx = train_idx[:train_up_to], train_idx[train_up_to:]


###### データの前処理を行う関数
def get_data_generator(df, indices, for_training, batch_size=32):
    # 処理した画像、年齢、人種、性別をbatch_sizeずつ返す

    images, ages, races, genders = [], [], [], []
    while True:
        for i in indices:
            r = df.iloc[i]
            file, age, race, gender = r['file'], r['age'], r['race_id'], r['gender_id']
            im = Image.open(file)
            im = im.resize((IM_WIDTH, IM_HEIGHT))
            im = np.array(im) / 255.0  # 規格化
            images.append(im)
            ages.append(age / max_age)  # 最大年齢で規格化
            races.append(to_categorical(race, len(RACE_ID_MAP)))  # kerasの仕様に合わせ、one-hot表現に
            genders.append(to_categorical(gender, 2))  # kerasの仕様に合わせ、one-hot表現に
            if len(images) >= batch_size:  # メモリを考慮して少しずつ結果を返す
                yield np.array(images), [np.array(ages), np.array(races), np.array(genders)]
                images, ages, races, genders = [], [], [], []
        if not for_training:
            break


###### モデルの作成
input_layer = Input(shape=(IM_HEIGHT, IM_WIDTH, 3))  # 最初の層

efficient_net = EfficientNetB4(
    weights='noisy-student',  # imagenetでもよい 
    include_top=False,  # 全結合層は自分で作成するので要らない
    input_tensor = input_layer,  # 入力
    pooling='max')

for layer in efficient_net.layers:  # 転移学習はしない
    layer.trainable = True

# 複数出力にする必要があるので、efficientnetの最終層から全結合層3つを枝分かれさせる
bottleneck=efficient_net.output 

# 年齢の予測
_ = Dense(units=128, activation='relu')(bottleneck)
age_output = Dense(units=1, activation='sigmoid', name='age_output')(_)

# 人種の予測
_ = Dense(units=128, activation='relu')(bottleneck)
race_output = Dense(units=len(RACE_ID_MAP), activation='softmax', name='race_output')(_)

# 性別の予測
_ = Dense(units=128, activation='relu')(bottleneck)
gender_output = Dense(units=len(GENDER_ID_MAP), activation='softmax', name='gender_output')(_)

# efficientnetと全結合層を結合する
model = Model(inputs=input_layer, outputs=[age_output, race_output, gender_output])

# 最適化手法・損失関数・評価関数を定義してコンパイル
model.compile(optimizer='rmsprop', 
              loss={'age_output': 'mse', 'race_output': 'categorical_crossentropy', 'gender_output': 'categorical_crossentropy'},
              loss_weights={'age_output': 2., 'race_output': 1.5, 'gender_output': 1.},
              metrics={'age_output': 'mae', 'race_output': 'accuracy', 'gender_output': 'accuracy'})

# バッチサイズを定義
batch_size = 32
valid_batch_size = 32

train_gen = get_data_generator(df, train_idx, for_training=True, batch_size=batch_size)
valid_gen = get_data_generator(df, valid_idx, for_training=True, batch_size=valid_batch_size)

# 検証誤差が最も低い状態のモデルを保存しておく
callbacks = [
    ModelCheckpoint('./model_checkpoint', monitor='val_loss', verbose=1, save_best_only=True, mode='min')
]

history = model.fit_generator(train_gen,
                    steps_per_epoch=len(train_idx)//batch_size,
                    epochs=10,
                    callbacks=callbacks,
                    validation_data=valid_gen,
                    validation_steps=len(valid_idx)//valid_batch_size)


###### 損失関数、評価関数の値をプロットする関数
def  plot_train_history(history):
    fig, axes = plt.subplots(1, 4, figsize=(20, 5))
    axes[0].plot(history.history['race_output_accuracy'], label='Race Train accuracy')
    axes[0].plot(history.history['val_race_output_accuracy'], label='Race Val accuracy')
    axes[0].set_xlabel('Epochs')
    axes[0].legend()

    axes[1].plot(history.history['gender_output_accuracy'], label='Gender Train accuracy')
    axes[1].plot(history.history['val_gender_output_accuracy'], label='Gener Val accuracy')
    axes[1].set_xlabel('Epochs')
    axes[1].legend()

    axes[2].plot(history.history['age_output_mae'], label='Age Train MAE')
    axes[2].plot(history.history['val_age_output_mae'], label='Age Val MAE')
    axes[2].set_xlabel('Epochs')
    axes[2].legend()  

    axes[3].plot(history.history['loss'], label='Training loss')
    axes[3].plot(history.history['val_loss'], label='Validation loss')
    axes[3].set_xlabel('Epochs')
    axes[3].legend()

plot_train_history(history)


test_gen = get_data_generator(df, test_idx, for_training=False, batch_size=128)
dict(zip(model.metrics_names, model.evaluate_generator(test_gen, steps=len(test_idx)//128)))

test_gen = get_data_generator(df, test_idx, for_training=False, batch_size=128)
x_test, (age_true, race_true, gender_true)= next(test_gen)
age_pred, race_pred, gender_pred = model.predict_on_batch(x_test)

race_true, gender_true = race_true.argmax(axis=-1), gender_true.argmax(axis=-1)
race_pred, gender_pred = race_pred.argmax(axis=-1), gender_pred.argmax(axis=-1)
age_true = age_true * max_age
age_pred = age_pred * max_age

from sklearn.metrics import classification_report
print("Classification report for race")
print(classification_report(race_true, race_pred))

print("\nClassification report for gender")
print(classification_report(gender_true, gender_pred))

import math
n = 30
random_indices = np.random.permutation(n)
n_cols = 5
n_rows = math.ceil(n / n_cols)
fig, axes = plt.subplots(n_rows, n_cols, figsize=(15, 20))
for i, img_idx in enumerate(random_indices):
    ax = axes.flat[i]
    ax.imshow(x_test[img_idx])
    ax.set_title('a:{}, g:{}, r:{}'.format(int(age_pred[img_idx]), ID_GENDER_MAP[gender_pred[img_idx]], ID_RACE_MAP[race_pred[img_idx]]))
    ax.set_xlabel('a:{}, g:{}, r:{}'.format(int(age_true[img_idx]), ID_GENDER_MAP[gender_true[img_idx]], ID_RACE_MAP[race_true[img_idx]]))
    ax.set_xticks([])
    ax.set_yticks([])


###### 最後にモデルを保存する
model.save('my_model.h5')

以上がデータ整形から、モデル構築、学習、予測までの一連のプログラムです。 ただ上記のコードは、データの可視化や、データの分布の分析といった試行錯誤の過程を含めていません。 以降ではこれらも含めて解説していきます。

コード解説

最初から行きましょう。

# This Python 3 environment comes with many helpful analytics libraries installed
# It is defined by the kaggle/python docker image: https://github.com/kaggle/docker-python
# For example, here's several helpful packages to load in 

import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)

# Input data files are available in the "../input/" directory.
# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory

import os
for dirname, _, filenames in os.walk('/kaggle/input'):
    for filename in filenames:
        print(os.path.join(dirname, filename))

# Any results you write to the current directory are saved as output.

この部分は Kaggle のNotebookの最初に必ず書いてあるコードで、単純に numpy, pandas を読み込んだ後、input ディレクトリ内にある、データファイルをすべて書き出すという処理です。

続いて、efficientnet をインストールしてライブラリを読み込みます。

###### 定数を定義
DATA_DIR = '../input/utkface-new/UTKFace'
IM_WIDTH = IM_HEIGHT = 198
TRAIN_TEST_SPLIT = 0.8  # 全体の8割を訓練データ、残り2割をテストデータにする
TRAIN_VALID_SPLIT = 0.7  # 訓練データのうち3割はバリデーションデータとして使う
ID_GENDER_MAP = {0: 'male', 1: 'female'}  # IDから性別へ変換するマップ
GENDER_ID_MAP = dict((g, i) for i, g in ID_GENDER_MAP.items())  # IDと性別の逆引き辞書
ID_RACE_MAP = {0: 'white', 1: 'black', 2: 'asian', 3: 'indian', 4: 'others'}  # IDから人種へ変換するマップ
RACE_ID_MAP = dict((r, i) for i, r in ID_RACE_MAP.items())  # IDと人種の逆引き辞書

ここでは各種定数を定義しています。DATADIR は画像ファイルが入っているディレクトリを指定します。画像は後で前処理をして、IMWIDTH, IM_HEIGHT のサイズにします。 この値は本来注意深く選ぶべきです(EfficientNetの強みが生きるパラメータです)が、今回はとりあえず予測まで実装することが先決なので、適当(テキトー)な値に設定してしまいます。 精度を上げたい場合には見直さなければいけないでしょう。

###### ファイル名から正解ラベルを取り出す関数
def parse_filepath(filepath):
    # 年齢(int)、性別(str)、人種(str) を返す
    try:
        path, filename = os.path.split(filepath)  # 相対パスからファイル名を取り出す
        filename, ext = os.path.splitext(filename)  # 拡張子を除く
        age, gender, race, _ = filename.split("_")  # _は無名変数
        return int(age), ID_GENDER_MAP[int(gender)], ID_RACE_MAP[int(race)]

    except Exception as e:  # いくつか欠損値があるので例外処理をしておく
        print(filepath)
        return None, None, None

データの配布元のwebページを見ればわかるのですが、それぞれの画像ファイルの名前は、 [age][gender][race]_[date&time].jpg となっており、[age] はそのまま 0 ~ 116 までの整数、[gender] は 0 (男性) か 1 (女性)、[race] は 0 (白人) か 1 (黒人) か 2 (アジア系) か 3 (インド系) か 4 (その他--ヒスパニックやラテン系等) となっています。 従って画像ファイル名から、その画像に映っている人の情報を取り出す処理が必要で、それをしているのが上記の部分です。

###### 年齢、性別、人種、ファイル名からなるDataFrameを作成
files = glob.glob(os.path.join(DATA_DIR, "*.jpg"))  # 全ての画像ファイル名をfilesという変数にまとめる
attributes = list(map(parse_filepath, files))  # 上で作成した関数にファイル名を一つずつ入力

df = pd.DataFrame(attributes)
df['file'] = files
df.columns = ['age', 'gender', 'race', 'file']
df = df.dropna()  # 欠損値は3つ
df['gender_id'] = df['gender'].map(lambda gender: GENDER_ID_MAP[gender])
df['race_id'] = df['race'].map(lambda race: RACE_ID_MAP[race])

ここでは取り出した正解ラベルから、分析しやすいようにDataFrame を作成しています。 欠損値については

df.isnull().sum()

で調べることができ、結果は3でした。全体2万枚のうちで欠損値は3枚だけなので今回は考慮しません。

ここで、年齢について考えてみると、高齢者の写真は他の年代に比べて少ないのではないかと推測されます。もしそうであれば学習させるデータに偏りが生じることになり、予測精度が落ちてしまうでしょう。 画像の枚数が各年代で均一になるように画像の水増しをしても良いですが、ここでは簡単のためそういったマイナーな分は捨象することにします。

まず、次のようにして性別・人種ごとの年齢分布を調べます。

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
_ = sns.boxplot(data=df, x='gender', y='age', ax=ax1)
_ = sns.boxplot(data=df, x='race', y='age', ax=ax2)

how04.png

すると、図のような結果になり、多くが10歳から60歳くらいであるとわかります。

年齢だけの分布を見るには

fig = plt.figure()
ax = fig.add_subplot(111)

ax.hist(df['age'], bins=50)
fig.show()

とすればよく、次のグラフが得られます。

how4.png

以上の分析をもとに、10歳以上65歳以下だけ考えることにします(ちゃんと精度を上げたいなら、データの水増しの方が有効でしょう)。それが次の部分です。

# 10歳以下、65歳以上の人の画像は比較的少ないので使わないことにする
df = df[(df['age'] > 10) & (df['age'] < 65)]

次に行きます。

###### train, test, validationデータの分割
p = np.random.permutation(len(df))  # 並び替え
train_up_to = int(len(df) * TRAIN_TEST_SPLIT)
train_idx = p[:train_up_to]
test_idx = p[train_up_to:]

# split train_idx further into training and validation set
train_up_to = int(train_up_to * TRAIN_VALID_SPLIT)
train_idx, valid_idx = train_idx[:train_up_to], train_idx[train_up_to:]

この部分は実際に traintestsplit のように分割を行っているわけではなく、index を振りなおしているだけです。

###### データの前処理を行う関数
def get_data_generator(df, indices, for_training, batch_size=32):
    # 処理した画像、年齢、人種、性別をbatch_sizeずつ返す

    images, ages, races, genders = [], [], [], []
    while True:
        for i in indices:
            r = df.iloc[i]
            file, age, race, gender = r['file'], r['age'], r['race_id'], r['gender_id']
            im = Image.open(file)
            im = im.resize((IM_WIDTH, IM_HEIGHT))
            im = np.array(im) / 255.0  # 規格化
            images.append(im)
            ages.append(age / max_age)  # 最大年齢で規格化
            races.append(to_categorical(race, len(RACE_ID_MAP)))  # kerasの仕様に合わせ、one-hot表現に
            genders.append(to_categorical(gender, 2))  # kerasの仕様に合わせ、one-hot表現に
            if len(images) >= batch_size:  # メモリを考慮して少しずつ結果を返す
                yield np.array(images), [np.array(ages), np.array(races), np.array(genders)]
                images, ages, races, genders = [], [], [], []
        if not for_training:
            break

このこの部分はデータの前処理を行っています。前処理といっても大したことはしておらず、やっていることは、規格化とラベルの表現をone-hotに直すことだけです。 yield を使っているのは、メモリの上限が割と厳しいので、少しずつ渡さないとパンクしてしまうからです。

また、while True: の無限ループは学習実行時は epochs=10 のように同じ処理を繰り返す必要があるため、学習実行時のみ必要です。

続いて、いよいよモデルを構築していきます。 最終的に作りたいモデルは以下の図です。

how5.png

下の枝分かれしている部分(全結合層)は自分で作成し、上の畳み込み部分( EfficientNet )と結合させます。 Kerasには大きく二つの書き方があり、Sequentialモデルと、Functional API と呼ばれています。 Sequentialモデルの方は、

model = Sequential()
model.add(Dense(64, input_dim=100))
model.add(Activation('relu'))

のように、.add()メソッドを使って層を積み重ねていくようにモデルを構築できるので直感的でわかりやすい反面、柔軟性にやや劣り、複数入出力や分岐などを含む、複雑なモデルを構築するのには向いていません。

もうひとつのFunctional API は

inputs = Input(shape=(784,))
x = Dense(64, activation='relu')(inputs)
x = Dense(64, activation='relu')(x)
predictions = Dense(10, activation='softmax')(x)

のような書き方で、層一枚一枚の入出力を指定できる分、自由度の高いモデル構築が可能です。

今回作るものは、分岐が一か所入るだけの、比較的単純なものなのでどちらの書き方でも可能です。コードではFunctional APIで記述しています。

###### モデルの作成
input_layer = Input(shape=(IM_HEIGHT, IM_WIDTH, 3))  # 最初の層

efficient_net = EfficientNetB4(
    weights='noisy-student',  # imagenetでもよい 
    include_top=False,  # 全結合層は自分で作成するので要らない
    input_tensor = input_layer,  # 入力
    pooling='max')

for layer in efficient_net.layers:  # 転移学習はしない
    layer.trainable = True

efficient_net の引数について説明します。 weights は初期状態でのネットワークのパラメータのことです。これはランダムでもよいですが、imagenet という画像データ群で学習させた値を使ったり、noisy-studentという学習法で学習させた値を使ったほうが、一般的に計算時間は短くなります。

include_top は畳み込み層だけでなく、全結合層もefficientnetの物を使うかどうかを決める引数です。今回は分岐という特殊な場合なので自分で作成する必要があります。

また、layer.trainable は転移学習するかどうかを決めます。した方がずっと計算時間は短くなりますが、試したところ精度が悪かったので、今回はすべてのパラメータを学習させます。

# 複数出力にする必要があるので、efficientnetの最終層から全結合層3つを枝分かれさせる
bottleneck=efficient_net.output 

# 年齢の予測
_ = Dense(units=128, activation='relu')(bottleneck)
age_output = Dense(units=1, activation='sigmoid', name='age_output')(_)

# 人種の予測
_ = Dense(units=128, activation='relu')(bottleneck)
race_output = Dense(units=len(RACE_ID_MAP), activation='softmax', name='race_output')(_)

# 性別の予測
_ = Dense(units=128, activation='relu')(bottleneck)
gender_output = Dense(units=len(GENDER_ID_MAP), activation='softmax', name='gender_output')(_)

# efficientnetと全結合層を結合する
model = Model(inputs=input_layer, outputs=[age_output, race_output, gender_output])
この部分は functional API の書き方で全結合層を作成し、efficientnetと結合させています。

注意すべきは次の部分です。

# 最適化手法・損失関数・評価関数を定義してコンパイル
model.compile(optimizer='rmsprop', 
              loss={'age_output': 'mse', 'race_output': 'categorical_crossentropy', 'gender_output': 'categorical_crossentropy'},
              loss_weights={'age_output': 2., 'race_output': 1.5, 'gender_output': 1.},
              metrics={'age_output': 'mae', 'race_output': 'accuracy', 'gender_output': 'accuracy'})

全結合層が3つある分、損失関数や評価関数も3つずつ定義する必要があります。 年齢の予測は回帰問題なので、平均二乗誤差、性別と人種は分類問題なので categorical cross-entropy を損失関数に使えばよいでしょう。

続く部分はバッチサイズを定義し、データを作成しています。 バッチサイズを大きくすると収束性が良くなりますが、やりすぎるとメモリがパンクするので注意しましょう。 batch_size = 64 だとうまくいかないと思います。

次です。

# 検証誤差が最も低い状態のモデルを保存しておく
callbacks = [
    ModelCheckpoint('./model_checkpoint', monitor='val_loss', verbose=1, save_best_only=True, mode='min')
]

callbacks という便利な機能を使います。これは validation data の損失関数を監視し、それが最小であったepochでのモデルを保存しておいてくれる機能です。 これにより過学習を防ぐことができます。

そして次の部分で学習を実行します。

history = model.fit_generator(train_gen,
                    steps_per_epoch=len(train_idx)//batch_size,
                    epochs=10,
                    callbacks=callbacks,
                    validation_data=valid_gen,
                    validation_steps=len(valid_idx)//valid_batch_size)

私の場合は40分ほどかかりました。気長に待ちましょう。

学習が済んだら損失関数と評価関数の値をグラフに表して学習がうまくいったかどうか確認します。

def  plot_train_history(history):
    fig, axes = plt.subplots(1, 4, figsize=(20, 5))
    axes[0].plot(history.history['race_output_accuracy'], label='Race Train accuracy')
    axes[0].plot(history.history['val_race_output_accuracy'], label='Race Val accuracy')
    axes[0].set_xlabel('Epochs')
    axes[0].legend()

    axes[1].plot(history.history['gender_output_accuracy'], label='Gender Train accuracy')
    axes[1].plot(history.history['val_gender_output_accuracy'], label='Gener Val accuracy')
    axes[1].set_xlabel('Epochs')
    axes[1].legend()

    axes[2].plot(history.history['age_output_mae'], label='Age Train MAE')
    axes[2].plot(history.history['val_age_output_mae'], label='Age Val MAE')
    axes[2].set_xlabel('Epochs')
    axes[2].legend()  

    axes[3].plot(history.history['loss'], label='Training loss')
    axes[3].plot(history.history['val_loss'], label='Validation loss')
    axes[3].set_xlabel('Epochs')
    axes[3].legend()

plot_train_history(history)

loss1.png

epoch2.png

epoch 8 で何やら起こっていますが他の部分でも変動が激しいことからも確率的に起こりうることなのかもしれません。 また、特に性別と人種の分類において、かなり過学習が起こっていることが見て取れます。

最後に、各種精度に関係する値を出力し、テストデータについても予測します。

test_gen = get_data_generator(df, test_idx, for_training=False, batch_size=128)
dict(zip(model.metrics_names, model.evaluate_generator(test_gen, steps=len(test_idx)//128)))

test_gen = get_data_generator(df, test_idx, for_training=False, batch_size=128)
x_test, (age_true, race_true, gender_true)= next(test_gen)
age_pred, race_pred, gender_pred = model.predict_on_batch(x_test)

race_true, gender_true = race_true.argmax(axis=-1), gender_true.argmax(axis=-1)
race_pred, gender_pred = race_pred.argmax(axis=-1), gender_pred.argmax(axis=-1)
age_true = age_true * max_age
age_pred = age_pred * max_age

from sklearn.metrics import classification_report
print("Classification report for race")
print(classification_report(race_true, race_pred))

print("\nClassification report for gender")
print(classification_report(gender_true, gender_pred))

import math
n = 30
random_indices = np.random.permutation(n)
n_cols = 5
n_rows = math.ceil(n / n_cols)
fig, axes = plt.subplots(n_rows, n_cols, figsize=(15, 20))
for i, img_idx in enumerate(random_indices):
    ax = axes.flat[i]
    ax.imshow(x_test[img_idx])
    ax.set_title('a:{}, g:{}, r:{}'.format(int(age_pred[img_idx]), ID_GENDER_MAP[gender_pred[img_idx]], ID_RACE_MAP[race_pred[img_idx]]))
    ax.set_xlabel('a:{}, g:{}, r:{}'.format(int(age_true[img_idx]), ID_GENDER_MAP[gender_true[img_idx]], ID_RACE_MAP[race_true[img_idx]]))
    ax.set_xticks([])
    ax.set_yticks([])

err1.png

err2.png

f1- score が大まかな指標になります。人種については80%の確率、性別については97%の確率で正解していることが分かります。また、学習時と比べると、過学習の傾向が強いこともうかがえます。 人種に関しては、ラベル4、すなわち 「その他の人種」についての予測が壊滅的にできていないことが分かります。

続いてテストデータのサンプルです。上が予測値、下が実際の値です。

face1.png face2.png

チューニングの余地がある割にはある程度予測できています。

何人か知っている人についても予測してみました。

sample1.png sample2.png

あれ.........

まとめ

今回は顔の画像から、年齢・性別・人種を同時に推定するモデルをEfficient Net を使って作りました。 今回の例のようなマルチタスク処理は、シングルタスクの精度を向上させる際にも使われることもあり、有用なので是非利用してほしいと思います。 ただ、本来EfficientNetは画像の解像度を畳み込み層の深さ・大きさと共に調節すべきものであり、今回の処理ではそれを省いているので制度は出にくい状態です。 また、画像認識の大変なところはパラメータを調節して精度を上げていくところにこそあるので、次回はこのモデルをチューニングし、過学習を抑えたりしてより精度を上げていこうと思います。

参考となるリンク先


Twitter・Facebookで定期的に情報発信しています!

Googleが発表したBERTは記憶にも新しく、その高度な性能はTransformerを使ったことで実現されました。
TransformerとBERTが発表される以前の自然言語処理モデルでは、時系列データを処理するRNNとその発展形であるLSTMが使われてきました。このLSTMには、構造が複雑になってしまうという欠点がありました。こうしたなか、2017年6月に発表された論文「Attention is all you need」で論じられた言語モデルTransformerとAttentionと呼ばれる手法は、LSTMのような複雑な構造を使わずに高性能を実現したのでその後の言語モデル開発に大きな影響を与えました。 今回は転移学習モデルTransformerを用いた新しいモデルのText-to-Text Transfer Transformerを紹介します。


Text-to-Text Transfer Transformer(T5)とは

 近年、自然言語処理の分野では、事前学習モデルを利用しfine tuningをする転移学習(transfer learning)が強力な技術として様々なタスクで少ないデータセットでも精度向上をもたらしています。特に2018年に発表されたBERT以降、研究が盛んに行われており、ベンチマーク(GLUEなど)のSoTAも頻繁に更新されています。この論文に「多様なアプローチ、手法、実践がなされている」と書かれているように、それぞれの研究によってアプローチのしかたも異なります。  その中で、この論文で紹介されているモデルT5は「Text-to-Text Transfer Transformer」の略で、Text-to-Textとある通り、入力と出力の両方をテキストのフォーマットに統一して、転移学習を行うモデルです。
Figure1.png

 上図にあるように、翻訳、質疑応答、分類、要約などすべてのタスクで入力をテキストで受けて、出力もテキストの形で返しています。また、このモデルの特徴は一つのモデルで上で挙げたようなタスクをすべてこなせることです。実際にタスクを行わせる際には上の図にあるように"translate English to German:"とPrefixを与えてどのタスクかを知らせています。T5のモデル構造のベースはTransformerとなっていて、論文中でも特別新しい手法を紹介しているわけではありません。転移学習における研究が盛んに行われ、異なる手法の比較が難しい中で、どんなモデル構造やデータセットなどを用いれば良いのかを、T5を用いて比較していくことがこの論文の中心となっています。


精度比較

 それでは論文中で行われている実証研究について見ていきます。


Baseline

 まずベースラインについて見ていきます。

 事前学習どの程度行ったなどの詳細はここでは述べませんが、基本的なモデルの構造としては一般的なTransformerを用いて、特徴的なのはすべてのタスクがtext-to-textの形式にされていることです。また事前学習にはC4(Colosal Clean Crawled Corpus)というデータセットを使っています。後にデータセットでの精度比較があるのでC4の詳細はそこで述べます。
Figure2.png

教師なし学習の目的関数ついては、BERTで用いられたMasked Language Modelingなどに倣った"denoiding objective"を使用しています。上の図を見るとイメージしやすいと思います。
Table1.png

 ベースラインの性能を簡単に表で見ていきます。一番上がベースラインの結果の平均、2番目が標準偏差、最後が事前学習を行っていないモデルの結果となっています。この結果の中で、GLUEとSQuADに関してはBERTのモデルと非常に近いスコアを出しているそうです。またEnFr(英語からフランス語への翻訳)に関しては、十分に大きな訓練データがあるために、事前学習で得られる情報が重要ではなくなっているため、ベースラインのスコアと事前学習をしなかったモデルのスコアがあまり変わらないという結果が出ています。

それではここからモデル構造などを変えての比較を見ていきます。


モデル構造

 モデルのベースは上でも述べたようにTransformerで、今回の比較は次の三つについて行っています。

  • Encoder-Decoder:基本的なTransformerで採用されているモデル  Encoderはfully-visible attention mask(全ての入力を出力の予測に用いるマスクになっている)で、 Decoderはcasual attention mask(予測する単語を見えないようにしている)を採用したモデル       
  • Language Model:Encoder-DecoderでのDecoder部分のみを使ったようなモデル
  • Prefix LM:Language Modelをベースに、Prefix部分はマスクしないという変更を与えたモデル

以下の図がそれぞれのモデル構造のイメージ図になっています。
Figure4.png

 また、attention maskのイメージ図は下のようになっています。
Figure3.png

Transformerの詳細については、【論文】"Attention is all you need"の解説をご覧ください。検証結果は以下のようになります。
Table2.png

ここで教師なし学習の目的関数として、ベースラインと同様のdenoisingだけでなく、LM(通常の言語モデルで予測)も採用しています。また、モデルの構造で上の三つの他に"Enc-dec,shared"と"Enc-dec,6 layers"があります。Enc-dec,sharedはencoderとdecoderでパラメータを共有したもので、Enc-dec,6 layersはencoderとdecoderの層をそれぞれ12から6にして、パラメータを半分にしたもので、計算コストも半分になっています。それぞれのイメージ図は以下のようになります。

  • Enc-dec,shared
    enc-dec_share.png

  • Enc-dec,6 layers
    enc_dec_6layer.png

 結果を見てみると、まず目的関数については全体を見てもDenoisingのほうが良い結果を得ています。モデル構造については、Encoder-decoderが一番良い精度を出しています。Enc-dec,sharedはほとんど変わらず、パラメータを共有するしないは精度にあまり影響を及ぼさないことが分かり、Enc-dec,6 layersはその2つと比べて性能が劣り、層の数はある程度影響を与えています。また、Language ModelとPrefix LMもEncoder-decoderよる精度はわるくなっていて、2つを比べるとPrefix LMのほうが良い結果になっていてます。


Objectives

 次に教師なし学習の目的関数について比較を行っていきます。
Figure5.png

ここでは、上の図の左から順にそれぞれ検証していきます。下のような目的関数の例も記載されているので、逐次見ていきます。この例の元の文は"Thank you for inviting me to your party last week."です。
Table3.png

High-Level Approaches
 ここで比較するのは次の三つの目的関数です。
Table3_1.png

  • Prefix language modeling :オリジナルの文章の途中までを入れて、その続きの文章を予測
  • BERT-style:一部の単語がマスクトークンに置き換えられた文章から、オリジナルの文章を予測
  • Deshuffling:単語がランダムにシャッフルされた文章から、オリジナルの文章を予測

Table4.png  結果をみると、BERT-styleが、翻訳タスクではPrefix language modelingと大差ないものの、全体で見ると一番優れていることが分かります。

Corruption Strategies
 上の結果から、BERT-styleが優れていることが分かりました。ここでは、そのBERT-styleをベースとして、下の例のような三種類のトークンの入れ方を比較します。
Table3_2.png

  • mask tokens:一部の単語がマスクトークンになっている文章から、全文を予測
  • replase tokens:一部の単語がマスクトークンになっている文章から、マスクされた部分のみを予測
  • drop tokens:一部分が抜かれた文章から、抜かれたところのみを予測

 また、下の表中のMASS-styleは、BERT-styleに似た方式のものだそうです。詳細はMASS: Masked Sequence to Sequence Pre-training for Language Generationをご覧ください。
Table5.png  結果を見てみると全体的に似たようなスコアを出していて、特別優れているものはありません。ただ、BERT-styleとMASS-styleは全文を予測する目的関数なのに対して、replace tokenとdrop tokenはマスクされた部分のみを予測するので、より短い時間で訓練可能となり、その点でいうと優れていると言えます。また単純に一番良いスコアを出した数でいうと、drop tokenを使用したものになりますが、SuperGLUEでは、replace tokenのほうが良い結果を出していて、この2つのことからreplace tokenを用いるのが一番良い手法だと結論付けています。

Corruption Rate
 次にマスクする割合を10%,15%,25%,50%と変えて比較します。
Table6.png  結果を見てみると、それぞれであまり大きな精度の違いは見られず、マスクする割合はモデルの性能に大きな影響を与えないということが分かります。ただし、50%に関しては特にGLUEとSGLUEで精度が悪くなっており、マスクする割合が大きすぎると、モデルの性能に悪影響を与えてしまうことが分かります。このことから、従来の研究に沿ってBERTでも採用されている15%が適切としています。

Corrupted Span Length
 次に、マスクするトークンの平均の長さを変えて比較します。
Table7.png

 結果を見ると、10の場合はあまり良くなっていないので、長すぎると性能が下がっていくことが分かります。ただ、それ以外は、あまり性能に差はなく、ベースラインのものをそのまま採用することにしています。

結論
 ここまで、目的関数に関する4つの項目について比較を見ました。結果的に上で示した図のフローになります。   この検証で一番モデルの性能に影響を与えたのは、最初に見た3つ目的関数の選択でした。性能だけを見ると他の要素はあまり重要でないように感じますが、マスクトークンの取り方で、予測する文・単語は短い方が学習にかかる時間が短く、計算コストも抑えられることも大切なポイントになります。


Dataset

 次に、使うデータセットを変えることでの性能の違いを見ていきます。まず、使用するデータセットについて、T5で重要となるC4について説明したいと思います。

C4(Colosal Clean Crawled Corpus)
C4はColosal Clean Crawled Corpusの略で、Webから取得できるCommon Crawlを元に以下の前処理したものです。

  • ピリオド、クエスチョンマーク、ビックリマーク、コーテーションマークで終わる文のみを使用する。
  • 汚い言葉、不適切な語を含むページは取り除く。
  • javascriptの単語を含む行は取り除く。
  • ダミーテキストがあるページは取り除く。
  • ソースコードなどは取り除く。
  • 重複文は取り除く。

C4の一番の特徴は、データのサイズがかなり大きいことです(データが多様)。Common Crawlが1か月に20TBになるようなデータで、ここでののC4は前処理をすることで、750GBにしたデータセットです。これは結果の表にも書いてありますが、他のデータセットに比べてかなり大きなデータとなっており、ここでの比較により、データサイズによりどんな違いが出るのかを見ることができます。

比較の結果は以下のようになります。
Table8.png

 まず、C4とC4,unfiltered(前処理をしていないC4データセット)を比べると、当たり前ですがC4のほうが精度が良く、前処理が重要であることが分かります。  次に、C4と他のデータセットを比べると、タスクによって精度の良いデータセットが違っているように感じます。まず分かることは、データのサイズが単純に大きいだけでは、必ずしも精度は上がらないことです。また、このような結果になった要因として、使ったデータセットがあるタスクに適応しやすいデータだったということが挙げられます。このことから、それぞれのタスクに対して適したデータセット、ドメイン固有のデータセットを使ったほうが精度が高くなることも確認できます。  また一般的にドメイン固有のデータセットのサイズは小さくなりますが、そういったサイズの小さいデータを繰り返し学習させるのと、より大きな多様性のあるデータを繰り返さずに学習させるのでは、どちらが良いのかを検証したのが、次の表とグラフです。
Table9.png

Figure6.png

 結果を見ると、データの大きさを小さくして、リピートの回数を増やすほど、Training lossの収束が速くなるものの、精度が低くなっていることが分かります。どんどん過学習になりやすくなっているということです。このことから、可能であればより大きなデータセットを使って、データに多様性を持たせたほうが良いことが確認できます。


Fine-tuning

 次に、fine-tuningの仕方について以下の3つを比較しています。

  • All parameters:モデルのすべてのパラメータをfine-tuningして調節する
  • Adapter layers:事前学習のモデルを壊さないで保持するために、Dense + ReLU + Denseの層からなるAdapter layerを各層の間に入れてfine-tuningする
  • Gradual unfreezing:徐々にチューニングするパラメータを増やして学習範囲を広げていく   結果は、下のようになり従来の手法の通り、全てのパラメータをfine-tuningしたほうが精度が高くなっています。
    Table10.png


Multi-task

 次に、Multi-taskという名の通り、まとめて一度に様々なタスクを学習させることにより、精度がどのように変化するかを検証していきます。つまり、普通はあるタスクに対してひとつの教師なし学習を行わせるのに対して、タスクをミックスさせることにより、全てのタスクで同じパラメータを共有するということになります。  ここで比較するのは、

  • Equal:全てのタスクを同じ割合で学習させる方法
  • Examples-proportional:各タスクのデータのサイズに上限Kを与えて、その中でランダム得たデータを学習させる方法
  • Tempereture-scaled:一番でデータの少ないタスクと一番データの多いタスクの差に制限をかけたデータで学習させる方法

Table11.png

 結果を見ると、タスクごとに教師なし学習により事前学習+fine-tuningしたのに比べて、全体的に性能は劣っていて、特にEqualのときが一番悪くなっていて、GLUE、SGLUEのタスクに関してはすべて良い性能が出ていません。ただし、Examples-proportionalとTempereture-scaledについては、パラメータをうまく調節できた場合に限って、CNNDM、SQuADなどで精度が良くなっていることが分かります。  次に、ここで分かった性能の差を埋めることができないかということで、multi-taskとfine-tuningの様々な組み合わせ方について検証していきます。 ここで比較する手法は、通常の事前学習+fine-tuningとMulti-task含めて5つあります。

  • Unsupervised pretrining + fine-tuning
    multi1.png

  • Multi-task
    multi2.png

  • Multi-task pre-training + fine-tuning:すべてのタスクを事前学習させる方法
    multi3.png

  • Leave-one-out multi-task training:1つのデータを除いたもので事前学習を行い除いたタスクでの性能を図る方法
    multi4.png

  • Supervised multi-task pre-training:教師あり学習のみを事前学習させる方法
    multi5.png

Table12.png  結果をみると、Multi-task pre-training + fine-tuningによって性能の差を埋めることは出来ました。また、Leave-one-out multi-task training性能がそこまで下がっていないことから、様々なタスクに対して事前学習+fine-tuningをすると新しいタスクに対して、ある程度対応できる可能性を示しています。そして、Supervised multi-task pre-trainingの結果を見ると、翻訳のタスクのみ良い性能を示していることから、教師なし学習による事前学習は、それ以外のタスクに重要な影響を与えていることが分かります。


Scaling

 最後に、学習ステップ数・バッチサイズ・モデルの大きさ・アンサンブルについて比較を行っています。
Table13.png  結果を見ると、ベースラインと比較して、それぞれ大きくすることで精度が良くなっていることが分かります。予想できた結果ですが、より大きなモデルを使って、学習もそれなりに行ったほうが良いことが確認できます。


実験のまとめ

 最後に、以上の実験から得た結果を反映したモデルの性能を、様々なベンチマークで検証した結果を見てみます。
Table14.png それぞれのモデルのパラメータ数はこちらです。

  • T5-Base : 220million
  • T5-small : 60million
  • T5-Large : 770million
  • T5-3B : 2.8billion
  • T5-11B : 11billion

 今までの検証からも予想できるように、パラメータ数の多いもののほうが性能が良くなっています。また、様々なベンチマークでSoTAを獲得できていることから、検証して得た結果は正しかったことが分かります。ただし、翻訳タスクに関しては、事前学習に英語のみのデータセットを使ったために、これまでのSoTAには届いていないようです。  それぞれのベンチマークによる考察は長くなるので省きますが、興味があれば是非論文を読んでみてください。


まとめ

 今回はT5の論文について紹介しました。T5モデルのポイントはText-to-Textの形式を採用したこととC4というかなり大きなデータセットを使ったことですが、NLP分野は研究が盛んで次々に新たなモデルが発表されているので、整理するという意味でも、こののように検証を行っていくことも今後重要になってくると思います。


参考文献

最近はGoogleを始めとする翻訳サービスにも機械学習が取り入れられ、翻訳精度が向上しています。

しかし、完璧な翻訳を求めるには精度が足りず、確認作業に時間がかかったり、翻訳されたものが正しいのか見極めるスキルが必要なケースがほとんどです。

このような課題がある中、高精度な翻訳ができる「DeepL」が、日本語と中国語の翻訳に新しく対応したので、日本語での翻訳機能を試してみました。


DeepLとは

DeepLはドイツのケルンで開発された深層学習(ディープラーニング)を用いた人工知能(AI)による翻訳システムです。以前から英語・オランダ語・フランス語・ドイツ語・イタリア語・ポーランド語・ポルトガル語・ロシア語・スペイン語などの言語に対応していましたが、2020年3月19日から日本語と中国語にも対応したと発表されました。

DeepL翻訳が日本語と中国語を習得
https://www.deepl.com/blog/20200319.html

2020年初めにDeepL翻訳はニューラルネットワークの大幅な改善を行い、日本語と中国語の翻訳精度が向上しました。日本語と中国語の翻訳精度を他翻訳と比較したグラフです。
DeepL


Google翻訳と性能比較

DeepLではどの程度の翻訳ができるのでしょうか。
AIができるコロナウイルス対策について紹介している文章の冒頭を翻訳しました。
Fighting the Spread of Coronavirus with Artificial Intelligence
https://tractica.omdia.com/artificial-intelligence/fighting-the-spread-of-coronavirus-with-artificial-intelligence/

DeepL

ほとんど完璧な翻訳です。Google翻訳と比較してみましょう。
前半はほぼ同様の訳のため割愛し、後半のHowever以下を掲載します。少し苦戦しているようです。
DeepL

Google翻訳では訳しきれていない部分があります。その他にも理解はできますが、やや首を傾げる箇所もあり、この文章ではDeepLの方がスムーズな翻訳ができていることが分かります。


機械学習、深層学習は学習のために翻訳前後をセットにして学習させ、精度を向上していきます。 今後も更に学習を進め、精度向上していくでしょう。


Twitter・Facebookで定期的に情報発信しています!

NCAAコンペ概要

 全米大学体育協会バスケットボールトーナメントの試合の勝敗を予測するコンペでした。男女別にコンペが開かれました。リーグ戦の試合結果の詳細とトーナメントの試合結果のデータが年ごとに与えられ、今年のトーナメントの試合結果を予測します。評価指標はLoglossでした。


結果

 新型コロナウイルスの影響で、大会自体がキャンセルになってしまいました。リークなしのLBの最も良いスコアは0.52586です。


取り組み内容

コンペの内容を理解してから

 LBの順位が参考にならないということを一番意識しなければならないと感じました。
というのも、LBは2015~2019年の予測のスコアなのですが、その答えはすでに与えられたデータに入っているため簡単にスコアを0にすることができ、リークに気を付けないと簡単に誤ったスコアが出てしまいます。
どのコンペでもCV(Cross Validation)は重要ですが、今回は特に必要でした。公開されているノートブックにもリークをしたものが多かったため、もしコンペが中止にならなければかなりのshakeが起きていたと思います。しかし、リークを防ぐことに関するディスカッションもいくつかあり、そこに注意できている参加者もいました。
また、過去数年間は毎年NCAAコンペは開かれているため、それらの上位成績者の解法を読み参考にしました。しかし、一貫した特徴はなく様々な解法であった為、自分なりの方法を考える必要がありました。


前処理 • 特徴量エンジニアリング

 基本的には、リーグ戦の合計得点などの試合の詳細データをチームごとに集計し、それを特徴量としました。
また、与えられているデータにチームのランキングなどもあったため、欠損値を補完しながら特徴量に加えました。Kenpom.comという、リーグとトーナメントのデータを集計しているサイトがあり、その独自の集計方法が特徴量として使えそうであったためスクレイピングをしたのですが、トーナメントのデータをリークしているためそのまま使うことはできず、自分でコーディングして作り直しました。
このうちのピタゴラス勝率やポゼッション率は比較的重要な特徴量となりました。また、各チームのプレースタイルの特徴を掴む為、チームごとのリーグ戦の試合内容に対してPCA分析をしてその結果を加えるといったこともしました。特徴量選択はまだしていませんでした。


CV(Cross Validation)

 交差検証の仕方についてですが、2014年までのデータ12年分を用い12FoldのGroupKFoldで行いました。去年、一昨年などの戦績を反映した特徴量を作っていないため、リークは起きていないと思います。年によってValidationのスコアが全然違うことから、やはりスポーツの予測は難しいなということを感じました。ジャイアントキリングの多く起こった年のスコアはかなり悪くなってしまいます。


モデリング

 LightGBM、CatBoost、DNNのアンサンブルです。シングルモデルのスコアにそれほどの違いはなかったのですが、出力の分布は大きく違い、アンサンブルをすることでスコアを向上することができました。僕の場合は、LightGBM、CatBoost、DNNの配分を、3:2:5にした場合が最もスコアが良くなりました。
XGBoostは他のモデルに比べスコアが良くなかったため使いませんでした。ハイパーパラメータチューニングはまだしていなかったため、これをするとさらに良くなったかもしれません。


まとめ

 コンペ自体がキャンセルになってしまい非常に残念です。しかし、今までしっかりできていなかった、シングルモデル作成→複数モデル作ってアンサンブル の流れに慣れてきたという点や、LBの順位が全く信用できない中でCVだけを頼りに取り組むという点においては学びが多く、良かったと感じています。来年はコロナウイルスの影響も収まりコンペがまた開かれると思うので、その時に今回の取り組みの成果を出したいです。

 


Twitter・Facebookで定期的に情報発信しています!

サービスへのお客様の評価はその場では気付きにくく、特にネガティブなものは直接伝えてはくれません。

しかしお客様の声を知ることはより満足してもらうためには必須です。
今回は口コミサイトに投稿されたレビューを分析し、お客様の本当の声を知るためのサービスを紹介します。

0.サービス紹介_口コミ分析

Web上で集めた口コミ(レビュー)をAIが精査し、ネガティブな口コミはネガティブな原因を特定します。

数が少ないうちは手作業で評価の精査が出来ますが、数が多くなってくるとそういう訳にもいきません。
大量の口コミを一から全て見ていくとなると大量の人手、時間がかかります。

そのコスト削減に向けて口コミ文章をAIに評価させネガティブなものだけを選別し、改善のための時間を創出しましょう。

前回のブログでosetiというライブラリを用いて口コミをネガポジ分析しましたが、これには問題点がありました。

  1. 日本語評価極性辞書に載っていない単語が出現した際、それらを定量的に評価できない。
  2. 極性辞書の単語の評価には作成者の感情が入っているので、客観的な評価が完璧にできない。
  3. 1文ごとにネガポジ判定を行うので、文章全体で見たときに文脈を読み取れない。


特に3.について、1つの口コミ全体で見た時にそれがかなりポジティブなものであっても、トータルで見た時に「かなり」の部分をAIは読み取れませんでした。 また、全体的にポジティブなレビュー(=口コミ) でも、一部ネガティブな内容が含まれているケースもあります。

このような "ポジティブ寄りのレビュー" 中に含まれるネガティブな内容について、このように仮定しています。
ポジティブ寄りのレビューにもネガティブな内容を含んでいるものがあり、「自店のネガティブなイメージを発見したい」という目標を達成するためには、これらも発見しなければなりません。 そこで、図のような関係があると仮定し、今回はネガティブ寄りのレビューを発見していくことにします。

ブログbert1.png


1.口コミの抽出

ランダムに抽出した東京都内にあるラーメン店で、約800件のレビューをGoogle口コミから抽出しました。一部です。
ブログbert2.png

このように約800件のレビューを抽出し、ポジティブは「1」ネガティブは「0」とラベリングを行いました。


2.そもそもBERTとは?

ではBERTにこれらのデータを学習させ、評価をしていきましょう。BERTについて簡単に説明をします。

BERT

BERT ( Bidirectional Encoder Representations from Transformers )は2018年にGoogleが発表したNLPモデルであり、その翌年には検索エンジンにも導入されました。この導入に対しては「過去最大のアップデート」と呼ばれ、メディアにも大きく取り上げられました。

このBERTの特徴はなんといっても「(文章における) 文脈を理解できる 」ことでしょう。

BERTが発表される以前のNLPモデルでは、「魚介じゃないラーメン」と「魚介 ラーメン」がほぼ同じように認識されていました。 これまでのモデルは「魚介」「じゃない」「ラーメン」と個別に理解できることは可能でしたが、「じゃない」という単語が「魚介」にかかっていることを認識できずに、結果文章の中で意味が明確な「魚介」「ラーメン」の二語が強調されてしまうことが原因でした。

しかしこのBERTでは、「魚介じゃないラーメン」のうち、「じゃない」という単語が「魚介」にかかるという文法上の構造を理解することができるのです。 このようなBERTの処理能力の高さは、今回例にした「魚介じゃないラーメン」のような短いワード以上に、「銀座駅で10分以内に魚介じゃないラーメンを食べたい」などの文章となった場合に、より力を発揮すると推測されます。
Googleが導入したBERTとは?誰でもわかるBERTの特徴を解説より引用

このBERTについての詳しいアルゴリズムについては、本記事のレベルを逸脱するため割愛します。(7.参考文献を参照)


3.口コミ分析の実装

BERTについては、こちらのサイトにあるBERT日本語Pretrainedモデルを用い、コーディングはBERTを用いたネガポジ分類機の作成を参考に実装しました。

この日本語Pretrainedモデルは、日本語全てのWikipediaの文章約1,800万文のテキストから、32,000語の語彙を事前学習したモデルです。

未知語抽出によるデータの前処理

この事前学習済みモデルはWikipediaの文章から単語を学習しているため、「おいしかった」「不快だった」などの感情を表す客観的な言葉が未知語として認識されています。そのため、未知語を抽出しvocab2というBERT語録辞書に入っている意味の似た単語と未知語を交換します。
例えば、「めっちゃ」を「とても」に、「不快だった」を「悪かった」などといったように変換していきます。

import re
replaced_pos = []
replaced_neg = []

for i in range(len(pos)):
  replaced_pos.append(re.sub(r'おいしい', 'うまい', pos[i]))

for i in range(len(neg)):
  replaced_neg.append(re.sub(r'不味い', 'ひどい', neg[i]))

for i in range(len(neg)):
  replaced_neg[i] = re.sub(r'おいしい', 'うまい', replaced_neg[i])

for i in range(len(pos)):
  replaced_pos[i] = re.sub(r'らーめん', 'ラーメン', replaced_pos[i])

for i in range(len(neg)):
  replaced_neg[i] = re.sub(r'らーめん', 'ラーメン', replaced_neg[i])

. . .

レビューの評価に影響するであろう「味」「接客態度」「店内の雰囲気(衛生面など)」の3つに注目し変換しました。

サンプルの文章による推論とAttentionの可視化

レビューの評価にあたりAIが注目した箇所を色付けします。
前述したPretrainedモデルの utils/predict.py に学習済みモデルのビルド( buildbertmodel )と推論( predict )のメソッドを定義してあるので、 これらを利用してサンプルの文章をインプットし、予測値(Positive or Negative)とAttentionを可視化します。

from utils2.config import *
from utils2.predict import predict, create_vocab_text, build_bert_model
from IPython.display import HTML, display

input_text = "サンプルの文章を入力"
net_trained = build_bert_model()
html_output = predict(input_text, net_trained)
print("======================推論結果の表示======================")
print(input_text)
display(HTML(html_output))

結果は以下のようになります。(例としてPositiveとNegativeを1つずつ)

attention.png ブログbert3.png

ここで[UNK]は未知語を、[CLS]は文の開始を表しています。また、Attentionの重み値が大きいほど背景色が濃い赤で表示されています。Attentionによって、AIは判定に必要であろう単語に"注目"していることが分かります。
Attentionについては参考文献でも紹介しています。


4.結果及び考察

最後にテストデータで実際に判定をします。 今回は全てのデータを「訓練データ:テストデータ=7:3」に分け、ハイパーパラメータ(バッチサイズ、エポック)は適宜変更して学習させていきます。

バッチサイズを8、16、32としそれぞれエポックを1~100まで設定した結果は以下のようになりました。

  • 正解率 : 全サンプルのうち、正解したサンプルの割合
  • 適合率(精度) : positiveと予測された中で、実際にpositiveであった確率
  • 再現率 : 実際にpositiveであるデータに対して、positiveと予測された確率
  • F値 : 適合率と再現率の調和平均

バッチサイズ8(1).png バッチサイズ16(1).png バッチサイズ32(1).png

全体として適合率は90%前後と高い結果です。かなりの高精度でネガティブなレビューを抽出できています。(ネガティブが抽出できるということはポジティブも自ずと抽出できています。)

バッチサイズが8の時は再現率に波があり、エポック数を増やしても再現率が40%を下回るときがありました。そこでバッチサイズを16に変更したところ、エポック数の増加に伴い再現率もかなり向上しました。 次にバッチサイズを32として学習を進めると、エポック数45までは再現率70%前後でその後急低下、再び上昇し最終的には90%近くまで上がるという興味深い結果が得られました。 一見するとバッチサイズ16の時が一番学習が上手くいくように見えますが、3つのバッチサイズでは全体的に最終的なF値は90%前後で頭打ちとなる結果となりました。


参考までに訓練データに対する損失と正解率も見てみましょう。

  • trainloss : 訓練データの損失(学習の時点でほぼ0)
  • trainacc : 訓練データの正解率(学習の時点でほぼ1)
  • valloss : バリデーションデータの損失(低い方が良い)
  • valacc : バリデーションデータの正解率(高い方が良い)

バッチサイズ8(2).png バッチサイズ16(4).png バッチサイズ32(2).png

trainlossとtrainaccについては、訓練データで学習を行っているので自明の結果といって良いでしょう。 バリデーションデータの損失の山になっている(急上昇している)ところでは、それに対応して再現率は下がっていることが分かります。学習がうまく出来ていないということです。

5.【参考】口コミのグルーピング

今回の目的であったネガティブな口コミの選定は達成できることがわかりました。次にネガティブなレビューの原因を特定しましょう。
「clerk(店員の態度)」「shop(店内の雰囲気)」「taste(味)」「noodle(麺)」「soup(スープ)」「ingredients(具材)」の6つ(重複あり)に分けて棒グラフにします。

ネガ口コミ.png

それぞれが原因のレビューの数です。味はもちろん、店員の態度も重要な要因なことが分かります。

EmbeddingProjectorを用いた可視化

EmbeddingProjectorを用いて可視化します。
知りたいカテゴリーを絞り込んでレビューを確認できるので、改善点をより発見しやすくなり、口コミを活かした業務改善が効率よく行えるでしょう。

EmbeddingProjectorは口コミの文章をword2vecによってベクトル化し、その後PCAによる次元削減を行い2or3次元空間上にマッピングすることによって可視化できます。 今回は「店員」「味」の2つを3次元空間に落とし込んでみます。まずはデータをロードし、下の画面右側のSearchのところで「店員」と検索します。

clerk3.png

「店員」と含まれている口コミが計88件あり、3次元空間上にきちんとマッピングできています。 その中で基準となる口コミを一つ選択し、下の画面右側のneighbor(近傍)を10などと設定すると、基準となる口コミから距離の近い(意味の近い)口コミが10個マーキングされます。

clerk.png

同じように「味」についてもみていきましょう。

taste.png

棒グラフでみた店員と味に絞って「何が悪いか」を更に深堀りしました。


6.総評

今回はBERTを用いて口コミ分析をしました。

前回の「単語」のみに着目した評価では、辞書に載っていない単語の評価が出来なかったり、文章全体の文脈を理解出来ていないという問題点がありましたが、BERTを用いることで、人間に近い判断基準をモデルに学習させることが出来、大幅に精度が向上しました。 口コミの中でネガティブな評価を選定し、グルーピングをすることで今まで発見できていなかった課題点も見つけやすくなります。

最後に、これから更に改善できる点です。

  • BERTのpretrainedモデルは日本語のwikipediaを対象に事前学習していたため、口コミ特有のワードへの対応が不十分であった
  • データの前処理の方法はさらに検討できる
  • 対象となるターゲットを広げたときに口コミの文章や書き方にバラツキがでるため、良い精度を出すためにさらに検討が必要


これらの課題を解決するにはSNSの事前学習モデルを使ったり、様々な工夫を考えて分類器を作成することが重要となってくるでしょう。 BERTでもかなりの精度を出せると思いますが、他の新しいNLPモデルも次々と発表されているので、これらを用いてまだ企業が利活用出来ていない口コミやSNSの書き込みなどを分析することで、顧客満足度向上に繋げられると思います。


7.参考文献

BERTとは何か?Googleが誇る最先端技術の仕組みを解説!
【論文】"Attention is all you need"の解説
BERTを用いたネガポジ分類機の作成
BERTを理解しながら自分のツイートを可視化してみるハンズオン


Twitter・Facebookで定期的に情報発信しています!

はじめに

このブログは前回、ドーナツの無人レジ化に向け機械学習をどのように用いるかを紹介しました。今回は、その中で出てきたドーナツ検出器の中身について紹介します。


目次

  • はじめに
  • 検出器を作るために必要なもの
  • どのような流れで作るか
  • 実際に作る
  • まとめ


必要なもの

ドーナツ検出器を作るために、ドーナツの画像データを訓練とテストを用意します。
今回は、「6種類のドーナツを検出し、合計金額を出す」ことが目標として、6種類のドーナツそれぞれの写真を50枚ずつ撮影しました。また、ドーナツが裏返っていても判断できるよう、裏返ったドーナツも同様に撮影しています(訓練データ)。テストデータは複数のドーナツが写る写真を撮りました。このドーナツの中には裏返ったものや写真からきれてしまっているドーナツも含んでいます。

スクリーンショット 2020-03-12 16.04.54.png


作成手順

ドーナツ検出器をどのような流れで作るかを紹介します。物体検出のためにYOLO3を用います。

 大まかな流れとして、このような作業をしています。

  1. 学習用の画像を整える、画像の水増し
  2. YOLO3でテスト用データのドーナツ一つ一つを検出する
  3. 学習モデルを用いてドーナツ名を予測する
  4. 合計金額などを表示する


1.ではYOLO3を用いて学習用の画像データからドーナツの部分だけを検出します。検出後、画像のアスペクト比(縦横比)を変えずにリサイズをします。画像は一つのドーナツに対して50枚しかないので回転や反転を用いて画像を水増しましょう。一つのドーナツに対して1500枚まで水増ししました。
3.では2.で検出したドーナツ画像から学習モデルを作成します。VGG16を用いて作成しました。


実際に作る

訓練データからドーナツの部分だけ検出する

スクリーンショット 2020-03-12 17.19.50.png

必要なライブラリをインポートします。

import logging
logging.disable(logging.WARNING)
import os
import glob

import numpy as np
from keras import backend as K
from keras.layers import Input

from PIL import Image

from yolo import YOLO
from PIL import Image
from yolo3.utils import letterbox_image

from matplotlib import pyplot as plt

keras-yolo3のYOLOクラスを継承してdetect_imageメソッドを修正します。

class CustomYOLO(YOLO):
  _defaults = {
        "model_path": 'model_data/yolo.h5',
        "anchors_path": 'model_data/yolo_anchors.txt',
        "classes_path": 'model_data/coco_classes.txt',
        "model_image_size" : (640, 640),
        "gpu_num" : 1,
    }

  def __init__(self, score=0.3, iou=0.45):
    self.__dict__.update(self._defaults)
    self.score = score
    self.iou = iou
    self.class_names = self._get_class()
    self.anchors = self._get_anchors()
    self.sess = K.get_session()
    self.boxes, self.scores, self.classes = self.generate()

  def detect_image(self, image):
        if self.model_image_size != (None, None):
            assert self.model_image_size[0]%32 == 0, 'Multiples of 32 required'
            assert self.model_image_size[1]%32 == 0, 'Multiples of 32 required'
            boxed_image = letterbox_image(image, tuple(reversed(self.model_image_size)))
        else:
            new_image_size = (image.width - (image.width % 32),
                              image.height - (image.height % 32))
            boxed_image = letterbox_image(image, new_image_size)
        image_data = np.array(boxed_image, dtype='float32')

        image_data /= 255.
        image_data = np.expand_dims(image_data, 0)  # Add batch dimension.

        out_boxes, out_scores, out_classes = self.sess.run(
            [self.boxes, self.scores, self.classes],
            feed_dict={
                self.yolo_model.input: image_data,
                self.input_image_shape: [image.size[1], image.size[0]],
                K.learning_phase(): 0
            })

        donut_out_boxes = []

        for i, c in reversed(list(enumerate(out_classes))):
          if self.class_names[c] == 'donut':
            box = out_boxes[i]
            top, left, bottom, right = box
            top = max(0, np.floor(top + 0.5).astype('int32') - 100)
            left = max(0, np.floor(left + 0.5).astype('int32') - 100)
            bottom = min(image.size[1], np.floor(bottom + 0.5).astype('int32') + 100)
            right = min(image.size[0], np.floor(right + 0.5).astype('int32') + 100)
            donut_out_boxes.append([left, top, right, bottom])

        return donut_out_boxes

YOLOで訓練画像からドーナツ部分を切り取って画像を保存します。

def crop_donuts(front_or_back):
  for dir_name in label_dict.keys():
    print(dir_name)
    output_path = '../data/cropped_donut_images/' + front_or_back + '/' + dir_name

    if not os.path.exists(output_path):
      os.makedirs(output_path)

    for file_path in glob.glob('../data/donut_images/' + front_or_back + '/' + dir_name + '/*.jpg'):
      file_name = file_path[-12:-4] 
      image = Image.open(file_path)
      out_boxes = yolo.detect_image(image.copy())

      if len(out_boxes) == 1:
        cropped_img = image.crop(out_boxes[0])
        cropped_img.save(output_path + '/' + str(file_name) + '.jpg')

訓練画像内にはドーナツが1つしかないはずなので、2つ以上ドーナツを検出した場合は保存せずその画像はスキップします。保存した画像を確認し、検出したがうまく切り取れていない画像はフォルダから削除してください。

YOLOでの検出がうまくいかなかった画像、検出したが切り出しがうまくいかなかった画像を抽出します。

def copy_undetected_images(front_or_back):
  for dir_name in label_dict.keys():
    print(dir_name)
    output_path = '../data/not_detected_images/' + front_or_back + '/' + dir_name

    if not os.path.exists(output_path):
      os.makedirs(output_path)

    for file_path in glob.glob('../data/donut_images/' + front_or_back + '/' + dir_name + '/*.jpg'):
      file_name = file_path[-12:-4] 
      path = '../data/cropped_donut_images/' + front_or_back + '/' + dir_name + '/' + file_name + '.jpg'

      if not os.path.exists(path):
        image = Image.open(file_path)
        image.save(output_path + '/' + str(file_name) + '.jpg')

ここで、抽出されたものは、手動でドーナツ部分を切り取りました。

1つ前の関数で抽出した画像をcroppeddonutimagesフォルダ下の適切なフォルダにコピーします。

def copy_images_cropped_by_hands(front_or_back):
  for dir_name in label_dict.keys():
    print(dir_name)
    output_path = '../data/cropped_donut_images/' + front_or_back + '/' + dir_name

    if not os.path.exists(output_path):
      os.makedirs(output_path)

    for file_path in glob.glob('../data/images_cropped_by_hands/' + front_or_back + '/' + dir_name + '/*.jpg'):
      file_name = file_path[-12:-4] 
      path = output_path + '/' + file_name + '.jpg'

      if not os.path.exists(path):
        image = Image.open(file_path)
        image.save(path)

ドーナツの画像分類のモデル作成

スクリーンショット 2020-03-12 17.25.30.png

アスペクト比を変えずに設定した大きさに画像をリサイズします。

def resize(img, base_w, base_h):
  base_ratio = base_w / base_h
  img_h, img_w = img.shape[:2]
  img_ratio = img_w / img_h

  white_img = np.zeros((base_h, base_w, 3), np.uint8)
  white_img[:, :] = [220, 220, 220]

  if img_ratio > base_ratio:
    h = int(base_w / img_ratio)
    w = base_w
    resize_img = cv2.resize(img, (w, h))
  else:
    h = base_h
    w = int(base_h * img_ratio)
    resize_img = cv2.resize(img, (w, h))

  white_img[int(base_h/2-h/2):int(base_h/2+h/2),int(base_w/2-w/2):int(base_w/2+w/2)] = resize_img
  resize_img = white_img

  return resize_img

正解ラベルのエンコード用に辞書を定義します。

label_dict = {
    'エンゼルクリーム': 0,
    'エンゼルフレンチ': 1,
    'オールドファッションハニー': 2,
    'ダブルチョコレート': 3,
    'チョコファッション': 4,
    'ポンデリング': 5,
}

データセットを作成します。

front_path = './drive/My Drive/donuts_detection/data/cropped_donut_images/front/'
back_path = './drive/My Drive/donuts_detection/data/cropped_donut_images/back/'

IMG_SIZE = 256
X = []
y = []

print("== DONUTS FRONT ==")
for dir_name in label_dict.keys():
  print(dir_name)
  label = label_dict[str(dir_name)]

  X_tmp = []
  y_tmp = []

  for file_path in glob.glob(front_path + dir_name + '/*.jpg'):
    img = image.load_img(file_path)
    # img = rotate(img)
    img = image.img_to_array(img)
    img = resize(img, IMG_SIZE, IMG_SIZE)

    X_tmp.append(img)
    y_tmp.append(label)

  for x in datagen.flow(np.array(X_tmp), batch_size=1):
    new_image = x[0]

    X_tmp.append(new_image)
    y_tmp.append(label)

    if len(X_tmp) % 1000 == 0:
      break

  X.extend(X_tmp)
  y.extend(y_tmp)

del X_tmp, y_tmp

print("== DONUTS BACK ==")
for dir_name in label_dict.keys():
  print(dir_name)
  label = label_dict[str(dir_name)]

  X_tmp = []
  y_tmp = []

  for file_path in glob.glob(back_path + dir_name + '/*.jpg'):
    img = image.load_img(file_path)
    # img = rotate(img)
    img = image.img_to_array(img)
    img = resize(img, IMG_SIZE, IMG_SIZE)

    X_tmp.append(img)
    y_tmp.append(label)

  for x in datagen.flow(np.array(X_tmp), batch_size=1):
    new_image = x[0]

    X_tmp.append(new_image)
    y_tmp.append(label)

    if len(X_tmp) % 1000 == 0:
      break

  X.extend(X_tmp)
  y.extend(y_tmp)

X = np.array(X, dtype='float32')
X /= 255.0
y = np.array(y)
y = np_utils.to_categorical(y, len(label_dict))

データの水増しを行いながらデータセットを作成します。 ドーナツの表面だけ使用するなら、それぞれのラベルにつき1500枚までメモリ不足にならずに水増しできました。表面・裏面とも使用する場合はメモリ容量の関係で各ラベル1000枚まで水増ししました。

モデルを作成します。

def create_model():
  base_model=VGG16(weights='imagenet',include_top=False, input_tensor=Input(shape=(IMG_SIZE, IMG_SIZE, 3)))
  x = base_model.output
  x = GlobalAveragePooling2D()(x)
  x = Dense(1024, activation='relu')(x)
  prediction = Dense(len(label_dict), activation='softmax')(x)

  model=Model(inputs=base_model.input, outputs=prediction)

  for layer in base_model.layers:
      layer.trainable = False

  model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])

  return model

VGG16の事前学習モデルを利用しました。モデルにVGG16の全結合層は含まず、分類用に独自に全結合層を追加しています。また、VGG16の層は学習しないようにしています。

モデルを学習して保存します。

EPOCHS = 20
BATCH_SIZE = 64
MODEL_PATH = './drive/My Drive/donuts_detection/models/donuts_front_and_back_cropped_model_2.h5'

X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.30)

model = create_model()

history = model.fit(
    X_train, y_train,
    validation_data=[X_valid, y_valid],
    epochs=EPOCHS,
    batch_size=BATCH_SIZE
)

model.save(MODEL_PATH)

エポック数とバッチサイズは適切なものを選んで下さい。

画像内のドーナツをすべて検出し分類する

スクリーンショット 2020-03-12 17.30.46.png

必要な辞書を定義します。

label_dict = {

    'エンゼルクリーム': 0,
    'エンゼルフレンチ': 1,
    'オールドファッションハニー': 2,
    'ダブルチョコレート': 3,
    'チョコファッション': 4,
    'ポンデリング': 5,
}

inverse_dict = dict([(v, k) for k, v in label_dict.items()])

'''
{
   商品名: [値段, 熱量(kcal), たんぱく質(g), 脂質(g), 炭水化物(g), 食塩相当量(g)]
}
'''
menu_dict = {
    'エンゼルクリーム': [120, 219, 1.3, 12.0, 26.1, 0.6],
    'エンゼルフレンチ': [130, 200, 2.0, 15.5, 12.6, 0.3],
    'オールドファッションハニー': [110, 355, 3.4, 18.0, 44.4, 0.8],
    'ダブルチョコレート': [130, 265, 3.6, 16.8, 24.3, 0.5],
    'チョコファッション': [130, 330, 3.7, 20.8, 31.3, 0.8],
    'ポンデリング': [110, 219, 1.3, 12.0, 26.1, 0.6],
}

YOLOで取得したバウンディングボックスを元に画像からドーナツ部分をトリミングして分類します。

image = Image.open("../data/donut_images/multiple_front_and_back/IMG_2367.jpg")
r_image, out_boxes = yolo.detect_image(image.copy())

plt.figure(figsize=(6, 8))
plt.imshow(r_image)

X = []
for box in out_boxes:
  cropped_img = image.crop(box)
  cropped_img = np.asarray(cropped_img)
  cropped_img = resize(cropped_img, IMG_SIZE, IMG_SIZE)
  X.append(cropped_img)

X = np.array(X, dtype='float32')
X /= 255.0

preds = model.predict(X)

pred_labels = [inverse_dict[pred] for pred in np.argmax(preds, axis=1)]
result = np.zeros(6)

for label in pred_labels:
  result += np.array(menu_dict[label])

print()
print(pred_labels)

print()
print(f"値段:         {int(result[0])}")
print(f"熱量(kcal):   {result[1]:.1f}")
print(f"たんぱく質(g): {result[2]:.1f}")
print(f"脂質(g):      {result[3]:.1f}")
print(f"炭水化物(g):   {result[4]:.1f}")
print(f"食塩相当量(g): {result[5]:.1f}")
print()
image

まとめ

最後にどれだけ正確に判定できているか、分類のパフォーマンスを計算してみましょう。

def extract_labels(row):
  labels = []
  for key in label_dict.keys():
    if row[key] == '1':
      labels.append(key)
  return labels

df = pd.read_csv('../multiple_front_and_back.csv')
df['labels'] = df.apply(extract_labels, axis=1)

donuts_num = 0
detected_donuts_num = 0
corrected_classified_donuts_num = 0

print('== INCORRECTLY DETECTED ==')

for file_path in glob.glob('../data/donut_images/multiple_front_and_back/*.jpg'):
  file_name = file_path[-12:-4]
  correct_labels = df[df['file_name'] == file_name]['labels'].values[0]
  donuts_num += len(correct_labels)

  image = Image.open(file_path)
  r_image, out_boxes = yolo.detect_image(image.copy())

  X = []
  for box in out_boxes:
    cropped_img = image.crop(box)
    cropped_img = np.asarray(cropped_img)
    cropped_img = resize(cropped_img, IMG_SIZE, IMG_SIZE)
    X.append(cropped_img)

  X = np.array(X, dtype='float32')
  X /= 255.0

  preds = model.predict(X)
  pred_labels = [inverse_dict[pred] for pred in np.argmax(preds, axis=1)]

  if len(pred_labels) != len(correct_labels):
    print(file_name)

  for label in pred_labels:
    if label in correct_labels:
      corrected_classified_donuts_num += 1
      correct_labels.remove(label)

  detected_donuts_num += len(pred_labels)

print('==========================')

print()
print('The number of all donuts: {:d}'.format(donuts_num))
print('The number of donuts detected by YOLO: {:d}'.format(detected_donuts_num))
print('Percentage of donuts detected by YOLO: {:.2f}'.format(detected_donuts_num / donuts_num))
print('Percentage of donuts classified correctly out of all dontuts: {:.2f}'.format(corrected_classified_donuts_num / donuts_num))
print('Percentage of donuts classified correctly out of detected dontuts: {:.2f}'.format(corrected_classified_donuts_num / detected_donuts_num))

出力結果は以下のようになりました。

== INCORRECTLY DETECTED ==
IMG_2331
IMG_2344
IMG_2357
IMG_2356
==========================

The number of all donuts: 195
The number of donuts detected by YOLO: 195
Percentage of donuts detected by YOLO: 1.00
Percentage of donuts classified correctly out of all dontuts: 0.96
Percentage of donuts classified correctly out of detected dontuts: 0.96

つまり、ドーナツはYOLOによって100%検出され、すべてのドーナツ(検出されたドーナツ)を96%の割合で正しく分類できています。
このシステムにより、今まで手動で行っていたドーナツのレジ計算を自動で行うことができます。

もちろん、ドーナツだけではなく、お弁当詰めにミスがないかチェックしたり、工場の生産ラインで不良品を弾くこともできます。


Twitter・Facebookで定期的に情報発信しています!

世界の人口推移と起こりうる問題

日本だけでは人口減少と言われていますが、世界を見ると人工は増加すると予測されています。 2019年に国連が発表した、世界人口推計2019年版 データブックレットによると2050年に97億人、2100年には110億人まで増加すると言われています。
5902c9be50a0cb27b5b66f0daaecf766.png

人口増加分の8割ほどをアフリカが占めています。
各国はアフリカが巨大なマーケットになると予測して、国を挙げて進出を加速しています。中国はこれまでに6900億ドル以上をアフリカに投資しており、日本では2016年8月にケニアで開催された第6回アフリカ開発会議(TICAD)にて、アフリカに300億ドル単位の投資を行うと発表しています。

アフリカを始めとした各国で人口増加すると問題に挙がるのが「食糧問題」です。 日本以外にも北米の各国など、人口減少すると予測されている国もあり、今まで以上に効率的な食料供給が求められます。


各国の農業

2012年の農作物輸出額は1,449億ドルと世界トップのアメリカは、広大な土地を活かし、大型の農業機械で少ない種類の作物を最適な環境で作る大規模農業を採用し、高い生産性を保っています。

スクリーンショット 2020-03-12 14.29.23.png

2位のオランダは、決して広くはない農地で効率の良い生産で高い輸出高を保っています。 最新の情報通信技術(ICT)や環境制御技術を駆使した「スマート・アグリ」を導入し世界トップレベルの土地生産性を保っています。


日本の農業

日本はかねてから集約農業を採用していますが、コストがかかり農作物単価は高くなるため世界市場では戦いにくい状態です。近年の海外における日本食ブームや 2013年に「和食」がユネスコ無形文化遺産に登録されたことを受けて、コストを下げた大量生産をおこなうために日本でも大規模農業を進める動きがあります。

また、日本では農業に従事する人が増えています。 個人数は減少していますが、法人化して農業を行う経営体が急増(2000年:5,272経営体→2017年:21,800経営体)しており、"サラリーマン"として農業が出来る働き先が増えています。

2009年の農地法改正で農業参入が全面自由化になり、企業の農業参入も増加(2000年:5,272経営体→2017年:21,800経営体)したことで、増加に拍車をかけています。

農家数が減少はしたものの若い農業従事者が増え、企業での大規模農業の採用...。
日本でもデータに基づく効率的な農業をおこなうことでより高い生産性を実現できそうです。


機械学習を農業に活用するサービス

農場をデジタル管理する Climate社 FieldView

最高の生産性を実現するために、天候情報、窒素量、畑の健康状態などを監視してダッシュボード化し、収量目標に合わせた作付けプランを提供します。 広大な農地でも、現在の状況がダッシュボード化されるので管理しやすく、意思決定を助けます。農業でSFAを活用しているかのようです。

スクリーンショット 2020-03-11 16.54.12.png

実際の画面です。
左から、マップを並べて収穫量等を比較している画面、現状の良し悪しを判断し、適切な意思決定をするための収集分析、更に詳細な分析のために領域ごとに土地の価値を判定する画面、です。

その他にも機械学習を活用してトウモロコシの病害診断をおこなったり、それぞれの農地で何が成功して何が失敗したかを科学的に分析するための収益分析をおこないます。


航空映像から生育マップを作成する Mavrx社 Taranis

ドローン等で撮影した空中映像を、葉に乗っているカブトムシを数えられるくらいの高解像度の画像処理をして衛生画像と組み合わせた生育マップを作成します。

jared-brashier-duNHkmSkW6M-unsplash (1).jpg

撮影された写真は植物の健康と品質を評価するディープラーニングエンジンによって分析されます。ディープラーニングエンジンは、最先端の数学モデルとクラウド上のハードウェアプラットフォームを使用し、60人以上の専門の農学者によって訓練され、1,000,000を超える作物の健康問題の例を提供しています。

例えば、雑草を早期発見し適切な除草剤の作成を支援したり、作物の生育不良を特定して対処方法をユーザーに知らせるなど、適切な対処のための指南をしてくれます。


今後の方針

上記事例のように、従来の集約農業から大規模農業に変化するための仕組みが提供されはじめました。 また、農業へのノウハウがなくとも高品質な生産ができるようにデータの可視化だけではなく、対処法まで指南してくれるようになり始めています。 2050年までの人口増加へ準備が必要な段階になっています。日本では労働人口が減っていますが、生産やサービスの需要は減りません。いかに効率よく生産できるか、生産性を上げられるかがこれからの農業のカギになるでしょう。

当社でもAI・機械学習を活用したソリューションを提案しています。


アクセルユニバースの紹介

私達はビジョンに『社会生活を豊かにさせるサービスを提供する。』ことを掲げ、このビジョンを通して世界を笑顔にしようと機械学習・深層学習を提案しています。

  • ミッション(存在意義)
    私達は、情報通信技術を使って万物(全ての社会、生物)の暮らしをよりよくすることに貢献し、 それを加速させることを使命とします。

  • ビジョン(目標とする姿)
    社会生活を豊かにさせるサービスを提供する。

  • バリュー(行動規範)

    1. 変化を求め、変化を好み、変化する
    2. 自分の高みを目指してどんどん挑戦する
    3. お客様と一蓮托生でプロジェクトを進める


会社概要はこちら


Twitter・Facebookで定期的に情報発信しています!


参考

世界人口推計2019年版 データブックレット

農林水産省「平成29年一般企業の農業への参入状況」

概要

自分に似合う色、引き立たせてくれる色を知る手法として「パーソナルカラー診断」が最近流行しています。

パーソナルカラーとは、個人の生まれ持った素材(髪、瞳、肌など)と雰囲気が合う色のことです。人によって似合う色はそれぞれ異なります。 パーソナルカラー診断では、個人を大きく2タイプ(イエローベース、ブルーベース)、さらに4タイプ(スプリング、サマー、オータム、ウィンター)に分別し、それぞれのタイプに合った色を知ることができます。


パーソナルカラーを知るメリット

  • 自分をより好印象に見せることができる
  • 自分に合うものを知って、買い物の無駄を減らせる
  • 本来の魅力を発見できる


現在、「パーソナルカラー診断」と検索すると、膨大な量のページが見つかります。しかしそれらのほとんどは設問に自分で答える自己申告タイプでした。

ほんとにこれで合ってるの?と疑問に感じることもあるでしょう。
専門家に見てもらうにはお金も時間もかかるし正直面倒臭い。写真や動画で、自宅で気軽に判断できたらいいのに...なんて思いませんか?


今回は、「パーソナルカラー診断サービス」を機械学習を用いて製作しました!


どうやるの? 機械学習のしくみ

今回の作業の流れです。
①画像を収集→②パーソナルカラー(4パターン)の正解を付け→③モデルを作成→④モデルに②の画像を学習
→⑤学習させたモデルに新たな画像を投入(テスト)→⑥画像に対してパーソナルカラーを判定→⑦精度向上のための考察


この作業で大まかには正解のパーソナルカラーを予測できるシステムが作成できました。
技術を詳しくご紹介します。


訓練データの確保

[芸能人の名前 パーソナルカラー] で調べると、その人のパーソナルカラーが分かります。それを参考にして判定用のモデルを作成しています。
学習をイチからするためには相当量のデータが必要なので、今回は予め学習されたモデルの一部を基にして層を追加する転移学習という手法でモデルを作成しました。

実装はkerasを用いて行います。kerasでは様々な事前学習済みモデルが用意されています。

ImageNet検証データでのスコアがそれぞれ出ていますが、どのモデルが今回のケースに一番うまくマッチしてくれるかは試すまでわからないのでひとまずVGG16と、ここでのベンチマークで一番精度の高いInceptionResNetV2を選びました。
InceptionV3という別のモデルもありますが、所々 InceptionResNetV2をInceptionモデルと略すところがあります。


Applications.jpg (引用)https://keras.io/applications/


├─personal-color
│ ├─data
│ ├─images
│ │ ├─autumn
│ │ │ └─original
│ │ ├─spring
│ │ │ └─original
│ │ ├─summer
│ │ │ └─original
│ │ └─winter
│ │ │ └─original
│ ├─scripts

というフォルダ構造で季節ごとに階層を分け、収集してきた画像をoriginalに格納しています。この時、画像の名前は、通し番号のみで管理しています。
この後学習させるにあたってパーソナルカラーを決める上で重要な要素となる顔の形や目だけにトリミングして別画像として保存することを考えたため、originalという形で保存しています。

収集した画像から顔を切り取るのに加えて、目だけ、口だけを切り取るために、dlibのランドマーク検出を使います。
ランドマーク検出とは、顔から要所となる点を検出するものです。


facereg.jpg (引用)https://docs.opencv.org/master/d2/d42/tutorialfacelandmarkdetectioninanimage.html


import logging
import os
import shutil

import cv2
import dlib
import numpy as np
from PIL import Image, ImageFilter
import keras
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential, Model
from keras.layers import Input, Dense, Dropout, Activation, Flatten
from keras import optimizers
from keras.applications.vgg16 import VGG16
from sklearn.model_selection import train_test_split


LABELS = ['spring', 'summer', 'autumn', 'winter']
PARTS = ['face', 'eyes', 'mouth']

for season in LABELS:
    pathList = ['../images', season, 'original']
    rootPath = os.path.join(*pathList)
    files = os.listdir(rootPath)
    files.remove('.DS_Store')

    for file in files:
        filePath = os.path.join(rootPath, file)

        img = cv2.imread(filePath)
        rects = detector(img, 1)
        PREDICTOR_PATH = ('../data/shape_predictor_68_face_landmarks.dat')
        logging.debug('--- fetch each coordinates from settled index ---')
        for rect in rects:
            face = rect
            predicted = predictor(img, rect).parts()
            left_eye = predicted[36:42]
            right_eye = predicted[42:48]
            mouth = predicted[48:]
            partsList = [left_eye, right_eye, mouth]
    logging.debug('--- trimming and save images ---')
    savePart()  # 上で求めた領域をそれぞれトリミングする。
一部略


モデルの作成

画像を入力用に再度加工し、モデルを作っていきます。
訓練用データは少し水増しを加え、テストデータはそのまま使います。前述の通り今回はVGG16とInceptionResNetV2を使っています。


def imagePreprocess(self):
    trainDataGen = ImageDataGenerator(rescale=1 / 255,
                                      shear_range=0.2,
                                      zoom_range=0.2,
                                      rotation_range=60,
                                      brightness_range=[0.8, 1.0],
                                      horizontal_flip=True,
                                      vertical_flip=True)
    self.trainGenerator = trainDataGen.flow_from_directory(directory=self.trainFolder,
                                                           target_size=(
                                                               self.IMG_HEIGHT, self.IMG_WIDTH),
                                                           color_mode='rgb',
                                                           classes=LABELS,
                                                           class_mode='categorical',
                                                           batch_size=self.BATCHSIZE,
                                                           shuffle=True)

    testDataGen = ImageDataGenerator(rescale=1 / 255)
    self.testGenerator = testDataGen.flow_from_directory(directory=self.testFolder,
                                                         target_size=(
                                                             self.IMG_HEIGHT, self.IMG_WIDTH),
                                                         color_mode='rgb',
                                                         classes=LABELS,
                                                         class_mode='categorical',
                                                         batch_size=self.BATCHSIZE,
                                                         shuffle=True)


def vgg16Model(self, summary=False, name='model', verbose=1, lr=1e-4, epochs=25, freezefrom=0, optimizer='RMSprop'):
    input_tensor = Input(shape=(self.IMG_HEIGHT, self.IMG_WIDTH, 3))
    vgg16 = VGG16(include_top=False, weights='imagenet',
                  input_tensor=input_tensor)
    if summary:
        vgg16.summary()
    top_model = Sequential()
    top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
    top_model.add(Dense(256, activation='relu'))
    top_model.add(Dropout(0.5))
    top_model.add(Dense(len(LABELS), activation='softmax'))
    self.model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))
    if summary:
        self.model.summary()

    vgg16.trainable = True

    if freezefrom == 0:
        for layer in vgg16.layers:
            if layer.name == 'block5_conv1':
                layer.trainable = True
            else:
                layer.trainable = False
    else:
        for layer in vgg16.layers[:freezefrom]:
            layer.trainable = False

    if optimizer == 'RMSprop':
        self.model.compile(loss='categorical_crossentropy',
                           optimizer=optimizers.RMSprop(lr=lr), metrics=['acc'])
    if optimizer == 'SGD':
        self.model.compile(loss='categorical_crossentropy',
                           optimizer=optimizers.SGD(lr=lr), metrics=['acc'])

    history = self.model.fit_generator(self.trainGenerator, steps_per_epoch=25, epochs=epochs, validation_data=self.testGenerator,
                                       validation_steps=10, verbose=verbose)
    self.history.append(history)
    self.model.save(os.path.join(
        *[self.baseDir, 'data', name + '.h5']), include_optimizer=False)


def inception_resnet(self, name='model', lr=1e-4, epochs=25, trainFrom=0):

    resnet_v2 = InceptionResNetV2(include_top=False, weights='imagenet',
                                  input_tensor=Input(shape=(self.IMG_HEIGHT, self.IMG_WIDTH, 3)))
    model = Sequential()
    model.add(Flatten(input_shape=resnet_v2.output_shape[1:]))
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(len(LABELS), activation='softmax'))

    if trainFrom == 0:
        resnet_v2.trainable = False
    else:
        for layer in resnet_v2.layers[:trainFrom]:
            layer.trainable = False

    self.inception_model = Model(
        input=resnet_v2.input, output=model(resnet_v2.output))
    self.inception_model.compile(
        loss='categorical_crossentropy', optimizer=optimizers.RMSprop(lr=1e-4), metrics=['acc'])

    hist = self.inception_model.fit_generator(
        self.trainGenerator, epochs=epochs, validation_data=self.testGenerator, steps_per_epoch=25)
    self.history.append(hist)
    self.inception_model.save(os.path.join(
        *[self.baseDir, 'data', name + '.h5']), include_optimizer=False)


結果は?

目と口のみで学習させたモデルの結果はval accが0.25に非常に近いものでした。4クラス問題なので、これでは全く意味がありません。

一方顔全体での結果は以下の通りでした。


Inception
Epoch 25/25
25/25 [==============================] - 18s 709ms/step - loss: 0.7033 - acc: 0.7200 - val_loss: 2.7571 - val_acc: 0.4781
VGG16
Epoch 25/25
25/25 [==============================] - 11s 458ms/step - loss: 1.0617 - acc: 0.5225 - val_loss: 1.2682 - val_acc: 0.4230

学習時間はColab Tesla T4でInceptionが約10分、VGGが5分ほどでした。


決して非常に高機能なモデルとは言えませんが、目のモデルと比べると顔全体を使用したモデルが良さそうです。何より、私自身がパーソナルカラー診断をしたら確実に0.25を下回るくらい難しい分類だったので満足の行く結果に見えます。過学習していなければですが。
ということで過学習に震えながら別のテストをすると、内実は惨憺たるものでした。

VGGモデルに関しては、少し夏と冬が多くあとはほぼランダムな出力でした。上振れでテストスコアが上下するような感じです。
一方Inceptionモデルは、夏と冬のテストに関しては約8割ほどの正解率でした。しかし、春と秋はほとんどが夏、冬と回答されていて、春か秋と答えられたのは、100件中2件ほどでした。オリジナルデータ数はこの時すべて同じ枚数で設定していたのでこのような偏りはすごい不思議なものでした。


どうしてこうなったのか原因を考えていきます。


精度向上のための原因考察

仮説その1 パラメータに問題がある

ハイパーパラメータに問題があって過学習している可能性を考え、learning rateを1e-2 - 1e-5まで変化させてテストをしました。また、ファインチューニングという新しいモデルを追加するだけではなく、以前のモデルの一部を学習時に用いるという手法も試しました。

結果として、概してval accの結果が良いのは1e-4のときでした。

1e-5では、25epochsだと少したりないような印象を受けました。上述のスコアも1e-4にしたときのスコアです。しかし、スコアの微小な上下はあれど、本質的な偏りの修正には至りませんでした。


仮説その2 モデルがそもそもあっていない

人間の顔をその雰囲気から分類するというタスクがこれらのモデルにあっていないのではないか。しかし、これを言ってしまうと本末転倒です。
もともと訓練データを集めづらい分野において、予め学習してあるモデルを転用するというコンセプトが転移学習ですし、一旦考えなかったことにします。


仮説その3 訓練画像の質が悪い

画像の質と言っても、様々な要素があります。

画質、水増しでゴミができていないか、正しいクラスに分類されているかetc...
今回訓練に使ったのは芸能人の画像でした。もともと、化粧や照明の影響で印象が変わることは危惧していましたが、とりあえずモデルに投入していました。 今一度初心に帰り、これらを見直すことにしました。

基準が私では判断ができないので、当社腕利きのパーソナルカラー診断士が人の目で答えがわかっているテスト画像を再度精査をしました。

すると驚くことに、VGGモデルで、学習機の導き出していた答えが人の目の意見と一致するものが多々ありました。
人の目でも即座に判断できるものは正解しており、判断が難しいものに関しては、イエローベース、ブルーベースの2択までは絞り込めるという感覚でした。

つまり、テストデータとして与えていたラベルが間違っていただけで学習機は頑張って学習していたのに、画像を収集する際にこの人はこの季節、とその写真のときの状態を見ずに決めてしまっていたため引き起こされてしまったのです。

この結果を受けて、再度すべての画像を再分類することにしました。
VGGモデルでは偏りが減り、正解率も微小ながら上がりました。しかし、Inceptionモデルでは逆に夏と冬しか結果として出力されないようになってしまいました。
このモデルは(他もそうですが特に)非常に複雑なモデルなので、難しい学習の果てに夏と冬だけに焦点をあてた方が精度が上がると判断されてしまったのかもしれません。データ数に不均衡はないので今回は仮説その2として切り上げます。

(参考)https://qiita.com/koshian2/items/20af1548125c5c32dda9


まとめ

一番の原因がデータ処理が甘かったというなんとも情けのないものでした。

色々なところで色々な人が機械学習の8割は前処理といったことを口を酸っぱく言っている意味を再度認識しました。
また、とんでもなく巨大なBiTという新モデルが2019年の12月に発表されたので、次回はこれも試してみたいです。

(参考)https://qiita.com/omiita/items/90abe0799cf3efe8d93d


AI・機械学習を活用したシステムが少しずつ普及しています。今回のように画像を用いた判定・予想は人の手をシステムに代替するために便利な手法です。
例えば、人がおこなっている不良品チェックを機械学習でおこなったり、複数の散乱している物をなにであるか判定し金額を表示することで無人レジを作成したり...。
リモートワークや自由な働き方が進んでいる中、人間とシステムが上手に共生する社会がすぐそこまで迫ってきています。

当社ではAI・機械学習を活用したソリューションを提案しています。


アクセルユニバースの紹介

私達はビジョンに『社会生活を豊かにさせるサービスを提供する。』ことを掲げ、このビジョンを通して世界を笑顔にしようと機械学習・深層学習を提案しています。

  • ミッション(存在意義)
    私達は、情報通信技術を使って万物(全ての社会、生物)の暮らしをよりよくすることに貢献し、 それを加速させることを使命とします。

  • ビジョン(目標とする姿)
    社会生活を豊かにさせるサービスを提供する。

  • バリュー(行動規範)

    1. 変化を求め、変化を好み、変化する
    2. 自分の高みを目指してどんどん挑戦する
    3. お客様と一蓮托生でプロジェクトを進める


会社概要はこちら


Twitter・Facebookで定期的に情報発信しています!

「思っていたよりいい!」
購入した商品を使ったとき、こう思えると嬉しいですね。

重要なことは『思っていたより』という点で、私たち提供者は常にお客様の期待を超えていかねばなりません。
驚きと喜びが両立して初めて感動が生まれ、リピーター、そしてファンになってもらえるのだと思います。

そんな『いい!』と思ってもらうための重要な要素である品質。
今回はAI・機械学習を活用して品質を向上し、高品質を保つ事例をご紹介します。


スクリーンショット 2020-03-05 17.07.21.png

品​​質向上のための機械学習活用

機械学習が、機器を適切に動作させ、材料または工程順序の変更が製造内容に影響しないようにすることで、製造者がより良い製造工程と品質を保つことを手助けします。

まず、製造機器に取り付けられたセンサーで、信号を収集、監視し、機械の動作データと温度、相対湿度、その他の環境データなどの周囲のセンサーデータの両方を追跡できます。
次に、機械学習を使用して、この過去データとリアルタイムプロセスデータを比較します。品質に影響する条件が検出された場合、製造完了前に修正が可能です。

1日あたり5,000万回以上の溶接をする、ある自動車メーカーでは、低品質な溶接に気付き一定の品質を保つためにシステムが活用されています。
品質の低い溶接を発見した際には、溶接をやり直し、部品を完全に廃棄し、部品をキューに戻す時間のロスと金額のコストを削減しており、
各溶接ロボットからは、トルク、電流、モーターの1分あたりの回転数、アーク時間、および供給されたワイヤの太さを測定する信号を含む15の信号が収集されています。
同社は既知の高品質な溶接の信号をロボットからリアルタイムで取得するデータ信号と比較することで、溶接品質の良し悪しをリアルタイムで検出できます。

機械学習は、新しい異常を検出するためにも使用されます。異常はシステムにフィードバックされ、アルゴリズムを改良および改善します。
最終結果として、不良溶接の検出率は98%になり、再溶接が必要な溶接数の5倍減少しました。手動ではできなかった検知・分析によりコストと時間の両方が大幅に節約されています。


機械学習による品質基準チェック

品質基準を満たしていることを保証するためにもAI・機械学習は活用されています。

通常、製品の目視検査は、生産中または完成後に行われます。以前は人間が検査していましたがやはり疲労や速度に限界がありました。
また、人間には健康状態(アレルギー、病気、ストレスによる視力低下、白内障、黄斑変性、円錐角膜などの検出されない状態など)の悪い時があり、それが目視検査に影響を与える可能性があります。
マシンビジョンと機械学習を活用することで、機械と人間が適切に役割分担をし、製品検査工程の効率、精度、再現性の向上が実現します。

Landing.AIは、Google Brainの開発を率いた著名な機械学習エキスパートであるAndrew Ngによって設立された新しい会社です。
マシンビジョン、オブジェクト識別、および機械学習を組み込み、AIを業務の工程に統合できるようにしています。
以前の目視検査システムは、全ての欠陥を確実に認識するために約100万枚の画像データでトレーニングする必要がありました。新たなLanding.AIのシステムは5つの製品画像のみをレビューした後に欠陥のパターンを認識することができます。Landing.AIのディープラーニングは部品の検査に0.5秒で済み、多くの場合人間よりも正確だと言われています。

機械学習での画像認識に必要なデータ量と時間を削減するもう1つの例に富士通研究所の事例があります。
今までは、製造ラインや部品を変更する場合、検査システムも改訂して、画像データのデータベースが最新であることを確認する必要がありましたが、同社の既存の画像認識システムプログラムの目標と目的は事前に設定されていましたが、新しい製造ラインを開始する際にに使用できる画像データの量は限られていました。
富士通は、システムをテンプレート化して画像認識アプリケーションを構成する、学習プロセスを高速化する専門の遺伝的プログラミングに注目しました。たとえば、テンプレートを使用すると、学習と認識のプロセスを3つのプロセス(画像処理、しきい値処理、バイナリ画像処理)に絞り込むことができます。プログラムは正常な部品と欠陥のある部品の画像からトレーニングデータを準備して合格/不合格の判断を下すことにより、自動的に学習し、進化します。
このシステムを部品の組立ラインでテストすると、検査用のコードを自動的に生成しほぼ100%の認識率を達成しました。

その結果、プログラムを開発する時間が80%短縮され、調整が行われても97%以上の認識率を維持しながら、同社の部品組立機が再学習できるようになりました。


スクリーンショット 2020-03-05 17.07.02.png

機械学習でファン化を進める?

お客様は多くの情報を持ち、膨大な選択肢から購入の意思決定をます。また、一度購入したから安心できるわけでありません。買い替え(リプレイス)の決断はとても早く、容赦なくやってきます。

しかし、ファンになってしまえばどうでしょうか?
一度ファンになると簡単には離れません。それどころか、他の製品も好きになってもらえるでしょう。

品質はそんなファンを作る大きな要因です。

まだまだ機械学習の活用は発展段階ですが、品質向上、維持のためのAI活用は順調に進んでおり、2025年までに4億1,820万ドルの年間収益を生み出し、アジア太平洋(1億3,380万ドル)と北米(1億1,710万ドル)が市場を牽引すると予測されています。

品質向上、維持のために当社でもAI・機械学習を活用したソリューションをご提案します。


アクセルユニバースの紹介

私達はビジョンに『社会生活を豊かにさせるサービスを提供する。』ことを掲げ、このビジョンを通して世界を笑顔にしようと機械学習・深層学習を提案しています。

  • ミッション(存在意義)
    私達は、情報通信技術を使って万物(全ての社会、生物)の暮らしをよりよくすることに貢献し、 それを加速させることを使命とします。

  • ビジョン(目標とする姿)
    社会生活を豊かにさせるサービスを提供する。

  • バリュー(行動規範)

    1. 変化を求め、変化を好み、変化する
    2. 自分の高みを目指してどんどん挑戦する
    3. お客様と一蓮托生でプロジェクトを進める


会社概要はこちら


Twitter・Facebookで定期的に情報発信しています!

エネルギー分野における課題

エネルギーの供給と消費は金融および社会環境コストの観点から企業・国民のリスクの1つであるため、現在は再生可能エネルギーへの関心が高まっています。 ブルームバーグ・ニュー・エナジー・ファイナンスのニューヨークに拠点を置くアナリスト、カイル・ハリソンは以下のように話しています。

「100%再生可能エネルギーを使用すると宣言している企業もある。そのような企業の増加により、政府の補助金に関係なく、再生可能エネルギーの活用検討が促進される。」


再生可能エネルギー分野におけるAI・機械学習活用可能性は、気象予測の改善だけではなくエネルギー消費要因全般にも関連しています。 今回は海外事例から再生可能エネルギー分野のさらなる可能性を紹介します。


スクリーンショット 2020-03-05 14.50.37.png

機械学習を活用した事例 5選

再生可能エネルギー需要量予測

特定の日においてエネルギー需要がどれだけ発生するか予測します。 過去の時間ごとのエネルギー消費量データを機械学習に学習させて予測モデルを作成します。 正確なエネルギー需要と消費を予測することで、施設や建物の管理者、エネルギー会社、公益事業会社が省エネポリシーを展開するために使用できます。企業では予測データを活用し、運用とエネルギー貯蔵システムを最適化する方法を計画立てることができます。 また、顧客ごとに必要エネルギー量を予測し、最適な契約容量を提案することで、エネルギー費用のコストを最小限に抑えることができます。


再生可能エネルギーの供給量予測

ドイツでは既に再生可能エネルギー分野において機械学習が活用されています。 たとえば、エネルギー量の不足を事前に察知するために、国内の風力タービンとソーラーパネルのリアルタイムデータを分析して用意できるエネルギー量を予測します。2日間分のエネルギーが用意できるかどうかを基準として不足可能性があるとアラートで知らせます。

また、IBMでは再生可能エネルギーのために天気パターンを予測支援できる機械学習のシステムを独自に開発しました。 Self-Learning Weather ModelおよびRenewable Energy Forecasting Technology(SMT)と名付けられ、1,600の気象観測所、太陽光発電所、風力発電所、および気象衛星から取得したデータを分析します。SMTの天気予報は、National Weather Serviceがまとめたものよりも最大30%正確です。

上記の2つの事例は再生可能エネルギーの収集量を予測するために役立っています。


再生可能エネルギーの最適価格決定

需要と供給が予測できるようになったことで、エネルギー価格の最適値を予測することができます。従来の価格設定システムに比べていくつかの利点があります。

  • ニューラルネットワークは人では管理できない膨大な量のデータを分析できる
  • エネルギーの供給と需要の間の非線形相関を学習して、直感に反してデータに基づいた設定価格を推奨できる
  • ビッグデータ主導の価格戦略は可視化できる
  • 価格管理者の業務時間を短縮し、高レベルの意思決定のみが業務として残すことができる


スクリーンショット 2020-03-05 14.49.59.png

風速変動予測による風力発電地の検討

マサチューセッツ工科大学(MIT)の研究者は、一定期間の風速の変動をより迅速に予測できるシステムを開発しました。 このシステムにより、公益事業会社や再生可能エネルギーの新興企業は、風力発電所の候補地をより早く見つけられます。 候補地発見のためのデータ収集は電力会社がおこなうと、最大で12か月程かかりますが、MITが開発したような機械学習を活用したシステムでは、わずか3か月のデータに基づいてモデルを作成します。しかも従来のデータ収集よりも正確に予測ができます。


エネルギー消費量を利用した機器異常の検出

機械学習でエネルギー消費を常に監視、分析し、異常を検出します。 電力が消費されている中でどこでどのくらい電気が使用されているかを確認するのは難しく、機器の誤動作を検出することも難しいです。システムに障害が発生したり、構成が誤っていると、火災などの悪影響が生じる可能性があり、このシステムは大きな経済的損失を防ぎます。

人工知能アルゴリズムの開発により、スーパーマーケット、高校などを自動的に定義し、エネルギー消費に基づいて異常をリアルタイムで検出および分類できます。このようなソリューションは、リアルタイムでエネルギー消費の異常を自動的に検出し、非常に迅速に意思決定できるユーザーに通知します。大きな経済的損失を避けるのに役立ちます。


今後のエネルギーの移り変わり

最近まで再生可能エネルギーは予測不能であったこともあり、現時点では世界のエネルギー需要を満たすために化石燃料は必要不可欠です。 AIも化石燃料の探査・生産コストを削減し、配送を合理化することで化石燃料の供給を支援しています。

AIは、再生可能エネルギーと同じくらい化石燃料を強化できますが、化石燃料の持続不可能性が考慮すると、長期的に見た理想的なシナリオではありません。
最終的には、再生可能エネルギーが化石燃料に取って代わると予想され、AI・機械学習の活用は再生可能エネルギーの普及を助けるために役立っていくでしょう。


当社でもAI・機械学習を活用した課題解決をご提案しております。


アクセルユニバースの紹介

私達はビジョンに『社会生活を豊かにさせるサービスを提供する。』ことを掲げ、このビジョンを通して世界を笑顔にしようと機械学習・深層学習を提案しています。

  • ミッション(存在意義)
    私達は、情報通信技術を使って万物(全ての社会、生物)の暮らしをよりよくすることに貢献し、 それを加速させることを使命とします。

  • ビジョン(目標とする姿)
    社会生活を豊かにさせるサービスを提供する。

  • バリュー(行動規範)

    1. 変化を求め、変化を好み、変化する
    2. 自分の高みを目指してどんどん挑戦する
    3. お客様と一蓮托生でプロジェクトを進める


会社概要はこちら


Twitter・Facebookで定期的に情報発信しています!

機械学習のアルゴリズムがつくりだす状況を利用して、自然実験に近い分析をおこなった事例を紹介します。
このような事例を応用すれば、実際に実験をおこなわなくても介入効果などが分かるかもしれません。


はじめに

昨今、AI・機械学習の進歩のおかげで、様々な予測をおこなうことができるようになりました。
みなさんも機械学習を使った株価の予測などニュースでみかけることも増えたと思います。
株価だけでなく、交通量からチケットの売上・電力消費量etc......
なんでも予測されていますね。笑
このように2019年現在、たくさんの企業がなんらかの予測をするためにデータを集めています。


今回はこうした集めたデータを利用して、さらに分析をした事例を紹介します。
※正確に表現すると機械学習アルゴリズムが作った状況を利用して分析する事例です。


介入効果とは

介入効果と書くとピンと来ませんが、おこなったアクションに効果があったのかということです。

ある会社で商品の宣伝のために、全国でテレビCMをおこなったとします。
その結果、商品の売上が30%も上がりました! すごい! これからどんどんテレビCMを放送しよう!


本当にこれで良いでしょうか?


クリスマス時期のため売上が上がったかも...。(実際に多くの売上のデータでは季節調整がされています。)
もしくは、有名人がたまたまSNSでその商品の写真をupしたことで、若者を中心に大流行したからかも...。


テレビCMはお金をかけてやる必要があったのでしょうか?
広告の効果を正確に知るには、広告以外の状況が同じ店舗の売上を比べればわかります。(ざっくりいうとほぼ状況が同じものを比較する)


この場合だと、地域ごとにテレビCMを放送する地域、しない地域で分け、さらに売上状況や天気等、条件を揃えて比較する必要があります。


残念ながらこのような状況を意図的に作り出すのは難しいです。
より多くクリックされるweb広告を比較したり、奨学金の効果など、状況を同じにして効果を実験したい例はたくさんあります。


こうした詳しく原因を分析することを因果推論といいますが、これについては当社の記事「はじめての因果推論」を参考にしてみてください!


アルゴリズムが生むランダム化実験

ここで登場するのが、機械学習のアルゴリズムを利用して得るデータです。
需要と供給によって価格が変わるUberXのデータを使って、利用者がどれくらい価格に反応するか(価格弾力性)を測る分析を紹介します。
ここでネックなのが、価格だけの影響を知りたい場合に、どうやって他の要因を排除するか...
この点は、先程のテレビCMの効果を測る例と共通しています。


ここで役立つのが、機械学習を使ったアルゴリズムで集めたデータです!
Uberはもともと状況に応じて、自動で価格を上げ下げする仕組みです。そのためアルゴリズム内部では、1.249など少数点以下もしっかり計算されています。
しかし、利用者はそこまで細かい金額では払えないので、少数点第二位以下を四捨五入して表示するようプログラムされています。
ここにランダム化実験を見出すことができます。
つまりUberでは、1.249は1.2と表示され、1.251 は1.3と表示されることになります。
しかし値段以外の要因は1.249と1.251では、ほとんど同じです。よってこの2つで比較すれば、価格が利用者にどう影響するかを明らかにできます。


アルゴリズムが生むランダム化実験の応用性

このように、機械学習のアルゴリズムで集めたデータに自然実験が行えるような例は、たくさんあるのではないでしょうか?
例えば、裁判官の判決や奨学金を与えると生徒はどうなるのかなどです。
実際サイバーエージェントでは、こうした手法を使い広告の効果を測定する研究も行われているそうです。


このような手法を使えば、ランダム化実験や人為的なABテストなど、時間やコストが多くかかるプロセスを
回避できるかもしれません。


参考文献

・矢田紘平、成田悠輔「機械学習は自然実験を作り出す」『経済セミナーe-book No.15』、日本評論社、2019年12月、19-20ページ
・Cohen, Peter, Robert Hahn, Jonathan Hall, Steven Levitt and Robert Metcalfe (2016) "Using Big Data to Estimate Consumer Surplus: The Case of Uber,"NBER Working Paper 22627.
・Narita, Yusuke, Shota Yasui and Kohei Yata (2019) "Efficient Counterfactual Learning from Bandit Feedback,"Proceedings of the Thirty-Third AAAI Conference on Artificial Intelligence, pp.4634-4641.


Twitter・Facebookで定期的に情報発信しています!

はじめに

 ドーナツを買おうと店内を覗くと、大勢の人が並んでいて買う気をなくしてしまうことがよくあります。

行列を解消すると更に多くの人がドーナツを買い、売上げアップはもちろん、新しいお客さんを獲得するチャンスにもなるのでは...。と気づきました。
そのために店頭業務をスピードアップしてお客さんを待たせない仕組みを作ることが必要です。今回はドーナツ屋さん店頭業務の効率化について考えてみました。

現状、時間短縮の要因は

  • お客さんがドーナツを選ぶ時間が長い
  • ドーナツをレジ打ちする時間が長い、またはミスがあり時間がかかっている

    お客さんにより満足してもらうために、2点目に注目し実現方法を検討しました。


レジ打ち自動化にむけての課題

 現在、レジ打ちの自動化を実用しているお店はよく見かけます。例えば、GUではRFIDを用いてカゴを機械の中に入れただけで商品が登録され、お会計に進めます。しかしこれをドーナツに適用するのは難しいです。
なぜならば、ドーナツそのものにタグは付けられません。タグを付けることなく、GUのような無人レジを実現するにはどのようにすればよいでしょうか。
この問題は機械学習を使うことで解決できます。


解決策|機械学習を用いたドーナツの無人レジ


 機械学習を用いてドーナツの検出と判定を行い、名前と金額を表示しました。
精度は95%以上でドーナツが裏返っていても問題なく検出できています。

 このようなドーナツ検出器があれば次のような利点があります。

  • 機械が判別し、レジでの時間短縮
  • 回転率が上がり、多くのお客さん対応ができる
  • 従業員を使わずに会計ができ、人件費削減  - 人の疲れによる見落とし、ミスがなくなる


ドーナツ検出の応用

 機械学習でのドーナツ検出により、RFIDを使うことなく無人で金額の計算をすることができました。
これにより、タグを付けることができない商品にも無人レジで対応することができます。

 また、農作物の最適な収穫時期を知らせる機械にも応用する事ができます。
収穫する予定の農作物の写真を撮り、機械が今収穫することが最適か判断します。人が農作物の最適な収穫時期を判断するには慣れるまで時間がかかりますが、機械が行えばそのような時間は必要ありません。


終わりに

 今回はドーナツの無人レジによってどのようなことが実現可能かを記事にしました。
次回は、ドーナツ検出の技術を紹介します。


Twitter・Facebookで定期的に情報発信しています!

医療・ヘルスケア分野での機械学習検討状況

2019年6月にロンドンで開催されたAIサミットのヘルスケアAIストリームで実際のヘルスケア問題を解決するための魅力的な機械学習活用事例が発表されました。

医療の課題をいくつか考えてみましょう。

  • 圧倒的な量はあるがオフライン上にあり活用できないデータ(紙カルテ等)
  • 病気や健康など、性質上予測が困難なモノ(いつどんな病気にかかるか予測しにくい)


現在は機械学習を活用し、異なるデータの分析と予測、および日常的な作業の自動化について検討しており、成功したときはこれ以上ない程の大きな影響を与えると予想できます。

本記事では現代の課題に即している2つの事例ご紹介します。

  • Cleveland Clinic『病気治療と入院期間の予測』
  • HiveとCarers UK『最適なシニアケアで自立生活支援』


Cleveland Clinic『病気治療と入院期間の予測』

非営利団体のCleveland Clinicは年間540万人の患者の診察を行っている団体です。
Cleveland ClinicロンドンのCEOであるBrian Donley博士は業界最大の課題の1つである『医療従事者の燃え尽き症候群』へのAIを活用した対策を解説しました。

博士によると燃え尽き症候群に罹る人は平均で23%にもかかわらず、医療従事者は54%と多くいます。特に医師は更にストレスにさらされているそうです。 多大な業務負担により燃え尽き症候群が発生していると考えられるため、早急に負担を軽減しなければなりません。

技術の発達は諸刃の剣です。
技術の発達により医師が作成する必要がある情報と読み込む情報(43,000の医学雑誌、810,000の専門記事、患者が入力したデータ、試験など)が増加し、業務量も増加します。しかし、AIにとっては活用できるデータが増えるのでありがたい状態になります。 Cleveland Clinicはこの状況を利用し、医師がより効率的に治療に専念できることを目指し患者への分析と予測にAIを使用しています。

Cleveland Clinicは再入院の有無と滞在期間・個人の生存状態等の10億点ほどのデータから、退院後の患者はかなりの数が再入院していることを発見しました。
また、臨床データ、人口統計データ、および併存疾患データを分析してパターンを理解し、ある病気の治療方法と入院期間の予測モデルを構築しています。その予測結果で再入院の可能性と入院期間の大幅な短縮がされています。
現在は患者の状態を考慮して組織は必要な人員と期間を予測し配置しています。これは患者にとってより良い結果になっただけではなく、病院側もより適切にスタッフを配置できるようになりました。

スクリーンショット 2020-02-21 12.03.38.png

HiveとCarers UK『最適なシニアケアで自立生活支援』

HiveとClarkとCarers UKは「The Changing Face of Care (変化するケアの顔)」のテーマで発表しました。
Nonprofit Carers UKが共有したデータでは以下のことが明らかになっています。

  • イギリスの介護者は650万人ほどいる
  • そのうち介護と仕事の両方をしている人は300万人、高齢者の介護と子どもの世話をしている人は150万人ほどいる
  • 介護者の72%がメンタルヘルスの問題を抱えている
  • 65歳以上の半数が必要な介護について話していない
  • 40〜60歳以上の半数も親にどのような支援ができるかを話していない


これでは介護者の負担が大きいだけでなく、いざ介護が必要になった時にスムーズな介護ができません。


HiveはCarers UKと複数のパートナーと協力し、高齢者が自立して生活できるような監視システムを検討しました。
このシステムには高齢者の自宅での生活をリモートで監視する介護者向けのモバイルアプリも含まれています。
自宅のセンサーは、テレビ・ケトル・トースター・食器棚・ドア・リビングルーム・キッチンなど、様々な物の使用状況を記録するように設定し状況はレポートで介護者に通知されます。レポートは日次や週次で通知パターンを選択できます。

システムが生活パターンを学習すると介護者は、対象が通常寝ている時間・起きる時間・毎日一定の活動がある時間、およびこの時間に使用される特定の機器について設定ができます。 介護者はその場にいなくても家電の使用状況を確認できるため、介護のストレスを軽減できています。

このシステムの課題として、

  • 高齢者がモニターを設置する許可を得ること
  • 24時間年中無休のモニターに対する抵抗を和らげる必要があること が挙げられています。

    さらなる活用のために介護者と介護される人の事前のコミュニケーションとセキュリティー面での安心が必要です。

スクリーンショット 2020-02-21 12.03.54.png

おわりに

1日の会議でこのような2つの実用的な事例が発表され、注目を浴びたことはAIの今後の活用において大きな進歩です。
それは企業がAIの専門家になって技術で解決する問題を見つけるのではなく、実際の課題を考え、それらを解決するためにAIを活用していることを示しています。 つまり技術ありきのAIから脱出し、課題解決の手段としてのAIとなり始めました。


当社でもAI・機械学習を活用した課題解決をご提案しております。

  • 自社にあるデータを2次活用したい
  • 画像データを活用した機械学習を作成したい
  • 既にAI・機械学習システムを利用しているが思うような効果が得られていない
  • 機械学習ではなにが出来るのか興味がある


このようなご相談は画面右上の[お問い合わせ]までご相談ください。


アクセルユニバースの紹介

私達はビジョンに『社会生活を豊かにさせるサービスを提供する。』ことを掲げ、このビジョンを通して世界を笑顔にしようと機械学習・深層学習を提案しています。

  • ミッション(存在意義)
    私達は、情報通信技術を使って万物(全ての社会、生物)の暮らしをよりよくすることに貢献し、 それを加速させることを使命とします。

  • ビジョン(目標とする姿)
    社会生活を豊かにさせるサービスを提供する。

  • バリュー(行動規範)

    1. 変化を求め、変化を好み、変化する
    2. 自分の高みを目指してどんどん挑戦する
    3. お客様と一蓮托生でプロジェクトを進める


会社概要はこちら


Twitter・Facebookで定期的に情報発信しています!

SNS、口コミでの評価と顧客満足度は深い関係があります。
今回は「ネガポジ判定」を用いて、顧客の要望を発掘していきます。


目次

  • ネガポジ判定とは
  • 実装方法
  • 今後の検討方針
  • 参考文献


1.ネガポジ判定とは

自然言語処理分野に関する文章のネガポジ判定とは、AIが文章の内容がネガティブかポジティブか判定するものです。

今回は食べログからスクレイピングによって口コミ(お店の評価)を抽出し、それらを実際にネガポジ判定します。
判定結果、特にネガティブと判定されたものは、顧客満足度向上に役立ちます。この技術は、既存のデータを分析し二次活用していくために有効な手法です。


Sentiment Analysisライブラリ oseti

今回のネガポジ判定には oseti というライブラリを使用しました。
osetiは日本語評価極性辞書を用いて文の評価極性(ネガポジ)のスコアを計算します。このライブラリのリンクは参考文献に載せておきます。
例えば、以下の3つの文章でosetiを使います。


import oseti
analyzer = oseti.Analyzer()
analyzer.analyze('店員の態度は悪かった。')
==>[-1.0]
analyzer.analyze('ここのラーメンは美味しかった。')
==>[1.0]
analyzer.analyze('店員の態度は悪かったが、ここのラーメンは美味しかった。')
==>[0.0]


このように、osetiは極性を判定するキーワードに対しポジなら「+1」、ネガなら「-1」とスコアリングします。キーワードが複数ある場合はそれらのスコアの和の平均を出力します。また、osetiは1文ごとにスコアを出力し、文章を入力した場合は1文ごとにスコアを出していきます。


2.実装方法

事前準備【食べログから口コミのスクレイピング(抽出)】

では本題に入る前に、実際に食べログから口コミをある程度スクレイピングします。
スクレイピングする対象として、今回は東京都の渋谷(恵比寿,代官山含む)と池袋(早稲田,高田馬場含む)にあるラーメン屋を選択しました。

理由は、2つあります。
1.他の店舗間で値段の差がほぼないため、シンプルに味で口コミの評価が二分されると感じた
2.弊社が渋谷にあるのでどういうお店が評価が高いのか興味がある

そこで渋谷と池袋それぞれ、 評価が3.5以上のお店40件、それぞれの店舗から20件ずつ 計1600件(800×2)の口コミをスクレイピングしました。

スクレイピングの結果の一部です。

blog131_5-1.png blog131_6.png


scoreは食べログの評価、reviewcntはその店舗の口コミの件数で、著作権の関係上、店舗の名前storename、評価reviewは消してあります。このような形でそれぞれのデータをcsvファイルとして保存します。

さて、準備は整ったので早速osetiを使ってネガポジ判定していきましょう。


判定

まず、csvファイルのreviewに入っている文章を全てosetiに入力します。


 #ネガポジ判定
 def negaposi(text):
     review = analyzer.analyze(text)
     re_view= np.average(review)
     return re_view
 #ネガポジ判定値追加
 shibuya_ramen_review ['negaposi'] = shibuya_ramen_review['review'].map(negaposi)
 ikebukuro_ramen_review ['negaposi'] = shibuya_ramen_review['review'].map(negaposi)


出力は次のようになります。一番右のnegaposiの欄が判定スコアで、1文ずつのスコアの平均値を出しています。値が1に近ければよりポジティブであると考えられます。

blog131_7.png blog131_9.png


しかし、上の結果を見てみるとスコアは正の値となっていますが、極端に1に近いとは言えません。
例えば渋谷の1番上のスコア0.19444のレビューを見てみると(著作権の関係上載せれませんが)、スコア0.5は超えてもいいかなと思います。

文章全体を見てポジティブな内容であると分かっても、やはり文全体の平均を取っているので1に大きく近づきはしませんでした。なので、BERTなど文脈を読み取れるようなライブラリを用いた方が精度が上がりそうです。
全体としてポジティブに厳しい判定ではあったものの、ネガティブな内容をポジティブと誤判定することはなく、冒頭であげた「ネガティブな評価を見つける」、といった目的は達成できます。


N-gramによる頻出単語の可視化

次に、N-gramによってテキストを単語ごとに分割し、頻出単語を見ていきます。

blog131_10.png blog131_11.png blog131_12.png
今回ポジティブ判定されたラーメン屋の傾向が何となく分かります。

1、2、3の比較

  • 1では、麺などラーメン屋の口コミとしては当たり前に出てくる単語が上位に来てしまっているところは問題だが、味、麺、具材の種類を表す単語からは、池袋と渋谷を比較しても多少傾向が見られるので、ストップワードを工夫することで大まかな傾向は掴めそう。
  • 1は2、3と比べて一単語ずつの出現数が保証できる。
  • 2、3は1より具体的な麺、味の種類が出てくるため、より特徴的なワードを掴める。また、1よりも池袋、渋谷の差を確認しやすい。
  • しかし、一つ一つの出現数は少なくなるので、データの吟味が必要。
  • 2と3で入れ替わるワードもあり、両方のデータを考察する必要がある。


3.今後の検討方針

今回感情分析の手法(ライブラリ)としてosetiを用いましたが、単語の極性だけを見てもかなりの精度でネガポジ判定ができることがわかりました。

しかし、このosetiにはいくつか問題点があります。

  • 日本語評価極性辞書に載っていない単語が出現した際、それらを定量的に評価できない。
  • 極性辞書の単語の評価には作成者の感情が入っているので、客観的な評価が完璧にできない。
  • 1文ごとにネガポジ判定を行うので、文章全体で見たときに文脈を読み取れない。


これらが原因で、ポジティブな口コミをネガティブ寄りと誤判定したり、その逆の判定をしてしまう時もありました。
日々日本語は増えていくし、ニュアンスもそれに伴って変化していきます。人手で作る極性辞書にも限界があるので、今回はそこがボトルネックとなっていました。

3の問題点を改善するために、今後の検討ではBERTを用いて文章の感情分析を行いたいと思います。
また、単語の出現数だけを見て、ある程度の傾向は感覚的に掴めますが、単語同士の繋がりや、その単語がポジティブへ関係しているか明確ではありません。そのため係り受け解析をするなどが必要だと考えています。
全部の文章からだとその店に対する評価をしている文以外も入ってくるので、そこの取捨選択ができれば、評価されている部分と批判されている部分がより明確になると思っています。


4.参考文献

日本語評価極性辞書を利用したPython用Sentiment Analysisライブラリ oseti
【初学者向け】TFIDFについて簡単にまとめてみた


Twitter・Facebookで定期的に情報発信しています!

機械学習を利用して「エントリーシート自己PR分析サービス」を作成しました。

エントリーシートの評価や言いたいことが伝わるか、心配ですよね。
また、企業の採用担当者は膨大な数のエントリーシートを確認することはかなりの業務量かと思います。

「エントリーシート自己PR分析サービス」では、自己PRの内容を入力すると点数や頻出単語を表示します。


[2020年2月21日追記:デモ動画]

機能追加しました!
・自己PRそのものの採点ができるようになりました。


スクリーンショット 2020-01-23 11.53.29.png

サービスのポイント

  • 文章の特徴を可視化する
  • キーワードとの適合度を判定
  • 文章のカテゴリーを判定
  • 過去合格した自己PRと比較して採点


サービス内容を紹介します。


エントリーシート自己PRの例

私は、アルバイトの中で最も時給がアップしたという実績を持っています。

コンビニエンスストアで3年間勤務していますが、ただ働くのではなく、計画性を持って働くことができるという点が時給アップにつながりました。

具体的には、3つのポイントがあります。

お店の繁忙期をプライベートの予定と照合し、あらかじめお店が忙しい時にはいつでも残業できるようにしていたことです。一緒に働くスタッフの性格を把握しておき、一緒にシフトに入る人によって、自分の立ち位置を変えていたことです。集中力が必要となる発注作業がある日の前後には、徹夜するなどの無理なことはせず、身体的にも余裕をもっておくことです。

これら3つをすべて実行することで、他のスタッフは通常1度に30円しか昇給しないところ、前例のない100円の昇給に成功しました。

この計画性を活かし、御社でも先を見据えたスケジューリングと自己管理で、生産性の向上だけではなく、業務のクオリティをあげることにもつなげて参りたいと考えております。

(【例文多数掲載!】自己PRで計画性を伝えるときのポイントをご紹介から引用したものを少し修正)


ワードクラウド


wordcloud


結果を見ると「時給」や「計画」「アップ」などの頻度が高いことがわかります。
ワードクラウドとは与えられた文章を元に、出現頻度が高い単語ほど大きなサイズで表示するものです。文章内使われた単語を視覚的に捉えることで、エントリーシートなどの文章作成でも役立ちます。


キーワードと自己PRの適合度を判定

キーワード: 計画性 昇給
点数:77.7 点

キーワード:真面目 研究
点数:24.9 点

言いたいことを表現しているか採点するために文章内の頻出単語と自分で付けたキーワードを照合します。

就活において自分の強みなどを記述する際は、「計画性」や「行動力」、「部活」や「研究」などキーワードとなる言葉を意識して文章を組み立てますよね。これがどれぼど的確に出来ているかを採点するために、ワードクラウドの結果 (単語の頻度) とキーワードとなる単語との類似度を点数化しました。

例えば先程の自己PRでは、計画性やアルバイトに関するキーワードを選ぶと点数が高くなり、部活や協調性など関係のないキーワードを選ぶと低い点数になります。


単語の分散表現

キーワードとの適合度を判定するために単語の分散表現を用いました。
分散表現とは簡単に言うと単語を200次元などの高次元のベクトルで表現したものです。分散表現では似た単語同士は類似度が高く算出されます。

さらに、単語の意味も捉えることもできるため、
king - man + woman = queen
といった分散表現の足し引きをすることも可能です。
分散表現を使って、入力文章中の上位10個の頻出単語とキーワードを比べ、最大の類似度から点数を算出しています。
より適切に採点するために、類似度は文章中の出現頻度によって重み付けをしています。例えば、最も頻度が高い単語とキーワードの類似度は計算結果の値をそのまま使い、単語の頻度が1位の半分の場合は、類似度も計算結果の半分の値を使います。
キーワードも複数設定できるようにし、ユーザーの意図を汲み取りやすくしています。


自己PRを100点満点で点数化

自然言語処理において強力なBERTを使って自己PRを点数化しました。
ざっくりとしたBERTの解説については以下の記事をご参照ください。

Googleを理解する!文脈を読み取る最新の機械学習(BERT, ELMo)

自己PRを点数化する方針は良い自己PRを1とラベル付けし、悪い自己PRを0とラベル付けした後に2値分類を行います。2値分類の結果は0以上1以下の連続値で得られるので、その値に100をかけて点数化しました。

このときBERTをいちから学習させようと思うと大量のデータが必要になります。しかし、手元にあるデータ量は限られていたため事前に学習されたモデル(BERT日本語Pretrainedモデル)を利用しました。

最終的なモデルの構成は以下のようになりました。
BERTのEncoder-12-FeedForward-Norm層までを取り出しBidirectional層とDropout層を加えた後、全結合層を追加し2値分類できるモデルを作成しました。

BERT model structure


自己PRの点数化

上で例示した自己PRの点数を出してみましょう。

点数:84 点


次に悪い自己PRの例を用いて点数を出してみましょう。

エントリーシート自己PRの悪い例

私の強みは辛いことも諦めずに立ち向かう粘り強さです。わたしは大学の時にコンビニエンスストアでアルバイトをしていました。

コンビニでは担当する業務が思ったより多く、なかなかすべてを覚えることができなかったので、最初は店長やアルバイトの先輩に叱られてばかりでした。何度も辞めてしまいたいと思うことがありましたが、せっかく始めたからには諦めたくないという気持ちが強く、もっと前向きに仕事に取り組もうと考えました。

そこで、家に帰ってからもアルバイト先で学んだことをしっかり復習し、どの仕事も任せてもらえるような知識を身に付けました。また、気持ちよくお客様に接する事を心掛けて、どんなに疲れている時でも、どんなに忙しい時でも笑顔を絶やさないようにしてきました。今では店長や他のアルバイトの人にも認めてもらえるようになり、そのアルバイトを続けていくことができています。

これからもどんな仕事も諦めずに取り組む姿勢を大事にしたいです。

(自己PRの例文【悪い例:400文字、コンビニでのアルバイト①】から引用)

この自己PRはマイナスなことを書いている部分が多かったり、数字や具体的な内容が欠けておい良くない自己PRだと言えます。実際に点数を出すと

点数:52 点

冒頭の自己PRと比べて30点以上も低い点数となりました。

今回は良い自己PRと悪い自己PRの例をそれぞれ約50件ずつしか用意できなかったにも関わらず、2値分類のAccuracyでは75%以上の良い性能を出すことができました。やはり自然言語処理においてBERTは強力ですね。


まとめ

まだデータ量が少ないので精度にバラツキはありますが、大量のデータがあれば更に実用的なサービスになります。
現在はMicrosoft社などが提供するAPIを利用すれば機械学習を用いた様々なサービスを作ることが可能です。今後も多くのサービスがリリースされていくと予想されます。


Twitter・Facebookで定期的に情報発信しています!

車を運転していてヒヤッとした経験はありませんか?

疲れや睡眠不足からついうとうとしてしまい、急ブレーキ...。
起こってはならない事故ですが、死亡事故の4割程度を居眠り運転による事故が占めるそうです。1人で運転していると頼れるのは自分だけ。音楽やガムで気を紛らわせるのも限界があり不安ですよね。
本日はAI・機械学習を活用した、居眠りを検知する仕組みをご紹介します。


実際に使ってみました。うとうとして目が半目になるとアラートを出します。


このAIは動画のように、目が半目になると"Wake up !"と注意を促します。
今回はおこなっていませんが、よそ見時間が長いことで注意することや、音でより強い注意をすることもできます。



作成にあたり、Open CVとDlibというオープンソースのライブラリを活用しました。
Open CV Dlib
Open CVで顔そのものを認識し、Dlibで目の認識、また目が閉じそうな時の認識をしています。



AI・機械学習が身近になり、「こんなところにもAIが!」と気付くシーンが多くなってきていますね。
今後も身近な活用例をご紹介していきます。


Twitter・Facebookで定期的に情報発信しています!

消費者や企業によって発生する廃棄物の処理・管理が課題として挙げられることが増えています。

包装材の削減などで最終的に発生するゴミの量が削減されてはいますが、ゴミの発生は無くなることはなく今後も少なからず発生します。
廃棄物の処理・管理は主に手作業で実施されていて膨大な労力とコストが生じています。これらの課題解決のためにAIが活用され始めています。機械学習、ディープラーニング、コンピュータービジョンなどのテクノロジーで、廃棄物管理の効率と生産性向上のためのソリューションが登場しました。

「ゴミ発生段階 / 収集中 / 廃棄物処理プラント」の3段階に分けて海外サービスを紹介します。


SMART WASTE BIN

ゴミ箱でゴミを識別し、種類ごとに分類します。

SMART WASTE BINはBin.e社によって開発されたシステムで機械学習でゴミ分類のルールを学習し、ゴミ収集前のゴミ箱段階で分類をおこないます。ゴミが捨てられる時に全ての分別がなされので廃棄物処理センターで大量の廃棄物を選別する必要がなくなります。

さらにシステムはゴミ箱がいっぱいになったことも検知し、収集スケジュールを無駄のないように最適化します。事前に決まっているスケジュールで収集トラックを発送する代わりに、ゴミ箱がいっぱいになった場所のみを訪問するように収集ルートを最適化します。これにより、人手不足であった課題が解消され、収集速度が向上し、人件費・燃料費も削減されます。

WASTE


Waste & recycling sorting systems(廃棄物およびリサイクル選別システム)

廃棄場で分類し、適切なゴミ処理をします。

ゴミ収集後に廃棄場で人が分別するのではなく、機械学習を使用して分別ルールを学習し、ゴミの種類に基づいて廃棄物を識別および処理します。様々なタイプの廃棄物の画像を大量に学習させることで、システムは廃棄物の分類を理解し、特定の特徴に基づいて学習したカテゴリーとゴミを一致させます。
人の業務をシステムが代わり、今まで悩まされていた人手不足や見落としを解消し、少ないコストで同じ業務をおこなっています。

2018年のWaste Expo conferenceにも出展した、Machinex社はリサイクルすべきカートン、プラスチックボトルを見つけるためにAIを活用しています。Machinex社によると、このシステムは毎分最大70回ピックします。それは人間の2倍の業務量で、イリノイ州の大手リサイクル会社であるLakeshore Recycling Systems社は同社のSamurAIを設置し、2人分の作業をAIが実施し年間約130,000ドルの削減に成功したと発表しています。

WASTE


GAIN technology

上記のようにゴミは収集の時点で分別されることが理想です。
しかし、全てのゴミを分別し切ることは難しく、収集後のゴミをリサイクル時に分別するAIが開発されています。

TOMRA社は、2019年にGAIN technologyを発表しました。リサイクルする上で廃棄物の純度を確保するにはカートリッジからシリコンを分離する必要があります。GAIN technologyはコンピューターセンサーを使用してポリエチレンストリームからポリエチレンシリコンカートリッジを取り外します。
何千もの廃棄物タイプの画像が与えられ、ディープラーニングを利用し分類する方法を学習しました。そのため、さまざまな種類のシリコンカートリッジ、ダブルカートリッジ、さらには変形または部分的に破壊されたカートリッジを画像を分けて訓練することなく識別できます。
TOMRA社によるとGAIN technologyはカートリッジの99%の排出を達成しています。

WASTE


効率の改善と人件費の削減

課題としてあげた「廃棄物の処理・管理には膨大な労力とコストがかかっている」ことの背景には労働人口の減少が考えられます。今後はエネルギー不足も課題となってくると予想できるため、限られたエネルギーを最適化していく必要が更に高まると想定されます。

今回紹介したゴミ・廃棄物処理方法は発生段階、収集中、更には廃棄物処理プラント...と全ての段階でより効率的な改善策の提案をしています。
機械学習、ディープラーニング、およびコンピュータービジョンテクノロジーの活用により廃棄物の収集・管理を効率的に実施することができ、労働力の削減、様々な人にとって働きやすい環境の構築を実現しています。


Twitter・Facebookで定期的に情報発信しています!

日々AIに関する技術は発展していき、その中でも自然言語処理に関するトピックには目が離せません。
Apple社のSiri、AmazonのAlexaなど人間と会話できる(対話型)AIを通して、そういった技術が私たちの身近な存在になってきました。
そのような中、2020年1月末にGoogleが凄まじいAIチャットボット「Meena」を発表しました。今回はこのMeenaから今後のチャットボットの可能性について考えていこうと思います。


そもそもチャットボットとは?何ができるのか?

一般にチャットボットとは、「音声やテキストを分析し、自動的に会話を行うロボット」のことを指します。
先ほど述べたSiriは、iPhoneの普及に伴ってその知名度は爆発的に上昇しました。

「明日の天気は?」「朝8時にアラームをセットして」など、話しかけるだけで応答してくれるシステムは確かに便利です。

しかしこのような技術を商業的に用いるとなると、どういったことが考えられるでしょうか?

例えば、「顧客からのメールや電話対応にチャットボットを用いて業務の効率化を図る」ことが挙げられます。 顧客からのサービスや製品についての疑問というものは、Web上のFAQを読めば分かるような事も多いでしょう。

そういった簡単な質問に対してチャットボットを活用すれば、実際の社員はそれ以外のクレーム対応など重要な対応に専念できます。

今後のAIの普及と共に「AIができること」と「人間が行うべきこと」の棲み分けが重要になってきます。


Meenaとは?既存のチャットボットとの違いは?

では本題の「Meena」について見ていきましょう。

SiriやAlexaは一問一答形式の応答には特化しています。しかし実際に"自然な"会話をしようとすると、 AIが答えやすいように人間側がちょっとした調整をしないといけません。

しかし今回紹介する「Meena」ですが、ディープラーニングの技術を用いて人間と"自然な"会話を行うことができます。

GoogleはこのMeenaの能力を定量的に評価するため、SSA(Sensibleness and Specificity Average)[整合度と特異度の平均] という新しい評価尺度を導入しています。

SSAは自然な会話に必要な特性を評価するための指標で、(AIの)応答が文脈において意味をなすか、 そしてそれまでの話に対して特有なものであるか(限定的なものか)を計測します。

一般に前者は既存のチャットボットなら可能ですが、後者を達成するのは難しいとされていました。

つまり、「私はテニスが好きです。」という発話に対して「私もです。」という応答はどんな話題にも当てはまりますが、 「私もです。ロジャー・フェデラーにはなれないけども!」という応答は当てはまる場面が限られてきます。 こういった応答ができるのがこのMeenaというわけです。

Googleはクラウドワーカーを使ってMeenaとの会話のサンプルを生成し、約100の会話で発話を評価しました。 このSSAに対して、Meenaは以下の好成績を叩き出しています。

meena1.png

[✳︎Google AI Blog より引用]

Humansは人間、Mitsuku、Cleverbot、DialoGPT、Xiaoiceは既存のチャットボットを指します。
Mitsukuはチューリングテストコンテストで有名な ローブナー賞 を過去4度受賞するほどのチャットボットでしたが、Meenaはこれに圧倒的差を付け、人間のスコアにかなり近い値を出しています。


Meenaとの会話

実際にMeenaと人間が対話しているテキストがGithub上に上がっているのでそれらの1つを見てみましょう。

まず比較のためにMitsukuと人間の対話を見てみます。

meena2.png

29行目で人間側が「遅刻した」と言っているのに、Mitsukuはその後3回も「あなたは遅刻したの?」と聞き返しています。ちゃんとした会話が成り立っていません。

ではMeenaと人間の対話はどうでしょうか。

meena3.png

論文のトピック(題名)について人間側が迷っているようですが、それに対しMeenaは「水中での呼吸法」とそこそこ的確な返答ができています。


チャットボットの今後の可能性

Meenaについて、今回Googleは「整合度と特異度にのみフォーカスしたが、今後の課題として他の属性(個性や事実性)にも注視していく」と述べています。

他にも、Meenaに安全性があるか、バイアス(偏見)を持たないかといった倫理的側面がチェックされるまで一般向けに公開しないとしています。

数年前 Microsoftが発表したチャットボット「Tay」が人種差別発言をしたことはまだ記憶に新しいです。 こういった差別的発言をしないようなチャットボットができる未来が楽しみです。

MeenaのSSAのスコアの高さには正直驚きを隠せませんでした。AIが人間の会話レベルに到達するのはそう遠くない未来かもしれません。

コールセンターでは、顧客からの製品に関する簡単な質問に答えるチャットボットを導入している企業もあるそうですが、 近い将来はクレーム対応など難しいタスクもこなせるようになるかもしれません。今回のMeenaの発表は、今後の技術発展への期待が止まらないものでした。


チャットボットを用いて改善できる業務

人間と同レベルもしくはそれに近いレベルのチャットボットが誕生したら何ができるようになるでしょうか。

先程述べたことも含め、以下のようなことが考えられます。

  • サービスや製品に関するお客様の疑問は全てチャットボットで対応できる(現時点で一部をAIに任せている企業もある)
  • 音声による感情分析と合わせれば、クレーム処理など高度な対応もできるようになる
  • お客様との会話データを全て残せるため、それらのデータからお客様のニーズをキャッチできる


こういったメリットはたくさんありますが、チャットボットと人間の応答を比較した時、ちょっとしたニュアンスの違いや倫理観のズレが生じる時もあるでしょう。
特にAIが犯したミスに関して、その責任の所在が「AI」にあるのか「AIを作った人間」にあるのかという議論も出てきます。
倫理的側面も含め、こういった問題との向き合い方がこれからの課題となってくるでしょう。


参考文献

Towards a Human-like Open-Domain Chatbot
Towards a Conversational Agent that Can Chat About...Anything


Twitter・Facebookで定期的に情報発信しています!

こんなチャットボットを作りたい

仕事の休み時間に料理好きのメンバーからこんな話を聞きました。「なんでもいいが一番困る!!」
なんの話か分かりますでしょうか?この記事にたどり着いたあなたなら分かるはず・・・。


そう、「晩ご飯何でも良い問題」です!


この問題、調べてみるとかなり多くの主婦の方々が悩んでいて、夫婦喧嘩の原因の1つでもあるようです。

奥さんは、洗濯をしたり、毎日食事を考えてたりでやることがいっぱい。
対して旦那さんは、仕事で疲れ果てて食事を考える元気もない。

最近は共働きの夫婦も増えています。仕事だけでも大変なのに料理のことも考えるなんて「辛いな・・・。」と思う日もありますよね。

でも栄養をしっかり取るために料理はしたい・・・。
どうすればこの問題を解決できるでしょうか?


「自動で献立を決めてもらおう!!!」


そうすれば、「今日の晩ごはん何にしよう・・・。昨日は麻婆豆腐、一昨日は八宝菜・・・。」と毎日考える必要はありません。

こんな不安もありますよね。
「できれば買い物行きたくない・・・。」
「食べたくない気分の料理も紹介されたくない!」
このような気持ちも理解して、献立を紹介してもらえれば、毎日楽ちんです!


晩ご飯何でも良い問題を解決します。

こんなことができます。

  • 冷蔵庫にある食材からおすすめのレシピを紹介

  • 栄養バランス・調理時間も教えてくれる

  • 気分に合わせたレシピを紹介


お料理ボットってどうやって使うの?
①冷蔵庫の食材を入力する
②おすすめのレシピが表示される
③リンクをタッチしてレシピの詳細を確認


お料理ボットの流れはこれだけ!左側がAIが送るチャット、右側が私達が送るチャットです。

①冷蔵庫の食材を入力する
今回は「豚バラ」と「はくさい」を入力しましたが、「鶏肉」「ひき肉」「ほうれんそう」など何を入力しても大丈夫です。

ffbed1a0ae2ef04e379f43984f1fb0f8da66251f.png


②おすすめの料理が表示される
先程2つの食材を入力したところで、チャットボットがおすすめの料理を5つまで表示してくれます。
適当にレシピを表示しているのではなく、2つの食材を用いたレシピで人気トップ5を表示しています。

5ca426918a68f93f92e89916aa8846e65403456f.png


③リンクをタッチしてレシピの詳細を確認
料理名は青色の文字で表示されています。
これはリンクになっていて、タッチすると料理の詳細を確認できます。

79f57ed3b9c2859eb2b1fef7d66405332ec1e3f2.png 8a50fcc5262bd189db12f82acd1b893efe2df2b3.png


もっと活用したい

なんとなく雰囲気はつかめましたか?
お料理ボットは冷蔵庫の食材を入力するだけで、その食材を使った人気料理とレシピを紹介します。

今の実装段階では「作れる人気なレシピの紹介」はできても、栄養バランスやあなたの気分を考えたレシピの紹介はできていません。
「気分や昨日の食事の内容をチャットボットに入力すると、栄養バランスを考えた料理を紹介してくれる機能」を実装中です。


お料理ボットを使うとこんな風に生活が変わります。

今まで

あなた「今日の晩ごはん何が良い?」
相手 「うーん、なんでもいいよ。」
あなた(何でも良いが一番困る!!)


お料理ボットを使うと

あなた「今日はどんな気分?」
相手 「うーん、仕事で疲れちゃったな〜。」
あなた「お疲れ様。(お料理ボットに気分を入力)」
ボット「お疲れ様!今日は豚汁なんてどうかな?温かいスープと、お肉でエネルギー補給ができるよ!」
あなた「ありがとう!助かったよ!」


お料理ボットとこんな風に会話をしながら献立を決められれば、もっと楽しくお料理生活を楽しめるようになると思いませんか?


  • 冷蔵庫にある食材からおすすめのレシピを紹介

  • 栄養バランス・調理時間も教えてくれる

  • 気分に合わせたレシピを紹介


これらの機能の他にも、お料理ボットには便利な機能を追加することができます。
例えば、「赤ちゃんのための食事が知りたい」や「好きな飲食店はココ!」などと言えば、それに合ったレシピを紹介してくれるなどなど・・・。


お料理ボットは、あなたの悩み・願いに合わせて料理生活をさらに楽しいものにすることができます。

  • チャットボットについてもっと知りたい!

  • 料理でこんな悩みがある!

  • こういうことできないの?

等、是非ご相談ください!


献立のリンク先

https://www.kyounoryouri.jp/recipe/3293_%E3%81%98%E3%82%83%E3%81%8C%E3%83%81%E3%82%B2.html


Twitter・Facebookで定期的に情報発信しています!

第1弾、第2弾に続き



 今回は第1弾で取り上げたこちらを検討していく。

課題①「電力需要量とのバランスが取りにくい」、課題③「無駄な待機運転の時間がある」への解決策

~発電量予測~
 


 ここでの「発電量予測」とは、発電装置周辺の気象・海象データを説明変数として発電量を予測することである。電力は常に需要量と供給量(発電量)が同量でなければ、停電を起こしてしまう。それを防ぐために発電量が予測されていれば、需要と供給のバランスを保ちやすくなる。また発電装置の無駄な待機時間も削減され、設備稼働率も向上する。このようにして、課題①「電力需要量とのバランスが取りにくい」、課題③「無駄な待機運転の時間がある」を解決する。

 更に第二弾で紹介した「電力需要量予測による制御」と組み合わせれば、発電量と需要量をより正確に一致させることができる。

 今回は発電方法を洋上風力発電としてこの「発電量予測」を実装する。

news4049_pic1.png

図1 ドイツの洋上風力発電


目次

  1. データセットについて
  2. 予測モデルについて
  3. 精度の向上
  4. 結果・考察・課題
  5. 参考文献


1. データセットについて

 1章でも述べたが、発電量予測は発電装置周辺の気象・海象データを説明変数とすべきだ。しかし、風速や天候などの気象データ、波高や波向などの海象データ、そして発電量の三つ揃ったデータセットを手に入れるには、造波装置を搭載する大型水槽での模型試験、または実海域での実証試験を行うしかない。大規模な装置を使わずに単純なモデルで模型試験を行い、そこからデータセットを得ようというアイデアもあるが、それは一度おいておき、今回は表1のようなデータの種類を用いることにした。表2がデータセットであり、2016年1月1日0時0分から2017年12月31日23時45分までの二年分のデータ値が記入されている。

表1 データの種類
スクリーンショット 2020-01-29 14.19.11.png


表2 データセット
スクリーンショット 2020-01-29 14.50.50.png

 訓練データとして表1のデータを三つとも全て用い、テストデータは発電量を予測したいので、「DE wind offshore generation actual」とする。


2. 予測モデルについて

 2章のデータセットは時系列データなので、時系列の分析に強いLSTMをモデルとして採用した。

 LSTMとは、ディープラーニングの一種であるが、過去の情報をモデル内に保持していることが一番の特徴である。過去の情報といっても、少し前からの情報(短期記憶)や、かなり前からの情報(長期記憶)がある。LSTMはそのどちらも必要な分保持し続けるような仕組みになっている。

 重みの更新の方法はディープラーニングの一種なので誤差逆伝播法となるのだが、LSTMの場合、誤差が時間を遡って逆伝播することから、「通時的誤差逆伝播法BPTT(Backpropagation Through Time)」と呼ばれる。

 ところが、長い時系列に対してこれを行うと、勾配が不安定になったり、計算量が膨大になり、分析に時間がかかってしまう。そこで、連なったLSTM層の逆伝播のつながりだけを適当な長さ(「ブロック長さ」)で切断することで、この問題を解決することができる。このようなBPTTを「Truncated BPTT」と言い、この切断した一つの単位を「LSTMブロック」と呼ぶ。そして、そして全てのLSTMブロックを最初から最後までまとめたものを「Time LSTM層」と呼ぶ。

 今回は過去の「DE wind offshore generation actual」(発電量)のデータ値とその他の二つの特徴量から、1時間後の「DE wind offshore generation actual」(発電量)を予測するというモデルになっている。


3. 精度の向上

 予測精度を向上させるために下記を実施した。

  • 「Time LSTM層」を増やす
  • 「Time LSTM層」のユニット数を増やす
  • 活性化関数を変える
  • 「ブロック長さ」を変える
  • 最適化アルゴリズムであるAdamの学習率を変える


 この中で特に精度に差が出たのは、「「ブロック長さ」を変える」ことであった。ブロック長さを5、10、20、30と変えていくと、二乗平均平方根誤差RMSEは表3のようになる。この時、「Time LSTM層」は1つ、「Time LSTM層」のユニット数は20つとした。

表3 ブロック長さと誤差
スクリーンショット 2020-01-29 15.08.25.png

 また、図3、4はそれぞれ最も誤差の大きい、ブロック長さが5の時と、最も誤差が小さい、ブロック長さが10の時の実測値(real)(黒い破線)と予測値(predicted)(赤い実線)のグラフである。但し、発電量の値は0から1に正規化してある。図4の方が、黒い破線が赤い実線と重なり消えていて、予測が正しいということが分かる。

スクリーンショット 2020-01-29 15.15.07.png

図3 ブロック長さが5の時


スクリーンショット 2020-01-29 15.16.28.png

図4 ブロック長さが10の時

 また、「最適化アルゴリズムであるAdamの学習率を変える」ことも精度を変化させた。結果的に、学習率が0.0007の時に最も精度がよくなった。(図3、4は学習率0.0007の場合)


4. 結果・考察・課題

 図4はブロック長さを10、Adamの学習率を0.0007とした結果であるが、これは私が今回実装した中で最も精度の高い結果である。全体的にかなりの精度で予測できていることが分かり、時系列データに非常に強いLSTMをモデルとして採用していることが大きな要因である。

 しかし、発電量が非常に多い時(発電量を0から1に正規化した時の0.95以上)の予測精度は、今後、発電量予測を実用化する場合には必ず解決しなければならない問題である。当然であるが沢山発電することができる時というのは非常に重要であるからだ。このような結果を招く理由として考えられることは、これらが挙げられる。

  • 訓練データとして気象・海象データがない(特徴量が足りない)
  • 何らかのパラメータのチューニングで失敗している
  • 測定期間が短すぎる


私としては、パラメータのチューニングについては非常に多くのパターンを試してみたので、それによってこれ以上大きく変化するとは思えない。やはり訓練データとして気象・海象データがないことが一番の原因ではないかと考えている。自然の力を利用して発電しているのにも関わらず、自然の力に関するデータなしに、過去の発電量、容量上限、シェア率だけから発電量を予測しては精度は期待できないであろう。もし気象・海象データ(具体的には、風速、風向き、天候、波高、波向など)と発電量のデータセットを手に入れることができれば、実用化も遠くない予測モデルが完成するかもしれない。1章でも触れたが、大規模な装置を使わずに単純なモデルで模型試験を行って、そこからデータセットを得ることについても今後模索してみようと思っている。


5.参考文献

  • 斎藤康毅『ゼロから作るDeep Learning ② ー自然言語処理編』株式会社オライリージャパン, 2018


Twitter・Facebookで定期的に情報発信しています!

このような課題はありませんか

  • 不良品検査の人員不足で外注しており、コストがかかっている...【コスト削減】
  • ノウハウが引き継げずにベテラン検査員が退職し、検査に膨大な時間がかかっている...【人依存の解消】
  • 利益率向上・働きやすい環境のために生産性を上げたい...【生産性の向上】
  • 人によって判定にばらつきがあるため、品質にもばらつきが出てしまう...【品質向上】


どれも製造業のお客様からよく聞くお困り事ですし、改善には時間もお金もかかります。しかし、改善しないと品質低下を招き、お客様に不満を持たれてしまう可能性もあります。
これらのお困り事を機械学習で解決する、機械学習を活用した物体判定をご紹介をします。


画像を用いた物体判定の仕組み

画像認識の際には「画像のどこに何が写っているのか」を認識するためのモデルが必要です。機械学習を用いて学習データからこのような検出・判別するモデルを構築します。モデルをあらかじめ構築しておいて、認識する画像に対して判別結果を出力する仕組みを作ります。

モデルで実際に画像を判別する際には、画像の中から 特徴抽出する必要があります。画像の局所的な特徴の抽出や画像に含まれるノイズの除去などを、画像処理の手法や統計的な手法によっておこないます。判別に必要のない情報を除いた上で、判別結果を計算することができます。

抽出した特徴はいくつかの一定の大きさの領域にまとめた後、プーリング と呼ばれる処理でまとめられた領域を1つの値で代表します。画像の空間的な情報を削除し、判別に必要な情報のみを残します。

特徴抽出・プーリングの実施後には、事前に用意していたモデルによって画像を判別します。

また、ディープラーニングに代表される学習手法は特徴抽出・プーリングの処理をひとまとめにして、それらの手順をさらに繰り返すことで認識精度を高めています。


▼画像撮影から物体判定、振り分けまでのイメージ
画像を撮影しどこに物体があるか認識し、物体が何であるか判定し、判定内容によって振り分け(行動)します。
スクリーンショット 2020-01-29 15.05.29.png 1.カメラを設置し、動画で物があることを認識・検出します。(物体検出技術)


2.学習時に付けたラベルをもとに、検出した物が何であるか判定します。

学習は画像に対してラベル(正解)をつけておこないます。実際の運用では、カメラで検出した物体が学習画像のどれに近しいかと判定します。


3.判定結果により適切な行動をします。

機械学習の範囲からは出ますが、判定した内容をもとに次の指示を出します。例えば、ベルトコンベアー上のものがA製品であれば右に振り分け、B製品であれば左に振り分ける、または不良品であればアラートを出すことができます。


課題別 機械学習事例 コスト削減

点検作業の自動化
カメラで撮影した建物画像からひび割れ等の老朽化箇所を検出します。人からシステムに役割を変えることができ、人件費削減だけではなくかかる時間も短縮することができています。

倉庫内配置の適切化
倉庫内にカメラを配置し、撮影することで作業社の行動や物の位置を把握し分析します。倉庫内の動線や配置の最適化によって業務を効率化し、コスト削減を実現します。

特定箇所への農薬散布
企業が農業へ参入したことで、日本では集約農業から大規模農業へと転換が進んでいます。広大な農地で作物を育成する際に、ドローン等で空撮したデータから必要な箇所を割り出して、病害虫が発生している箇所ピンポイントに農薬を散布します。農薬使用量を削減できるだけでなく、他作物へのダメージを減らすことができます。


人依存の解消

受注量予測
過去の受注量のメカニズムからどれだけの発注があるか予測します。ベテランにしかできなかった発注業務の敷居を下げることで、限られた人しかできなかった業務を分配することができます。

野菜収穫の自動化
ノウハウが重要な収穫時の見極めをAIがおこないます。AIが判断した後にロボットに信号を送ると自動で収穫をおこなうマシンも検討できます。


生産性の向上

問合せへの自動応答
社内からの問合せ件数は日にかなりものです。その問合せをチャットボットで自動応答にすることができます。質問者も作文に時間をかけずに気軽に質問することができます。

居眠り検知
同じ作業が続く検品等で、うとうとしそうになってしまうことがあります。目の開きがあまくなるとアラートが鳴り、目を覚ましてくれるシステムも構築できます。


品質向上

高解像度画像の作成
最新のAI技術では荒く見づらい画像を高解像度に直すことができます。品質で失注していた案件に、より良い提案が出来る可能性が上がります。

コンベア内の品質チェック
コンベアを流れる物体が良品か不良品かを判定します。不良品可能性のある物は人が見るまでもなく振り分けることで、人の疲労による見落としを減らすことができます。


機械学習検討の作業プロセス

▼機械学習を検討する際のプロセスです。
スクリーンショット 2020-01-29 15.21.39.png

・事前検証

対象/判断の基準/期待する精度を基に適切な学習手法・アルゴリズムを設定します。


・システム開発

画像処理及び画像判定システムの検証・開発をおこないます。モデルへ画像と正解ラベルを合わせて学習させ、テストデータで事前検証で決めた精度が出せるようにチューニングします。


・テスト運用

運用に限りなく近いデータでトライアル運用をおこない、運用面や精度面での問題や課題を発見し対処します。


・リリース

テスト運用終了後に正式リリースとなります。必要に応じて、判定の精度向上のための再学習や活用範囲拡大のための追加学習を実施します。



当社は機械学習を活用したソリューションをご提案しています。

  • 自社にあるデータを2次活用したい
  • 画像データを活用したAIを作成したい
  • 既にAIシステムを利用しているが思うような効果が得られていない
  • 機械学習ではなにが出来るのか興味がある


このようなご相談は画面右上の[お問い合わせ]までご相談ください。


acceluniverse


Twitter・Facebookで定期的に情報発信しています!

機械学習では、訓練データとテストデータの違いによって、一部のテストデータに対する精度が上がらないことがあります。

例えば、水辺の鳥と野原の鳥を分類するCUB(Caltech-UCSD Birds-200-2011)データセットに対する画像認識の問題が挙げられます。意図的にではありますが訓練データを、

  • 水辺の鳥が写っている画像は背景が水辺のものが90%、野原のものが10%
  • 野原の鳥が写っている画像は背景が水辺のものが10%、野原のものが90%

となるように分割します。このときに、訓練データの中で「背景が野原で水辺の鳥」の画像や「背景が水辺で野原の鳥」の画像が少なく、同じようなテストデータに対して精度が上がらないことがあります。

Alt text

以降では、テストデータ全体の精度をaverage accuracyと呼ぶのに対して、このようなデータに対する精度をrobust accuracyと呼ぶことにします。パラメータの数が訓練データの数よりも多い(overparameterized)ニューラルネットワークでは、モデルの複雑度が高いために過学習しやすく、average accuracyは高くともrobust accuracyは低くなりがちです。

論文"Distributionally Robust Neural Networks"では、上記のような訓練データとテストデータの分布が異なるときのrobust accuracyを上げる最適化手法について説明されています。パラメータの多いニューラルネットワークがよく使われる画像認識や自然言語処理などのタスクに対して同じような最適化手法を適用でき、今後も広く使われる手法かもしれません。

この記事では論文で説明されていた手法について、簡単に概要を説明しようと思います。

"distributionally robust optimization"とは?

訓練データよりも多くパラメータが存在するニューラルネットワークでは、学習データにおけるロスの消失による過学習が問題となっていました。そのようなときは一般には平均的に汎化誤差(generalization gap)が小さくなるように最適化するのですが、どうしてもロスが最も大きいworst-case groupに対しては、依然汎化誤差大きいままになってしまいます。

そこで考えられた手法がdistributionally robust optimization(以下DRO)です。DROは一言で言えば最も大きいロスでの最小化です。

\[ \min_{\theta \in \Theta} \sup_{Q \in \mathcal{Q}} {\rm E}_{(x,y)\sim Q}[l(\theta;(x,y))] \]

\( \sup {\rm E}[l(\theta;(x,y))]\)が表すのがworst-case groupの平均のロスとなります。\(Q\)が表すのが分類する各グループ\(g\)ごとの分布の線形結合となるのですが、最小化は線形計画法のアルゴリズム(単体法)で行われます。そのため、最適解は実行可能領域の頂点、すなわちworst-case groupのみの分布における最適解と一致します。

\[ \min_{\theta \in \Theta} \max_{g \in \mathcal{G}} {\rm E}_{(x,y)\sim P_{g}}[l(\theta;(x,y))] \]

worst-case groupの分布では平均のロスが最も大きくなります。DROはその分布でのロスの最小化を目的とするアルゴリズムだと言えます。これまでの機械学習は平均的な汎化誤差を正則化(regularization)などによって低減させていましたが、DROはworst-case groupの精度の向上、つまりrobust accuracyの向上が目的です。

では、実際にどのようにしてworst-case groupの精度を向上させているのでしょうか?次節からはその具体的な手法について説明します。

従来手法によるrobust accuracyの向上

DROで使われる正則化の1つとして重み減衰(weight decay)が挙げられます。すでに様々な機械学習の中で使われている手法であり、例えば有名なものではL2正則化が挙げられます。

\[ E(w) + \cfrac{\lambda ||w||^{2}_{2}}{2} \]

論文では、画像認識のモデルであるResNet50においてL2正則化をするとき、\(\lambda\)は通常小さな値\((\lambda=0.0001)\)が設定されるが、この値を大きくするとrobust accuracyが上がるということが述べられています。つまり、強い重み減衰(strong weight decay)が手法の1つとして考えられます。

また、もう1つの正則化としてearly stoppingが挙げられます。こちらも機械学習でよく使われる手法ですが、想定されるニューラルネットワークのパラメータ数が多く学習数が大きいとすぐに過学習するため、early stoppingが有効だと言えます。

検証

それではDROの検証結果について見てみましょう。ベンチマークとしてERMモデルとの比較を行います。最初に述べたCUBのWaterbirdsの分類タスク(ResNet50による)の他に、CelebAデータセットにおける髪色の分類タスク(ResNet50による)と、MultiNLIデータセットにおける自然言語推論タスク(BERTによる)で比較しています。一般的な正則化(Standard Regularization)と前節で述べた2つの手法を試したときのaverage accuracy、robust accuracyは以下のとおりです。

Alt text

この結果からどのタスクにおいても、ERMではaverage accuracyに比べてrobust accuracyが大幅に低下したのに対して、DROのstrong weight decayとearly stoppingによってrobust accuracyが大幅に低下するのを防いでいることが確認できると思います。

また、CelebAに関してaccuracyの収束性についても見てみましょう。

Alt text

worst-case groupである「Blondの髪で性別がmale」の判別において、strong weight decayを用いたDROがそれぞれのグループで他の手法よりも良い収束性を持つことが確認できます。

グループサイズを利用した正則化

今回の論文では分類するグループの大きさを利用したDRO(group-adjusted DRO)についても述べられています。グループ内のデータの数を\(n_{g}\)とすると、最適化するべき目的関数は、

\[ \min_{\theta \in \Theta} \max_{g \in \mathcal{G}} {\rm E}_{(x,y)\sim P_{g}}[l(\theta;(x,y))] + \cfrac{C}{\sqrt{n_{g}}} \]

となります。ハイパーパラメータ\(C\)を用いた正則化項を付け加えるアイディアです。\(n_{g}\)の平方根の逆数を掛けることで、グループごとのデータ数を考慮した汎化をおこなうことができるようです。このgroup-adjusted DROのaccuracyは以下のようになっています。

Alt text

robust accuracyにおいてさらなる改善が見られますね。バリデーションによって\(C\)の値さえうまく決めることができればかなり役に立つ手法だと言えます。

importance weightingとの比較

実は同じような解決策として、importance weightingという従来手法が存在します。これはロスに重み付けした上で最小化を行う手法です。これはミニバッチからデータを等確率でリサンプリング(RS)することでrobust accuracyを上げる手法だそうです。こちらについてもベンチマークを見てみましょう。

Alt text

ERMよりもrobust accuracyが上がっていますが、DROほどではありません。DROは従来手法よりもrobust accuracyの向上に有効だと言えます。

終わりに

今回紹介した論文では訓練データとテストデータの分布の違いを考慮した手法であるDROについて簡単に紹介しました。従来よりもrobust accuracyを大きく上げたという点でより注目される手法だと思います。

しかし、なぜこのように正則化をすると精度が向上するのかという問いに対する明確な答えがまだない状態です。この論文を足がかりにrobust accuracyが上がる数理的なメカニズムが解明されれば、様々なモデルで汎化性能の向上が期待できるでしょう。

参考文献

DISTRIBUTIONALLY ROBUST NEURAL NETWORKS


Twitter・Facebookで定期的に情報発信しています!

はじめに

昨日まで開催されていたKaggleの2019 Data Science Bowlに参加しました。結果から言いますと、public scoreでは銅メダル圏内に位置していたにも関わらず、大きなshake downを起こし3947チーム中1193位でのフィニッシュとなりました。今回メダルを獲得できればCompetition Expertになれたので悔しい結果となりましたが、このshake downの経験を通して学ぶことは多くあったので反省点も踏まえて今回のコンペを振り返っていきたいと思います。


コンペ概要

幼児用教育アプリを使う子ども達の能力を予測するコンペです。具体的な予測は次のようになります。
アプリ内でプレイ可能なゲームがそれぞれAssessment、Game、Activity、Clipの4つの分野に分類されます。そのうちAssessmentに分類されるゲームをプレイした際の問題の正解率を過去のプレイ履歴を元に0、1、2、3の4段階で予測します。モデルの評価指標はQuadratic Weighted Kappa (QWK)が採用されており、これがこのコンペで大きなshakeを生む原因の1つだったと言えます。
実際に多くの人がshake upまたはshake downし、private leaderboardにおいて1000位以上順位が動いた人もたくさんいました。


取り組み

以下で私がこのコンペで行った取り組みを記述していきます。


EDA

コンペの序盤は公開してくれているNotebookを元にEDAを行いました。
中盤以降はゲームの細かいプレイ履歴を見るためにテーブルデータそのものを見て、データ中の項目が何を示しているか注意深く観察するようにしました。


特徴量作成

特徴量は公開Notebookをベースとしました。そこにEDAやDiscussionを元に特徴量を作成して、モデルの精度が向上するかどうかトライアンドエラーを繰り返しました。


データの前処理

testデータの各特徴量の平均値をtrainデータに合わせて変換しているNotebookを見つけ、自分のパイプラインに取り込んだところ精度が大きく向上したのでそれ以降ずっとこの手法を取り入れていました。
しかし、正直なところ過学習の原因になりかねない危ない処理だとも考えていました。


モデル

今回はLGBMとXGBoostを試しました。それぞれのモデル単体ではLGBMが良い性能を示し、アンサンブルで2つのモデルを用いても性能の向上が見られなかったため最終的にはLGBMのみ使いました。
LGBM1つの時に比べて、Local CVのスコアが高くなるランダムシードを5つ選びseed averagingを行ったモデルがpublic scoreで少し良い結果でした。今回のコンペでは評価指標のQWKが原因でpublic scoreが不安定であったので、アンサンブルをせず1つのモデルの結果を提出しているチームも多かったです。しかし、private scoreではやはりアンサンブルを用いた方が結果が良かったようです。


データの後処理

予測結果としては問題の正答率から0、1、2、3のラベルに分類するタスクでした。しかし、多くの参加者がregressionを使って連続値で予測した後に閾値を決めてそれぞれのラベルに分類する手法を取り入れていました。
この閾値を決定する方法が2つありました。1つはvalidationスコアからQWKが最適化されるように閾値を決定する方法。もう1つはラベルの割合がtrainデータと一致するように閾値を決定する方法です。
trainデータとtestデータの分布が似ていると仮定し私は後者を選びました。


結果

冒頭でも述べましたが最終日に銅メダル圏内に突入したものの、モデルがpublic leaderboardに対してひどい過学習を起こしておりprivate leaderboardでは900位近く順位が下がり3947チーム中1193位となりました。


反省

自分なりに大きなshake downの原因が何だったかいくつか要因を考えてみました。

まず第一にデータの前処理でtestデータの各特徴量の平均値をtrainデータの平均値に合わせたことです。 この処理はtrainデータとtestデータの分布の差を少なくするためのものでした。しかし、testデータがtrainデータと同じ分布に由来していた場合に、平均値を調整することでpublic scoreが上がるのはpublic leaderboardに過学習していると考えられます。
上位陣がこの前処理を行っていないことから、実際にこの処理がpublic leaderboardに過学習する原因になっていると言えます。

次にshake downの原因として考え得るのは、予測ラベルの割合をtrainデータに合わせにいったことです。この処理ではtestデータの正解ラベルの割合がtrainデータの割合と似ていると仮定していますが、public testデータが少ない状況でこの処理は危険であったと思います。
上位陣の解法でもこの手法は使わずに、validationデータに対してQWKを最適化して閾値を決めていました。

コンペ終了後に最終のsubmissionとして選ばなかったものを見ると、過学習を起こしうる処理を使う前のものではメダル圏内のscoreのものもありました。
このコンペを通してpublic scoreを改善することよりもロジカルに考えてパイプラインを構築することが大切だと実感しました。特に今回はtestデータが非常に少なく大きなshakeが起きる可能性が高いと自覚しながら、また過学習になりかねない処理だとも自覚しながら、public scoreを追ってしまったことは反省しなければならないところです。


まとめ

銅メダル圏内から900位近くshake downするという悔しい経験ではありましたが、そこから学ぶこと多くありました。やはりモデル構築の際は論理的に筋の通った処理をする必要があるなと感じました。今回の反省を活かし上位陣の解法から学べることは吸収して精進していきたいと思います。


Twitter・Facebookで定期的に情報発信しています!

こんにちは。
今回は「アイトラッキング」について紹介します!

皆さんは「アイトラッキング」という技術をどのくらいご存知でしょうか?
「アイトラッキング」とは、人間の視線の動きを追跡・分析する手法であり、視線推定技術とも呼ばれます。
この技術により、これまで調査者側からではわからなかった被調査者の無意識の「本音」がわかるようになりました。

この記事ではそんな素晴らしい技術、「アイトラッキング」がどんな場所、場面で使われているのかを調査し、その可能性について探っていきます。

目次

1 なぜアイトラッキング技術?
2 アイトラッキング技術の活用
 A マーケティング
  B 防犯・事故防止
  C ユーザーインターフェイス
  D スポーツ
  E 都市環境
  F 学術・医療
3 まとめ

1 なぜアイトラッキング技術なの?

被調査者の意見を知りたいと思った時、例えば消費者に何か意見を求める時、アンケートやインタビューをしています。
しかし、これらは個人の意識が無意識で入り込んでしまうため、結果が正確であるとは断言できません。
とっさに見栄を張ってしまったり、質問者に求められている答えをしてしまったり(つまりは忖度ですね笑)、選択肢の番号の流れに乗って選んでしまったり...ということはないでしょうか?

アイトラッキング技術は被調査者の無意識の自然な目の動きを追うので、個人の意識的な介入が少なく、本音を読み取ることができます。

人は生活の中で自然と目を動かします。そこから得られる情報は、どんなものに目をつけたのか、何に興味を持ったのかなど、その人に関する詳細なデータです。
アイトラッキング技術はそれらの膨大な情報を読み取ることができ、それを分析し活用することができれば様々な分野で有効活用できるというわけです。

2 アイトラッキング技術の活用

アイトラッキングの技術は主に「業務効率化」のために利用されます。
ここでは各分野のアイトラッキング技術の活用事例を紹介し、今後の可能性について探っていきます。

A マーケティング

アイトラッキング技術はその特徴からマーケティングに活用されることが多いようです。
ここでは、顧客の注意や興味を知るためにアイトラッキング技術が使われています。

  • 興味検知
    スーパーではたくさんの商品が棚に陳列されています。
    ある特定のものを買いたいとしましょう。
    皆さんは何を基準に買う商品を決めますか?値段、ブランド、それともパッケージでしょうか?

    アイトラッキング技術は、顧客が商品を決める時の目の動きに着目し、「誰が何に興味を示したか」だけでなく、一番初めに見た要素、一番長く見られた要素、頻繁に見られた要素、あまり見られなかった要素、また他の商品のどこと比較されたのかなどを明らかにします。商品を作るメーカーは、デザインを変えるのが良いか、だとしたらどんなデザインが良いか、値段は適正かなどを検討することができます。

    また、店で商品を買う時、POPをみて興味を持ち、ついつい買ってしまった、または目につくところにあったから買ってしまった、なんてことはありませんか?
    アイトラッキング技術を使うことで、効果的なPOP・広告作りや、効果的な売り場づくりを人の目の動きというデータに基づいて行うことができます。
    これを真剣に行えば、売り上げアップが期待できそうですね。
    買い物.png

B 防犯・事故防止

  • 不審者検知
    明らかに不審な動きをしている人を検知します。例えば、必要以上にキョロ  キョロして周りを気にしていたり、監視カメラを必要以上に注視していたり...という人を認識します。
    顔認証を組み合わせればホームセキュリティに応用できたり、動きまで認識できれば万引きなどの犯罪防止に役立つとでしょう。

  • 運転中の事故防止
    近年では危険運転防止のため、ドライビングレコーダーの利用が増えています。ドライビングレコーダーは車の外側を見るものですが、ここでは車の内側を見ます。

    運転者の視線を見ることで、運転中の意識喪失や居眠りの検知をしたり、運転中の脇見を検知することができます。これはもし事故が起こった時、過失なのか、故意なのか判定するのに役立ちます。
    また、視線や顔の動きから運転を採点し、アドバイスしてくれる機能があったら楽しいですし、一方で、緊張感・危機感を持って運転できるかもしれません。
    事故防止だけでなく、運転中の姿勢変化により発生する視線の動きを観察することで、疲れにくい車の開発にも活用されています。

  • 検査の見落とし防止
    何かを検査する時、人間での検査だとら何かの拍子に見落としてしまうことがあります。視線を感知することで防止することが出来ます。見落としが起こった時にも、視線を確認することで何が起こっているか分析でき、再発防止に繋がります。

    居眠り運転.png

C ユーザーインターフェイス

  • 操作パネルのデザイン検証
    現在、何かサービスを受けるとき電子機器で操作が多くなりましたね。(例えば、飲食店の券売機、案内や空港での航空券発見など)。ちょっと見づらいなとか操作しづらいな、など感じたことはありませんか。
    アイトラッキングの技術は、人の視線の動きやどこに長く注目しているか(興味を持っているかもしれないし、わかりにくくてずっと見ているのかもしれない)を読み取ることによって、消費者が電子機器端末を快適に使えるようにするためのきっかけを与えてくれます。例えば、効果的な電子メニューの配置や見せ方、視線の動きから好みを分析しリコメンド、デザインは適切かの検証などがあります。

D スポーツ

プロ選手とアマチュア選手の視線を認識し、何を見てどんな動きをしているか分析をすることで、良い動きを見極めるヒントになり、選手のレベルアップのために役立ちます。
他分野でも熟練技術者の技術の継承にも同じように役立てられます。
フィギュアスケートなどの一部のスポーツでは、演技の出来栄えを審判が決定します。アイトラッキング技術を用いることで、審判が何を見て、どんな基準で点数をつけているのかを明らかにし、より良い演技のために活用されている事例もあります。

E 都市環境

人々がより快適な生活を送るためにも役立てられています。
近年、日本の都市に訪れる、もしくは居住している外国人の方々が増加しています。彼らが国内を移動する際、きちんと地図を読めているのか、標識を認識しているのかなどを視線の動きから分析し、改善に役立てます。
また、避難訓練時に視線計測を行うことで、避難者にとって標識や案内が正しく、そしてわかりやすいものであるかを検証し、その結果をもとに改善をすることで効果的な標識のデザインや設置場所を検討することができます。室内でも避難誘導標識や消火器標識の設置位置が適切かどうかをあらかじめアイトラッキング 技術を用いて検証することで、非常時の被害を最小限に抑えることができます。

F 学術・医療

心理学や脳神経学において、人間の思考・言動における視覚情報の影響や、認知プロセスの究明に利用されています。また、医療の分野では眼球疾患や精神・神経疾患の研究にも利用され始めているようです。

3 まとめ

今回はアイトラッキング技術の活用事例とその可能性について紹介しました。この他にも、パソコンやゲームを視線だけで操作することもアイトラッキング技術を用いることでできるようになるようです。また、子供の学習時、どこをどのくらい見ているかを分析することで、優秀な子が何に着目するのかや、きちんと見るべきポイントを抑えられているのかを明らかにすることで、勉強時間からではわからない学習の詳細な部分が見えてくるでしょう。

ただ、アイトラッキングは技術にすぎません。得られたデータ、事実からその裏にあるもの(その行動の背景)について考えることが必要不可欠です。技術が進歩しても人間が考え、検証する必要があります。
アイトラッキング技術は今後ますます活用されていくでしょう。将来性があるので、今後ますます活用されていくのではないでしょうか。


Twitter・Facebookで定期的に情報発信しています!

はじめに

KaggleのNFLコンペで2038チーム中118位となり、銅メダルをとることができました。以下に、参加してからの取り組みや、反省点を書いていきたいと思います。

コンペ参加前の状況

10ヶ月ほど前にTitanicコンペに参加してから、「Predicting Molecular Properties」と「IEEE-CIS Fraud Detection」というコンペに参加してみましたが、公開されているカーネルを少しいじってみた程度でメダルには到底届きませんでした。

コンペ概要

簡潔に書くと、アメフトのワンプレーごとに、ボール保持者がランプレーでいくらヤードを稼げるか?を予測するコンペです。しかしアメフトのルールを知らないため、はじめは全くわからなかったです。

アメリカンフットボールでは、野球のようにプレーごとにチームが攻撃と守備にきっちり分かれているようなのですが、今回の予測はこの攻撃側のランプレーに関係します。

攻撃側のチームはボールを保持し、相手陣地にできるだけ深く攻め込もうとするのですが、その方法が2パターンあります。パスプレーとランプレーです(パスプレーは省略します)。ランプレーは攻撃開始直後に、クォーターバックが走ってくる味方にすれ違いざまにパスを出し、そのボール保持者は相手を交わしながらできるだけ相手陣地の深いところまで、すなわちヤードを稼ごうとします。

今回予想するのは、このボール保持者が稼いだヤードが可能性のあるヤードそれぞれ以下である確率です。

例)3ヤード以下である確率:0.3、 4ヤード以下である確率:0.35、5ヤード以下である確率:0.38 .......

取り組み

以下では自分の取り組みを説明していきます。始めたのは、締め切りの約1ヶ月前からです。

コンペ概要理解とEDAなど

アメリカンフットボールの理解
アメフトのルールを知らなかったため、ここから始めました。サイトや動画を参考に進めました。

予測するものの理解
ランプレー時にオフェンスが得たヤードに関するもので、それぞれのヤード以下である確率を求めなければならないということをなんとか理解しました。ここからは、アメフトの動画はランプレーに絞って見ていました。

与えられたデータの内容
プレーごとのデータでした。まずそのプレーの情報で、日付と時刻、スタジアムの状態、天気と風速など。また、プレーに出場している22人それぞれの情報で、名前、身長体重、出身大学、ポジション、位置情報、進行方向や速度と加速度、背番号などが与えられていました。

モデル

多層ニューラルネットワーク(以下DNN)を使いました。今まではLGBMを使ってきたため、DNNを本格的に使うのは初めてでした。このカーネルと同じものです。

特徴量エンジニアリング

ベースのモデルができてからは、データ分析→そこから得られたアイデアを元に特徴量作る→スコア上がるかどうか?→データ分析 といったように仮説と検証の繰り返しでした。うまくいった特徴量を具体的に書いていきます。

攻撃チーム、守備チーム、ボール保持者(Rusher)、守備チームの前線選手などのそれぞれの戦績をランク付け
やはりアメフトにも強いチーム、弱いチームが存在し、同様にボール保持者の能力にも差があります。これを単純にターゲットエンコーディングしても良かったのですが、それは避けました。他の競技にも言えることですが、チームも選手も年によってかなり調子が上下します。そのままターゲットエンコーディングすると与えられたデータに過学習してしまうと思い、5つにランク分けし、エンコーディングしました。これは、リーダーボードのPublicからPrivateで、順位が約70位上がった要因にもなっていると思います。

ボロノイ図の面積を用いる
ボロノイ図というのは、平面上に配置された点に大して、その平面内の点を、どの点に最も近いかによって分割してできる図のことで、今回のコンペではこの記事でPythonで実装してくれています。僕はここから着想を得て、ボロノイ図によって分割された部分の面積を特徴量として加えてみることにしました。面積が無限大となってしまうのを防ぐため、うまくミラーリングを使う必要があるのですが、実装力不足のため数日を費やすこととなりました。しかし、この面積を標準化して特徴量として加えると期待以上にスコアがよくなったので達成感も十分にありました。ここで出した面積を元に、ある特定のポジションの選手の面積を利用するなど、さらに試行錯誤をしました。

選手同士の距離感
これは多くの方がされていると思います。ボール保持者と相手ディフェンスとの距離感を計算し、その平均や最小値、最大値などを利用しました。

上手くいかなかったこと

CNNを用いる
上記のことはコンペ終了1週間前には出来ており、銅メダル圏内にも入っていました。しかし、さらに順位をあげたいと思い、残り1週間は新しいことにチャレンジしました。そもそも僕が上記で作った特徴量は、主に選手の戦績と位置情報に関したものです。その位置情報を最もシンプルに用いることができるのはCNNではないか?と考えました。
つまり、選手の戦績やプレー時の状況、スタジアムなどプレー情報はシンプルなDNNにいれ、選手の位置情報と進行方向のベクトル、速度、加速度などはCNNに入れ、それをくっつけてしまい、最終的な出力を得ようというものです。題の通り、この試みは失敗しました。lossが全く下がらず、それまでのモデルより悪いスコアとなってしまいました。DNNの使用経験が少ないことによる安直な考えが原因ではないかと考えています。しかし、このコンペで1位であったチームはCNNを用いていたため、アイデア自体は悪くなかったのでは?とも思います。

数秒後の選手の位置を利用する
選手の進行方向のベクトル、速度、加速度が与えられているため、未来の選手の位置が求められると思い1秒後と0.5秒後の選手の位置を求め、それを用いて特徴量を作ったのですが、精度の向上には繋がりませんでした。他の参加者にはこの特徴量が効いたとコンペ後におしゃっていた方もいたので不思議です。

上位陣の解法

1st place solution
このチームは2位に大差をつけて1位となったのですが、とてもシンプルな解法で驚きました。選手の位置情報と速度、加速度をディフェンスとボール保持者、オフェンスとボール保持者、ディフェンスとオフェンスなどに分けた上で特徴量とし、モデルとしてCNNを使っていました。また、有用なCVを見つけたようで、CVのスコアをよくすることに注力することが出来たようです。

2nd place solution
Transformerという、主に自然言語処理で使われる手法があるのですがこの方はそれを使っています。上位の方の多くはこの手法を使っているようなので、僕もこの手法を理解したいと思います。

4th place solution
上記のTransformerは、Attentionという仕組みを用いているのですが、このチームはこのAttentionをDNNと組み合わせているようです。

ちなみにAttentionについてはこちらで解説しています。

まとめ

今回のコンペでは、データ分析→生まれたアイデアを元に特徴量作成→精度をあげる、という基本的な流れはうまくいきました。しかし、データ分析によって生まれたアイデアをモデルに反映させることはできず、それが上位陣との差であると感じました。もちろん、自力でメダル圏内に入れるようになったのは大きな成長であると思いますし、この経験と学びを生かして次回は銀メダルを狙いたいと思います。

その他Kaggle関連の記事

地震コンペをやってみた

インタビュー|Kaggle Expertまでの道のり

Adversarial Validationとは

Attentionモデルの解説

アクセルユニバース株式会社(以下当社)では、人が対応している業務を画像認識、音声認識、文字認識等を活用して効率化する機械学習ソリューション開発をおこなっています。


インターン生は業務の一環としてKaggleに取り組んでおり、先日のASHRAE - Great Energy Predictor IIIにて銅メダルを獲得しました。


メダルを獲得した田村くんのコメントです。

今回は、他の方が提出したもののブレンド(混ぜる)の仕方を工夫しました。
まずはなるべく違う解法を混ぜる対象として選定しました。その後は、混ぜ方が良い悪いの指標も評価できたので良かったです。

先日のアメフトのコンペ(NFL Big Data Bowl)も同様のことが言えますが、暫定順位(public leaderboard)を上げることだけを考えていると、private leaderboardの順位が下がる可能性が大きいので次のコンペでは十分に気をつけたいです。


その他当社インターンでは技術ブログを作成しています。

▼Kaggle

▼論文解説

▼新技術の実装


その他、随時紹介していくので是非ご覧ください!


Twitter・Facebookで定期的に情報発信しています!

業種別 機械学習導入・検討状況

2018年にIBMがおこなった調査によると、企業の82%はAIの導入を検討しており、金融サービス業界では既に16%の企業がAI システムを運用または最適化し、製造業がそれを追いかけるように導入・検討が進んでいます。

例えば、シーメンス、ジェネラルエレクトリック(GE)、ボッシュ、マイクロソフトなどの業界大手企業は、既に製造業のあらゆる部分を後押しするための機械学習アプローチによるAIの製造に多額の投資をおこなっているようです。

また、Google Trendsでも現在までの検索数の増加から、世の中の関心の高まりが伺えます。

スクリーンショット 2020-01-20 11.55.34.png

本記事では、製造業でのさらなるAI・機械学習活用のために3つの活用例をご紹介します。


製造業での機械学習活用例

メンテナンス時期予知

機器を使った製造行程がある場合、機器のメンテナンスが必須になりコストがかかることは避けられません。 また、製造行程において、想定外のダウンタイムは世界中の工場で起こっており、その約42%が機器の故障によるものだそうです。

そのため、メンテナンス時期の予測にAIを活用することが注目されています。 測定できる機器の状態データをAI・機械学習を使って、機器の状態を予測、推定します。メンテナンスが必要となるまでの機器の寿命が大幅に長くなります。 担当者は、機器があとどれくらいで交換/修理が必要になるか事前に知ることができ、またそのための対策を前もってとることが可能になります。


不良品検知

製造過程で発生する不良品はごく少数の割合でしか発生しませんが、不良品チェックは省くことの出来ない工程です。

そこで、人が目で確認している不良品のチェックを段階的にシステムがおこない、不良品可能性のあるものだけを人がチェックをするように役割分担をすることで、人の業務負担を軽減することが出来ます。

良品・不良品の画像等のデータを学習させ、不良品可能性の高いものにアラートを出します。不良品と断定するのではなく、あくまでも可能性とすることで、不良品の見逃しを防ぎます。


需要予測による市場適応

今後の需要を知ることで経営者はもちろん、現場担当者も適切に準備をすることで過不足なく対応することが出来ます。機会損失や過剰に在庫を抱えることを避けられます。

何をいつどのくらい受注したかの受注情報とその要因になるデータを学習させることで、未来の需要(受注)を予測します。

スクリーンショット 2020-01-20 13.16.20.png


今まで人がおこなってきた業務をシステムが代替することでこのようなメリットがあります。

AI・機械学習活用のメリット

  • 需要への調整
  • 運用コスト削減
  • 生産性向上
  • ダウンタイム削減
  • 商品力/競争力強化



AI・機械学習の浸透

今後も業種を問わずAIの活用は進み、とりわけ製造業での活用は急速に進んでいくと予想できます。


2019年12月に株式会社アイ・ティ・アールが以下のように調査報告しています。

2018年度のAI主要6市場の売上金額は199億5,000万円、前年度比53.5%増と大幅な伸びとなり、今後も継続的な伸びが見込まれることから、CAGR(2018~2023年度)は26.5%、2023年度には640億円に達すると予測している。 また、AI主要6市場の中で最も高い伸びを示したのが画像認識市場である。画像認識は工場などで行っている製品の外観検査や作業員の安全管理業務で導入が進んできたが、現在、道路や橋などの社会インフラ、各種建造物の保全業務での利用も急速に進んでいる。また、顔認証や車両の自動運転など、活用シーンの多様化により、今後も継続的な導入拡大が見込まれます。

上記報告から、AIはその技術進歩と相まって、私達の生活に浸透し始めていることがわかります。


当社も機械学習を活用したソリューションをご提案しています。
例えば、動画を用いた物体検出や、電力需要の予測が一例です。このような技術を用いて、お客様それぞれの課題解決へ取り組んでいます。

  • 自社にあるデータを活用したい
  • 自社に親しい業種の活用例を知りたい
  • AI・機械学習を活用したいが、方法に困っている
  • 機械学習ではなにが出来るのか興味がある


上記のようなご相談は画面右上の[お問い合わせ]までご相談ください。


当社、アクセルユニバースのご紹介

私達はビジョンに『社会生活を豊かにさせるサービスを提供する。』ことを掲げ、このビジョンを通して世界を笑顔にしようと機械学習・深層学習を提案しています。

  • ミッション(存在意義)
    私達は、情報通信技術を使って万物(全ての社会、生物)の暮らしをよりよくすることに貢献し、 それを加速させることを使命とします。

  • ビジョン(目標とする姿)
    社会生活を豊かにさせるサービスを提供する。

  • バリュー(行動規範)

    1. 変化を求め、変化を好み、変化する
    2. 自分の高みを目指してどんどん挑戦する
    3. お客様と一蓮托生でプロジェクトを進める



acceluniverse


Twitter・Facebookで定期的に情報発信しています!

はじめに

多くの機械学習モデルにおいて注意することの一つとして過学習(overfitting)があります。過学習は学習データに適合しすぎて未知のデータに適合できずに、汎化性能が低下してしまう現象のことを指します。DNNを例に取ると、モデルサイズを大きくしたり、エポック(epoch)及びイテレーション(iteration)を大きくしすぎるとモデルが過学習しすぎてテストエラー(汎化誤差)が大きくなってしまいます。ですが最近になって、一定以上を超えて上記のパラメータを大きくしていくとテストエラーが減少する"Double Descent"という現象が報告されているようです。今回はこの現象が起きている要因を解析している論文"Deep Double Descent: Where Bigger Models and More Data Hurt"の要約をしていこうと思います。

"Double Descent"とは

[The Elements of Statistical Learning]
この文献で述べられているように、従来ではモデルの複雑度(complexity)がある閾値を超えるとテストエラーが大きくなり続けるということが言われていました。一方で、ここ最近では100万を超えるパラメータを持つ巨大なモデルを構築する、学習回数を増やす、データを増やすことでテストエラーが改善していくという論文がここ5年の間に次々と報告されてきています。以下の図のように一度降下して再度降下していく現象を"Double Descent"と名付けられています。

スクリーンショット 2020-01-15 17.34.36.png

このグラフの特性は2つの領域に大別できます。上記で述べたテストエラーが悪くなり続けるという話は" Classical regime"のことを示しており、複雑度(モデルの構造や学習量)を一定以上に大きくすると再度降下していく"Modern regime"がその後に続いています。例えばシンプルな構造のニューラルネットワークと複雑なニューラルネットワークがあったとします。前者については従来から言われているように"under-fitting"と"over-fitting"からなるU字型の特性が観測できますが、後者は複雑にしていくとある閾値(図でいうinterpolation threshhold)で再度降下していくという具合です。
さて"Double Descent"についてはなんとなくわかりましたが、どのような要因によってこのような特性となるのでしょうか。次に論文の主軸であるEMCという指標について述べていきます。

EMCについて

EMCとは"トレーニングエラーがほぼ0になるときのサンプルの最大値"で定義されています。もちろんですがtraining errorが0になる時点というのは使用するモデルや学習方法や量、問題によって異なってきます。筆者はこのEMCという指標でDouble Descentを説明できるという仮設を立てています。
上記の文を式にすると以下のようになります。
スクリーンショット 2020-01-15 18.44.49.pngただし、
S:入力データ
D:データの分布
T:学習手順
n:サンプル数
ε:トレーニングエラー


上記の定義式を元に以下の図のように3つの領域に分けられます。

criteria.png

1. Uner-parameterized regime

EMCが大幅にnより小さいとき、複雑度が増加すると同時にテストエラーは減少する(EMC<n)

2. Critically parameterized regime

EMCがnにほぼ等しいとき、複雑度が増加すると同時にテストエラーは減少する若しくは増加する(EMC>n)

3. Over-parameterized regime

EMCが大幅にnより大きいとき、複雑度が増加すると同時にテストエラーは減少する(EMC≒n)

まだ分かりづらいと思うので補足します。横軸をsample数としてCritically parameterized regimeの部分に注目したグラフが以下のようになっています。
スクリーンショット 2020-01-16 14.14.48.png
定義通り捉えるとトレーニングエラーεが0付近の中でもサンプル数が最大となるのはおよそ1000となっているのでEMCは1000となります。この場合ではテストエラーのグラフのinterpolation threshholdはこの値付近に存在するということになります。もちろんこのグラフ特性は入力データSと分布D、学習手順T(これはモデルサイズは最適化アルゴリズムを含む)によって変化します。が、それぞれのパターン毎において求められるEMCの値付近にこのinterpolation threshholdが「経験則的に」存在している、つまりEMCとinterpolation threshholdは何かしらの相関が存在しているため、その延長線上に有るDouble DescentはEMCによって説明出来るという仮説が本論文の趣旨です。

 あくまでも仮説なので、EMC=nとなる付近でinterpolation threshholdが存在するということを以下の理論解析で説明しています。また、εの値は経験則的に決められており(ε= 0.1)、原則が存在するわけではないようです。図から分かるようにCritically parameterized regimeでは過学習のような振る舞いをしているため、汎化性能が劣化している領域です。そのため、予めこの領域を把握していれば汎化性能の劣化を防ぐことが出来るということですね。ということで以降はEMCに相関のあるモデルサイズ、学習量等を評価軸としてDouble Descentの振る舞いを見ていきます。

その前に

理論解析で採用されているLabel Noiseについて説明します。これは教師データの正解ラベルをpの割合で誤った正解ラベルに置き換えることでデータ分布を強制的に変えている雑音のことを指します。(以下イメージ図)Label Noiseを付加することでモデルが誤って学習をすすめるため、過学習のような特性になることが予想できます。また、εが非常に小さくなるまで学習をすすめることで テストエラーの理論限界はpになることも予想できます。
図1.png

それでは各種評価について見ていきます。今回評価軸は3つに大別できます。

・Model-wise Double Descentーモデル構造(モデルサイズ、最適化アルゴリズム)の変更やデータの水増しによるDouble Descentの特性(エポック固定)
・Epoch-wise Double Descentーいわゆる学習曲線(モデル構造固定)
・Sample-wise Non monotonicityーサンプル数変化によるDouble Descentの振る舞い及びCritically parameterized regime付近での特性

それぞれ多角的に評価しており、その一部を記載していきます。

1.Model-wise Double Descent

スクリーンショット 2020-01-16 11.09.06.png○諸元
モデル:ResNet18
最適化アルゴリズム:Adam(learning rate:0.0001)
エポック数:4000
その他:データ水増し
データセット:左 CIFAR-100、右 CIFAR-10
上記はモデルサイズ毎のテストエラー、トレーニングエラーの特性を示しています。両者グラフの違いとして左の結果はLabel Noiseを付加していない場合でも"Double Descent"のような振る舞いをしていることがわかります。また、Label Noiseが大きくなるにつれてinterpolation threshholdにおけるピーク値が大きくなり、左にシフトしていっていることも読み取れます。

2.Epoch-wise Double Descent

図2.png

○諸元
モデル:ResNet18
最適化アルゴリズム:Adam(learning rate:0.0001)
Label Noise:20%
その他:データ水増し
データセット:CIFAR-10
次に学習量に応じたテストエラーを見ていきます。左のグラフが馴染みのある学習曲線、右はテストエラーを深さとしたデプスマッピングです。学習量が多くなるにつれてEMCが大きくなることから、モデルサイズが大きくなるにつれてDouble Descentのような振る舞いが顕著に現れていることがわかります。また他のサイズでは範囲内の学習量ではUner-parameterized regimeの領域に属していることからモデルが小さい場合は引き続き学習を続け、その間のサイズであれば早期終了するなどして学習を止めたほうが良い事が読み取れます。

3.Sample-wise Non monotonicity

スクリーンショット 2020-01-16 12.11.32.png
○諸元
モデル:5-layers CNN
最適化アルゴリズム:SGD(learning rate:0.0001)
データセット:CIFAR-10
最後にサンプル数変化によるDouble Descentの振る舞いを見ていきます。サンプル数を増やすことでEMCが増加するため、interpolation threshholdが右にシフトします。そのため、モデル固定の場合にCritically parameterized regimeをサンプル数によって調整出来るため、汎化性能が劣化することを予め回避することができます。(例えばoverfitting に位置するモデルのサンプル数を増やすことでunderfittingの位置にシフト出来る)個人的に気になったのですが、Label Noiseが小さい上のグラフのほうがテストエラーが大きくなっているのが疑問に思いました。

結果まとめ

スクリーンショット 2020-01-16 12.32.19.png

終わりに

Fully understanding the mechanisms behind model-wise double descent in deep neu- ral networks remains an important open question. However, an analog of model-wise double descent occurs even for linear models. A recent stream of theoretical works analyzes this setting (Bartlett et al. (2019); Muthukumar et al. (2019); Belkin et al. (2019); Mei & Montanari (2019); Hastie et al. (2019)). We believe similar mechanisms may be at work in deep neural networks.

今回、"Double Descent"をEMCという指標で説明出来るという仮説を立てた事、またその根拠を理論解析で提示した論文の紹介をしました。上記の引用からも論理的な証明はまだできておらず発展途上ということだそうです。この"Double Descent"を解明することで、どれくらいの学習をさせるべきなのか事前に把握することができると同時に、モデルチューニングの最適化などにも貢献する重要なテーマであると思いました。

参考文献
・Trevor Hastie, Robert Tibshirani, Jerome Friedman"The Elements of Statistical Learning Data Mining, Inference, and Prediction,"Available:https://openreview.net/forum?id=B1g5sA4twr
・Preetum Nakkiran, Gal Kaplun, Yamini Bansal, Tristan Yang, Boaz Barak, Ilya Sutskever "DEEP DOUBLE DESCENT: WHERE BIGGER MODELS AND MORE DATA HURT," ICLR 2020 Conference Blind Submission, Available:https://openreview.net/attachment?id=B1g5sA4twr&name=original_pdf


Twitter・Facebookで定期的に情報発信しています!

リモートワーク・業務効率化を阻む紙

このようなことはありませんか?

  • お客様アンケートを手集計している。
  • 見積作成のために出社しないといけない。
  • 紙の伝票処理に時間がかかっている。


コロナウイルスの影響もあり、リモートワーク化が進む中、上司のハンコを貰うのでリモートワークできない。という声も少なからずあるようです。紙書類の作業のために出社をしなけばいけない...。リモートワークに限らず、営業が業務日報や見積り作成で会社に戻ることは業務効率を大きく下げる要因です。
2019年4月1日に改正された労働基準法では残業時間の上限が定められ、中小企業も2020年4月1日から規制の対象となりました。働き方関連法では有給休暇取得の義務化がはじまっており、少ない時間で現在の業務を遂行することの重要度がますます高まっています。


書類の電子化で期待できる効果

  • いつでも欲しい情報が引き出せ、編集できるのでリモートワークが促進する
  • 移動時間削減で業務時間が短縮
  • 現行の書類保管場所の省スペース化
  • 書類の内容をデータ化することで分析可能になり、二次活用できる
  • スムーズな情報の検索、共有で業務が効率化


書類データ化ソリューションの背景

MM総研が2019年7月30日に『AIを活用した手書き文字認識のAI-OCR(光学文字認識)サービスの利用実態』を調査しました。抽出した国内企業1000社のうち、9.6%の企業がAI-OCRを導入済みという結果が出ました。また、企業規模が大きいほど導入率が高く、1000人以上の大企業だけでみると13.2%が導入済みという結果です。
※AI OCRとは、手書きの書類や帳票を読み取りデータ化するOCRへ、AI技術を活用する新たなOCR処理をいいます。

スクリーンショット 2020-01-16 11.27.03.png
AI-OCRサービスの導入していない企業も、サービス利用への関心は高く、51.9%が「利用に関心がある」と回答しました。こちらも大企業を中心に関心が高く、1000人以上の大企業では導入済みを含めると72.7%がAI-OCRを利用することに関心があります。

業種別で見ると、卸売業・小売業や製造業、官公庁など、大量の手書き帳票が発生する業種でより強い導入意向がみられています。
また、導入企業のうち85.7%が「データ作成に要する時間を削減できた」と回答し、82.1%は「ミスの発生率」を、78.6%は「当該業務に必要な人員数」を改善できたと回答しています。


一方、AIを使わない既存技術のOCRは、全体の85.8%が「活用できていない」と回答しています。手書き文字やフォントの文字認識能力の低さが理由としてあげられており、調査では「手書き文字の識字率が低い」という回答が全体の41.6%、「フォントの識字率が低い」が31.8%という結果でした。
精度が求められる「文字の読み取り」にはAIは欠かせない存在となり始めています。

AIを活用した書類データ化の仕組み


スクリーンショット 2020-01-16 10.43.11.png
【文字認識】では文字の特徴を理解し、何の文字かAIが判定します。

文字の特徴を理解させるために、多くの画像をAIに学習させます。
「あ」であれば「中央に十字線がある」、「下に楕円がある」、「楕円は右で切れていて払いがある」のような特徴があり、新しく読み込んだ文字が「その特徴にどれだけ当てはまるか」でどの文字であるかを判定します。

文字ごとに判定していくとどうしても似た文字を誤判定してしまいます。
また書き癖の強い文字やつなげ字の判定は難しいとされています。


スクリーンショット 2020-01-16 10.43.51.png
そのため、【修正】では文字として判定した後に文章としても適切かチェックし、修正します。
そうすることでより高い精度で書類を認識することが可能です。


書類データ化活用シーン

大量の紙書類の存在はバックオフィス業務の生産性向上を妨げます。
帳票を種類毎に仕分け、記載内容の入力漏れや誤字脱字を確認し、あとは間違いに気をつけながらPCにデータを入力していく...。このような作業をシステムが代替する例を紹介します。


アンケートの集計

セミナー後や購入後にお客様にアンケートをとりますよね。
その場で回収することもあれば、後日郵送してもらうこと、様々ですが、お客様の声を反映させるためにスピード感が大切です。
また、見込みのお客様の場合はよりスピード感のある対応が必要となるので、手書きのアンケートでも即座にデータ化出来ることは初期対応を早めるために効果的です。


過去書類のデータ化

書類を探したいのに探せない...。重要な書類も倉庫の中やキャビネットに眠り、『書類探し』が業務になっていませんか?
過去書類をデータ化することで、検索性の向上による業務時間の短縮はもちろん、今までの保管場所をなくすこともできます。


営業メモの共有

敏腕営業マンが客先でどんな会話をし、売上を上げているか...。は永遠のテーマです。
そのノウハウを共有したいが、商談メモや勉強ノートを共有するのは難しく、経験と勘だよりの営業活動となるケースが多くあります。
メモやノートをデータ化することでノウハウの共有だけでなく、受注までのシナリオや商談の傾向を分析することで「勝ちパターン」を確立することができます。


テスト答案の読み取り

テスト答案を読み取り分析することで、問題に対する正解不正解以上に「どの問題はどう間違えるのか」を分析できます。
誤答率の高い問題がどのように間違えられたのかを知ることで「なぜ間違えたのか」を分析し、より効果的な教育をおこなうことができます。


申込書のデータ化

お客様からの申込書、事務所で転記していませんか?
転記作業の手間や誤入力も削減することが出来ます。大切なお客様データだからこそ、早く正確にデータ化をする管理をおすすめします。


まとめ

手書き書類をデータ化することで業務効率化を進めることはもちろん、たまったノウハウを共有したり、分析したり、有効活用できます。
ノウハウを共有することで新人の教育コストを削減するだけではありません。データを参照する仕組みを作れば「質問しにくさ」も解消でき、副次効果としてストレスやミスの軽減も見込めるでしょう。


当社ではみなさまの課題やお困り事を一緒に解決していきます。
問い合わせ口からご連絡ください。

  • 書類のデータ化が自社でも活用できるか知りたい
  • その他活用例を知りたい
  • 困っていることを相談したい
  • 機械学習・深層学習は他になにが出来るのか興味ある


アクセルユニバースのご紹介

私達はビジョンに『社会生活を豊かにさせるサービスを提供する。』ことを掲げ、このビジョンを通して世界を笑顔にしようと機械学習・深層学習を提案しています。
例えば、現在人がおこなっている作業をシステムが代わることで、人はより生産性の高い業務に携わることができます。


acceluniverse


Twitter・Facebookで定期的に情報発信しています!

概要

AI技術の発展が進み、今や私たちの身の回りでも当たり前のようにAIが生活をより便利にしてくれています。この夢のような技術を支えているのは研究者の方たちによる地道な努力です。では、最近はどのような研究が行われているのでしょうか?

研究の成果は論文という形で公開されますが、世界中で活発に研究されているAI関連の論文は1日に数十~百本もの論文が出ています。そのためこれらの論文を読んで最新の研究動向をつかむことは難しいでしょう。

そこで今回はテキストマイニングと呼ばれる技術を用いて20年前から現在までに出版された大量の論文を自動で分析し、大まかでよいので、今流行っている研究や過去のトレンドを調べてみたいと思います。

目次

テキストマイニング

テキストマイニングって?

インターネットやSNSが発達し、個人が自分の考えを自由に発信できる今、膨大な量の文章データがネット上に集積していきます。こういった「生の」情報を集めることは簡単ですが、この中から本当に意味のある情報を引き出すことは容易ではありません。例えば数値データであるならば、平均値を求めたりすることで、大体の状況を把握することができますが、文章の場合にはこういった処理ができないからです。

テキスト(文章)マイニング(採掘)は、こういった問題に対処する一つの方法で、「膨大な文章の中から自分にとって価値のある情報を抽出する技術」のことです。最近よく見かける、ワードクラウド(下の図)もテキストマイニングを用いたものです。

wordcloud.png

一体どのような方法で文章から情報を抽出するのでしょうか?

それを見る前に、テキストマイニングの便利さを実感するために1つ例を考えてみます。
仮に洋服屋に勤務しているとして、売り上げがなかなか伸びなかったとします。あなたはその原因を探るべく、お客様アンケートを行いました。
従来の方法では

Q、品ぞろえに満足していますか?

  • 満足
  • 普通
  • 不満

のように選択式でないと定量的に扱うことができず、さらにセーターの品ぞろえが悪いのか、パーカーの品ぞろえが悪いのか、あるいはそれ以外なのか、区別がつきません。
これでは質問を作るのは手間だし、的確な情報も得ることは難しいです。

テキストマイニングを使えば、

Q、品ぞろえに関して不満な点はありますか?

のような自由記述で回答してもらい、これを分析にかけることで、「パーカー」「品ぞろえ」「悪い」といった大まかな回答の傾向をつかむことができ、適切な対処をとることができるでしょう。

このような利点からテキストマイニングは、SNSを対象にした商品のレビュー調査、新聞記事を対象にした社会学、対話型AI等、様々な用途に利用されいます。膨大なデータから何か新しい情報を抽出したい際にきっと強力な道具となるはずです。

分析方法

ここではテキストマイニングの流れについて説明したいと思います。あくまでテキストマイニングを利用した分析を述べることが主眼なので統計学的な詳細については省略します。
例として、2019年9月に環境活動家のグレタ・トゥンベリさんが国連で行ったスピーチの一部を見てみましょう。

This is all wrong. I shouldn't be up here. I should be back in school on the other side of the ocean. Yet you all come to us, young people, for hope? How dare you! You have stolen my dreams and my childhood with your empty words. And yet I'm one of the lucky ones. People are suffering. People are dying. Entire ecosystems are collapsing. We are in the beginning of a mass extinction. And all you can talk about is money and fairytales of eternal economic growth. How dare you!

このスピーチは環境問題に真剣に取り組まない各国の首脳らに向けた怒りのメッセージで、" How dare you! "「よくもそんなことができるものだ!」というフレーズが特徴的で話題を集めました。実際このフレーズは全スピーチ中で4回繰り返されています。

このスピーチ全文を分析にかけた場合には、ネガポジ分析(テキストマイニングを利用した分析の一つで、その文章全体がネガティブな内容なのか、ポジティブな内容なのかを判断する)では「ネガティブ」と判断され、よく出てくる単語として dareや, air (大気), fail (失敗する), solution (解決策), emission (排出)のような環境問題系の言葉が現れるはずです。また、語同士のつながりは、How, dare, you の3語のつながりが明確に出るはずです。

それでは分析の流れを順を追って説明していきます。(実際にはソフトの「実行」ボタン一つで完了します)

1、まず、文章を一文ごとに区切ります。英語の場合はピリオド(.)で区切ればよいのですが、 U.S.AMr. Tanaka のような例外もあるので、こういった例外を集めた一種の「辞書」が必要です。ソフトはこの「辞書」を参照しつつ全文を区切っていきます。今回用いるソフトウェアKH Coderではこの作業をPearlのモジュールを使って行っているようです。
例えば上のスピーチの一文

I shouldn't be up here.  私は今ここにいるべきじゃない 。

をとってきたとしましょう。

2、区切った一文を今度は単語ごとに区切ります。英語の場合スペースで区切ればよいです。ただし shouldn't = should not のような例外もあるので、これも「辞書」を参照しつつ行います。
上の例では

I, should, not, be, up, here

となります。

3,取り出した単語一つ一つについて、基本形に直します。過去形を現在形に直したり、複数形を単数形にしたりするということです。そうすることで carscar 等の二種類の単語を一つにまとめて扱うことができ、分析が楽になるからです。この作業をステミング(stemming)と呼びます。これにも「辞書」が必要です。英語の場合には "Stanford POS Tagger"、 "FreeLing"、 "SnowBall" といった辞書が公開されています。今回は2、および3の作業には "Standard POS Tagger"を用います。
この作業を行うと上の例では

I, shell, not, be, up, here

となります。

4,次に stop word を削除します。これは英語の場合 be動詞や前置詞など、どんな文章にも頻繁に現れる、重要ではない語のことです。何をstop word とするかは分析者が自分で定義します。
上の例では

not, here

のようになるかもしれませんし、何も残らないかもしれません。

5,ここまでの作業はどのテキストマイニングのソフトにも共通の前処理でした。ここからどのように分析を行っていくのかがそのソフトの特徴となります。分析の方向性には以下のように大きく二つあります。

  • 分析者があらかじめ指定した単語を中心にコンピュータが分析する手法
    • 例えば地球温暖化についての新聞記事を対象としている際に、分析者が「火力発電」という切り口で分析を進めたい場合、コンピューターは指定された「火力発電」を含む文章を集め、多変量解析の手法で分析します。(単語の出現回数を数えたり、一緒に現れやすい単語の組を探したりします)
    • 分析者の問題意識が反映されやすい一方で、客観性に問題があるかもしれません。

  • 分析者が何の条件も指定せず、バイアスなしでコンピュータが分析する手法
    • 初めから全データをコンピュータが多変量解析の手法で分析し、得られた結果から何が言えるのかを考えます。
    • 上の例だと、地球温暖化に関する記事を全て分析にかけ、その中で「火力発電」がどのくらいのウエイトを占めているのかなどを調べます。
    • 結果があいまいになる(ほかのデータの中に埋もれやすい)恐れがある一方で客観性は保証されます。

今回用いるKH Coderはどちらのアプローチでも分析できるのが特徴です。

実際に後者の方法で上のスピーチ全文についての分析を行い、「共起ネットワーク」(語の出現回数を丸の大きさで表し、語同士のつながりを線の太さで表した図)を描いたものが次の図です。

example.png

中心付近で、 How, dare, youの3語が強く結びついているのが分かります。ただ、頻出の単語は come, people, say 等、環境問題特有のものではなく、一般的に多くの文章でよく使う単語が目立ちます。このスピーチは短いのでまだマシですが、大量の文章を分析するとこの傾向がさらに強まると考えられます。そのため、こういった単語はstop wordにしてしまうか、あるいは表示する単語の出現回数に上限を設けるなどの対策が必要です。


データの収集

arXiv

論文の収集には、物理、数学、情報科学といった分野の論文が保存・公開されている、arXivというサイトを使います。arXivは時間のかかる査読(提出した論文を他の専門家がチェックする過程)を経ずに論文を無料で投稿できるため、多くの論文が集積しています。今回は分野を機械学習分野に絞り、論文の最初に書かれている、Summary(要約)を集めて分析したいと思います。Summaryは短いので大量の論文から集めても計算時間がそれほど長くはならず、また論文全体の内容が凝縮されているので、機械学習に関係のない単語の割合が少なく、分析しやすいと考えたからです。

スクレイピング

大量の論文を集めるにはスクレイピングという手法を用います。いちいち自分で該当するwebサイトにアクセスせずに、自動でダウンロードしてくれる便利な方法です。arXivはスクレイピング用のAPIを用意してくれているのでこれを利用します。今回は2019年、2018年、2017年、2016年、~2009年、~1999年に出版された論文を集めます。

※以下のコードは Google Colaboratory で動作確認済みです。

まずは必要なライブラリをインポートします。

import arxiv
import pandas as pd

※ arxivが入っていない場合は、次のように打ってインストールしてください。

! pip install arxiv


このarxivというAPIを使えば、検索条件を指定するだけで自動で論文名、著者、日付、要約などをダウンロードできます。
今回は、「機械学習分野(LG)で2019年に出版されたもののうち、最大10,000件を提出日の新しい順に」取得します。それが以下のコードです。

latestQuery = arxiv.query(query='cs.LG AND submittedDate:[20190101 TO 20191231]', max_results=10000, sort_by='submittedDate', sort_order='descending')

得られるデータは辞書形式で見にくいのでデータフレーム形式(エクセルのような表形式)に直します。

df_latest = pd.io.json.json_normalize(latestQuery)
print(df_latest)

以下のような表が得られます。

スクリーンショット 2019-12-27 17.49.22.png

ここから Summary(要約)だけ取り出します。

df_latest_s = df_latest[['summary']]
df_latest_s.index.name='index' #後でつかうソフトに合わせるためのもので特に意味はありません。 

最後に、得られたデータを同じディレクトリにcsvファイルとして保存します。

df_latest_s.to_csv('./latest_data.csv')

全く同様に、2018年、2017年...の論文を集めます。

# 検索条件を指定
oneoldQuery = arxiv.query(query='cs.LG AND submittedDate:[20180101 TO 20181231]', max_results=10000, sort_by='submittedDate', sort_order='descending')
twooldQuery = arxiv.query(query='cs.LG AND submittedDate:[20170101 TO 20171231]', max_results=10000, sort_by='submittedDate', sort_order='descending')
throldQuery = arxiv.query(query='cs.LG AND submittedDate:[20160101 TO 20161231]', max_results=10000, sort_by='submittedDate', sort_order='descending')
tenoldQuery = arxiv.query(query='cs.LG AND submittedDate:[20000101 TO 20091231]', max_results=10000, sort_by='submittedDate', sort_order='descending')
tweoldQuery = arxiv.query(query='cs.LG AND submittedDate:[19900101 TO 19991231]', max_results=10000, sort_by='submittedDate', sort_order='descending')

# データフレーム型に変換
df_oneold = pd.io.json.json_normalize(oneoldQuery)
df_twoold = pd.io.json.json_normalize(twooldQuery)
df_throld = pd.io.json.json_normalize(throldQuery)
df_tenold = pd.io.json.json_normalize(tenoldQuery)
df_tweold = pd.io.json.json_normalize(tweoldQuery)

# Summaryだけ抜き取る
df_oneold_s = df_oneold[['summary']]
df_oneold_s.index.name='index'
df_twoold_s = df_twoold[['summary']]
df_twoold_s.index.name='index'
df_throld_s = df_throld[['summary']]
df_throld_s.index.name='index'
df_tenold_s = df_tenold[['summary']]
df_tenold_s.index.name='index'
df_tweold_s = df_tweold[['summary']]
df_tweold_s.index.name='index'

# csvファイルに保存
df_oneold_s.to_csv('./oneold_data.csv')
df_twoold_s.to_csv('./twoold_data.csv')
df_throld_s.to_csv('./throld_data.csv')
df_tenold_s.to_csv('./tenold_data.csv')
df_tweold_s.to_csv('./tweold_data.csv')

これでデータの準備は整いました。なお2009年、1999年に出版された論文は少なすぎたので、前10年分をとりました。

分析

今回テキストマイニングに用いるソフトはKH Coderです。これは日本人の方が開発されたソフトで、英語だけでなく日本語や中国語にも対応しています。

KH Coderのインストール

ここからダウンロードできます。Windowsの場合はダウンロードしたファイルを実行するだけですが、MacやLinuxの場合、MySQLやPearl、Rの設定などを自分で行わなければいけないので環境構築が大変です(インストールを自動化してくれる有償サポートもあります)。基本的には このサイト に従えばよいですが、それでもエラーが頻発すると思います(私はいやというほどしました)。どうしても解決しない場合は、製作者の方が質問を受け付けてくださっているので ここで質問してみるのも手です。

私が詰まったエラーを二つ書いておきます。

・MySQLの「LOAD DATA LOCAL INFILE」コマンドでエラー

err2.png

↓エラーメッセージ

SQL Input:
LOAD DATA LOCAL INFILE '/Applications/khcoder-master/config/khc26/khc26_ch.txt' INTO TABLE rowdata CHARACTER SET utf8mb4
Error:
The used command is not allowed with this MySQL version
```

これはKH Coderの開発時からMySQLのバージョンが新しくなったことによる問題です。まずターミナルで

mysql -uroot

と打ってMySQLにログインします。その状態で次のようにコマンドを打てば解決するはずです。

SET PERSIST local_infile= 1;

・MySQLの「GROUP BY」でエラー

error1.png

↓エラーメッセージ

SQL Input:
INSERT INTO hgh2 (genkei, sum, h_id, h_name)
SELECT hgh.genkei, SUM(num), hinshi.id, hinshi.name
FROM hgh, hinshi
WHERE hgh.hinshi=hinshi.name
GROUP BY hgh.genkei, hgh.hinshi

Error:
Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'khc25.hinshi.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
```

これも 開発時からMySQLのバージョンが更新されたことによる問題です。MySQLにログインした状態で以下のコマンドを打てば解決します。

mysql> set global sql_mode=(selectreplace(@@sql_mode,'only_full_group_by',''));

KH Coderの設定

上述したように、文章から単語を取り出して基本形に直すには「辞書」が必要です。また、stop wordの削除を行うには、自分でstop wordを定義しなければいけません。

まず、今回使う辞書 "Standard POS Tagger" をダウンロードして適当な場所に保存しましょう。ここからダウンロードします。
KH Coder のメニューバーから、【プロジェクト】→【設定】→【語を抽出する方法】→【Standard POS Tagger】→【*. TAGGER file path】に先ほど保存した場所を指定します。また、同時に【Stop words】も定義します。KH Coderをダウンロードしたときに一緒にダウンロードされる、sample fileをそのままコピペすればよいでしょう。

また、【その他】の「前処理効率化のためにデータをRAMに読み出すを選択しておくと前処理が早くなるのでチェックしておくと良いです。

前処理の実行

設定が終われば、【プロジェクト】→【新規】から先ほどスクレイピングで集めたファイルを指定します。「分析対象とする列」にはindexではなく、 **summaryを指定** するようにしましょう。また「言語」は英語、Standard POS Tagger となっていることも確認しましょう。

次に前処理をします。メニューバーから【前処理】→【前処理の実行】を押し、現れるダイアログは「OK」を選択し、しばらく待ちます(私の場合1~10分ほどでした。)
初めのうちはここで山ほどエラーが出ると思いますが一つ一つつぶしていきましょう。

結果

結果の表示にはその分析法に応じて複数の描画の方法があります。「対応分析」と「共起ネットワーク」が視覚的にわかりやすいので今回はこれを使いました。他にも多くの方法があるので詳しくはKH Coderのマニュアルを参照しましょう。マニュアルは、メニューバーから【ヘルプ】→【マニュアル】で見ることができます。

まずは、古い順に共起ネットワークを描いていきます。共起ネットワークは、語の出現回数を丸の大きさで表し、語同士のつながりを線で表しています。また、語の色分けについては、「サブグラフ検出」と呼ばれる方法で比較的強くお互いに結びついている部分を自動で検出してグループ分けを行った結果です。ただし、マニュアルにも書かれている通り、

あくまで機械的な処理の結果であるから,色分けには必ず重要な意味があるはずだと考えて深読みをするのではなく,グラフを解釈する際の
補助として利用することが穏当であろう

とのことなので注意します。
語同士のつながりには実線と破線がありますが、同じサブグラフに属する語同士は実線、そうでなければ破線という意味です。

まずは一番古い1990 - 1999年まで(実際にあったのは1997/12 - 1999/12)に出た全論文33本について分析を行ったのが以下の図です。

twenty.png

algorithmという単語が最もよく出てきていることからもわかるように、この時期は基礎的な研究が主だったことがうかがえます。
reinforcement, agent, maxq, corpus, natural, language 等の単語から、強化学習や自然言語処理の研究がすでに始まっていたこともわかります。


続いて2000 - 2009年にかけて出版された全論文762本について分析したのが以下の図です。

ten.png

依然 algorithm が最頻出単語です。 vector - machine はいわゆる SVM(サポートベクターマシン)、 decision - tree は決定木、 classification = 分類、など今につながる具体的な手法が目につきます。 time - algorithm や、 model - learning のつながりが現れたことから、機械学習の原理の研究から、現実的な問題解決の方法論へと研究が移行していったのがこの時期だと考えられます。


続いて2016年に出版された全論文3568本について分析した結果が以下です。

throld_100-1500.png

上述のように機械学習に関係のない語をはじくために、出現回数が100回以上1500回以下の単語に絞って書いてあります。この対処法は感覚的なもので、これが最も適切な処理である根拠はありません。実際機械学習の中心的な単語であるはずの algorithm model が出てきていないのは出現回数が大きすぎたためです。これがテキスト分析の難しいところですが、これ以上ソフトで分析を進めるのは難しいので、あとは注意深く結果を見て、何かしらの傾向をつかめるように頑張ります。

左にある緑色の大きなグループは、 task を中心として image, classification, dataset, frameworkのような単語が並んでいることから、画像分類の内容であると推測できます。ディープラーニングによって画像分類の精度が飛躍的に高まり、話題を集めたのが2012年のことなので、これは比較的新しい話題で、研究のフロンティアだったのだと考えられます。
右の方には reinforcementを中心にした強化学習、下の方には wordを中心にした自然言語処理が20年前から依然としてあり、この二分野は長らく、よく研究されていることが言えます。
上の方には optimization(最適化), gradient(勾配)などのやや基礎的な研究内容があります。
また、教師なし学習の代表格 clusteringも目につきます。


続いて2017年に出版された52381本の論文について。

twoold_200-1000.png

出現回数が200回以上1000回以下の単語に絞った描画です。
この年に特徴的なのは、reinforcementを中心とする強化学習に関連する単語群の出現数がほかの分野に比べて相対的にずっと多くなったことです。前年のグラフと比べてみれば一目瞭然です。
この時期に強化学習関連で目立ったことがあったのかどうか調べてみると...ありました!
2016年3月に GoogleのAlphaGoが韓国のトップ棋士李世乭さんに5番勝負で4勝1敗にて勝利し、2017年5月には中国のトップ棋士柯潔さんにも3局全勝を上げていました。ニュースでも大々的に取り上げられましたね。

将棋やチェスなど数あるボードゲームの中でも、囲碁はそのありうる盤面の数が際立って大きいです。そのためコンピュータの得意とする全探索手法が使えないために、人間に勝利することは難しいと考えられていたために、AIに詳しい人ほど、この対局は衝撃的だったのでしょう。これを機に研究者たちの中でも強化学習の可能性に注目が集まり、よく研究されるようになったのだと推測されます。

左上の方には RNN, LSTM, GAN といったディープラーニングに関する話題が多く出てきています。以前にもあったけれども、ほかの語に埋もれていたのかもしれないので、この時期にはやったのかどうかは何とも言えません。

左の方には language, textなどの自然言語処理の話題があり、前年に比べ相対的に大きくなっています。また、 speechが新たに自然言語処理に加わっているのも面白いですね。


続いて2018年に出版されたもののうち5600本(「うち」と書いているのは、APIの仕様のせいか、全ての論文を集めることができなかったためです)。

oneold_200-1000.png

出現回数が200回以上1000回以下の単語に絞った描画です。
下の方にある optimization, gradientはアルゴリズムの研究のような基礎的な話題でしょう。
左の方にある青い大きなグループは layerがハブになっていて、また雑多な単語がつながっていることからディープニューラルネットワークを用いた応用的な話題かと思われます。
上の方にあるオレンジ色のグループは強化学習、右の方にある紫色のグループは自然言語処理の話題でしょう。

最後に2019年に出版されたもののうち3000本です。

latest_200-1000.png

出現回数が200回以上1000回以下の単語に絞った描画です。
アルゴリズム(赤)、強化学習(青)、自然言語処理(オレンジ)、画像認識(黄緑)など、今よく聞く話題がよく研究されていることがわかります。また、突出して出現頻度が多い語はなく、色分けされたグループもだいたい同じ規模です。これが出現回数の制限によるものかどうか調べるため、試しに2000回以下、及び制限なしの場合に同じ図を描いたのが次の図です。

latest_2000.png

latest_max.png

やはり同じ傾向が見られます。このことから、現在の研究は、アルゴリズム、強化学習、自然言語処理、画像認識がどれも活発に研究されていると言えるでしょう。


これまで出版年ごとに共起ネットワークを出してきました。各年ごとの特徴はよく分かるのですが、時間変化はわかりにくくなっています。
時間変化をメインに共起ネットワークを描くには、すべての論文データを出版年とSummaryだけ残して一つのCSVファイルに統合し、これを前処理します。そして共起ネットワークを描く際のオプションとして、「共起パターンの変化を探る(相関)」にチェックを入れます。こうすると、以下の図が得られます。

change_100_1000-5000.png

この図は、赤い線ほど、最近出版された論文に特徴的なつながり、青い線ほど古い論文に特徴的な論文に特徴的なつながりを表します。例えば、下の方にある rewardは古い論文では regretとよくつながっていましたが新しい論文では reinforcementとよくつながっているようです。これは強化学習における rewardに対する考え方が変化したことを表している可能性があります。
他にも、右の方にある languageは、よく共起する単語が wordから textへと変化していることもわかります。これは自然言語処理の発展により、研究対象が wordから textへと移り変わったことを示していると推測することもできます。

共起ネットワーク以外の表現方法もあります。以下の図は対応分析と呼ばれる手法を用いて分析した結果です。

unified_taiou.png

この図では出版年が書いてある赤四角の領域に近い言葉ほど、その年に特徴的な言葉であることを意味します。
例えば2018年と2019年の四角は領域がほとんどかぶっていて、出てくる主要な語に変化が少なかったことを意味します。ただ、出てきている語を見ると、 CNN, reinforcementのような機械学習の具体的な手法や分野を表す語がなく、抽象的な語ばかりなので、ここからトレンドの変化を探ることはできませんでした。描く対象になる語の出現回数を制限するなど、パラメータを適切な値にできればそういったことが可能であったかもしれません。


参考文献


Twitter・Facebookで定期的に情報発信しています!

今回は「じゃらんの口コミをスクレイピングしてみた」ということで紹介していきます。
※この記事はスクレイピング初心者向けに書いています。

目次

 1はじめに
 2スクレイピング
 3可視化
 4分析・まとめ
 5注意すること
 6終わりに

はじめに

 皆さんは今年の冬をどのように過ごす予定でしょうか?
 今回は「冬」「雪」といえば「スキー」「温泉」ということで、この二つのキーワードに関連するホテル・旅館の口コミを分析しました。LINEトラベルのサイトによると、温泉が楽しめるスキー場1位は「山形蔵王温泉スキー場」のようです。
 このエリアの口コミ評価今現在第一位のホテルについてスクレイピングさせていただきました。

 今回は特定のホテルの口コミをスクレイピングし、どんな人が口コミを投稿し、どんな評価をつけているのかをグラフを表示しながら分析しました。

スクレイピング

 今回取得する情報

 ・性別
 ・年齢
 ・評価
 ・いつ宿泊したか
 ・誰と旅行したか
 ・価格帯

 この記事は初心者向けに書いていますので、コードを初めから紹介したいと思います。
 ここではスクレイピングからデータフレームを作るところまでを紹介しています。
 
 まずはじめに必要なものをインポートします。

 
from bs4 import BeautifulSoup import urllib
import pandas as pd 
import requests

 

取得したいホテル口コミページのURLを取得します。

html = requests.get('https://www.jalan.net/yad309590/kuchikomi/')
soup = BeautifulSoup(html.content,'html.parser')

このホテルの口コミページは3ページあったので、それぞれのURLをリストに入れておきます。

 url_list = ['https://www.jalan.net/yad309590/kuchikomi/?screenId=UWW3701&idx=0&smlCd=060203&dateUndecided=1&yadNo=309590&distCd=01',
'https://www.jalan.net/yad309590/kuchikomi/2.HTML?screenId=UWW3701&idx=30&smlCd=060203&dateUndecided=1&yadNo=309590&distCd=01',
'https://www.jalan.net/yad309590/kuchikomi/3.HTML?screenId=UWW3701&idx=60&smlCd=060203&dateUndecided=1&yadNo=309590&distCd=01']

ここから本題に入っていきます。
まず、口コミ投稿者の性別と年代を取得し、綺麗な形にします。

valuer = []
    for row in url_list:
row = str(row) html = urllib.request.urlopen(row) soup = BeautifulSoup(html) valuer.append(soup.find_all("span", class_='jlnpc-kuchikomi__cassette__user__name')) continue valuer_list = valuer[0]+valuer[1]+valuer[2] new_valuer_list = [] for row in valuer_list: row = str(row) new_valuer_list.append(row.split('(')1.split(')')0)

このようになります。


スクリーンショット 2019-12-27 15.22.27.png

性別・年代をそれぞれデータフレームに入れます。


data = pd.DataFrame()
sex = []  
age = []  
for row in new_valuer_list:
  row = str(row)
  sex.append(row.split(' / ')[0])
  age.append(row.split(' / ')[1])
 new_age = []
 for row in age:
   row = str(row)
   new_age.append(row.replace("代","'s")) 
 data['sex'] = sex
 data['age'] = new_age

スクリーンショット 2019-12-27 15.33.04.png

次に、口コミ評価を取得します。


value = []
for row in url_list:
    row = str(row)
    html = urllib.request.urlopen(row)
    soup = BeautifulSoup(html)
    value.append(soup.find_all("span", class_='jlnpc-kuchikomi__cassette__rating__em'))
    continue
value = value[0]+value[1]+value[2]
new_value = []
for row in value:
    row = str(row)
    new_value.append(row.split('')[1].split('')[0])
data['value'] = new_value

最後に、いつ・誰と・どのくらいの価格帯で利用したのか取得します。


what = []
 for row in url_list:
 row = str(row)
 html = urllib.request.urlopen(row)
 soup = BeautifulSoup(html)
 what.append(soup.find_all("div", class_='jlnpc-kuchikomi__cassette__attribute1 styleguide-scope'))
 continue
 
 what = what0+what1+what2
 
 new_what = []
 for row in what:
 row = str(row)
 new_what.append(row.split('')1.split('')0)
 
 date = []
 trip = []
 for row in new_what:
 row = str(row)
 date.append(row.split('【')1.split('宿泊')0)
 trip.append(row.split('\xa0\xa0')1.split('】')0)
 
 data['date'] = date
 data['trip'] = trip

 price = []
 for row in what:
 row = str(row)
  price.append(row.split('【宿泊価格帯】')1.split('(大人1人あたり/税込)')0)

 data['price'] = price

データフレームが完成しました。


スクリーンショット 2019-12-27 15.52.35.png

可視化

ここでは先ほどスクレイピングした口コミ投稿者のデータについて可視化し、簡単に考察します。
まずはじめに、取得したデータについて簡単に見ていきましょう。


性別

スクリーンショット 2019-12-27 16.09.00.png

年代


スクリーンショット 2019-12-27 16.18.32.png

口コミ評価


スクリーンショット 2019-12-27 16.27.10.png

いつ利用したか


スクリーンショット 2019-12-27 16.30.44.png

誰と利用したか


スクリーンショット 2019-12-27 16.34.27.png

価格帯


スクリーンショット 2019-12-27 17.35.14.png

分析・まとめ

データからわかること
・口コミ投稿者は50代が一番多く、60代、40代と続く。
若い層(20代、30代)よりも多いのは、お金に余裕があるからなのか、あるいは温泉地ということが関係しているのか。
  ・今回「スキー」と「温泉」というキーワードで探したが、2019年8月の投稿が多い。夏でも人気のある観光地なのかもしれない。
・大人1人あたり1万円を超え、高いものは3万円を超えるものもあることがわかる。夫婦旅行が多いことにも関係していそう。


 

仮説:蔵王には、お金に比較的余裕があり、子育ても終わった50代の夫婦が旅行に来ることが多いのでしょうか。8月に口コミが多かったのも、冬に体力の必要なスキーを楽しむのではなく、ゆったりと自然を感じたいという人が多いのかもしれません。もしかすると、今回、「スキー」「温泉」で蔵王が出てきたのは、スキーで有名という理由だけではなく、体力のある若い世代に冬の時期に多く来て欲しいという地域の狙いがあるのかもしれません。


今回取得した口コミの数は74件と少なく、取得したデータの種類も少ないため、事実に対して理由を断定することはできません。しかし、だからこそ上記の仮説のように想像を膨らませ、いろいろなことに思いを巡らせることができるのかもしれませんね。


注意すること

口コミを分析する際にはいくつか気をつけなければいけないことがあります。
・口コミ分析は、宿泊者全員について分析できるというわけではなく、あくまで「口コミをした人」のみに対する分析となります。もしかしたら、男性よりも女性の方が口コミをするのが好きかもしれないし、年齢層が高めの人より若い人の方が口コミを投稿するということもあり得ます(その逆も然り)。
 口コミを分析している時点で情報を限定してしまっているということに気をつける必要があります。
・上と似ているのですが、口コミを投稿する人はどんな人かを考える必要があります。
 口コミを通して伝えたい!という人はどんな人でしょうか?宿泊にとても満足してお礼を伝えたい、良さを伝えたいという人や、何か不満があって意見を言いたい、改善策を伝えたいという人が想定されます(不満だった人は関わりたくないから口コミを投稿しないということも考えられます)。可もなく不可もなく感じている人は、口コミ投稿するのが好きという人を除き、わざわざ口コミを投稿するでしょうか?
・口コミは利用した人の感想ですから、主観が入り、その情報が正確かを確かめることは難しいでしょう。もしかしたら嘘をついている人や誇張して書いている人、あるいはサクラがいるという可能性も0ではありません。完全ではないということを意識する必要があります。
・今回は、口コミ評価が高評価に著しく偏っているため、どんな人が高評価・低評価をするのか明らかにすることはできませんでした。「口コミ評価が高評価に著しく偏っている」のは、このホテルに限ることなのか、もしくはエリア全体、口コミ全体でそういう傾向があるのかを明らかにすると、今後の口コミ分析の役に立つかもしれません。

終わりに

今回は特定のホテルの口コミをスクレイピングし、投稿者についての分析を行いました。
 次回は、今回のスクレイピングの手法を活かして、どこかの「エリア」のホテル・旅館についてスクレイピングし、そのホテル・旅館ごとの傾向や、どんな人がそのホテル・旅館に向いているかなどを考察していこうと思います。
 後々、機械学習を用いて、旅行しようと思っている人に最適なホテルをオススメできる機能を作りたいと考えています。



Twitter・Facebookで定期的に情報発信しています!

アクセルユニバース株式会社(以下当社)では、人が対応している業務を画像認識、音声認識、文字認識等を活用して効率化する機械学習ソリューション開発をおこなっています。


インターン生は業務の一環としてkaggleに取り組んでおり、先日のNFL Big Data Bowlコンペにて銅メダルを獲得しました。
こちらのコンペは、アメリカンフットボールのランプレイにおいて、攻撃側が進むヤード数を予測するコンペです。


メダル獲得した小野くんのコメントです。
ーーー
主な勝因は特徴量エンジニアリングの部分だと考えています。
調子に波があるだろうと考えたので選手やチームの情報は極力使わず、選手の位置情報や進行方向のベクトルを用いて様々な切り口で特徴量を作ることに注力しました。

その他、今回はカーネルコンペであったため、以前よりコーディング力がつき、メモリやコードの実行時間に対する意識も増しました。
また過学習を防ぐことの重要性を再認識しました。
ーーー


現在、解法を詳しく解説したものを公開できるように準備を進めています。


その他当社インターンでは論文のまとめ記事論文 Attention Is All You Need から Attentionモデルの解説を書いたり、実際にTensorFlowでVGG19を使ったインスタ映え画像の生成実装をしています。 随時紹介していくので是非ご覧ください!


Twitter・Facebookで定期的に情報発信しています!

はじめに

この記事では物体検出に興味がある初学者向けに、最新技術をデモンストレーションを通して体感的に知ってもらうことを目的としています。今回紹介するのはAAAI19というカンファレンスにて精度と速度を高水準で叩き出した「M2Det」です。one-stage手法の中では最強モデル候補の一つとなっており、以下の図を見ても分かるようにYOLO,SSD,Refine-Net等と比較しても同程度の速度を保ちつつ、精度が上がっていることがわかります。
M2Det

https://arxiv.org/pdf/1811.04533.pdfより引用

物体検出デモ

それではM2Detでの物体検出をしていきたいのですがひとつ問題が
著者がgithubに公開しているソースコードはCUDAを使用する前提のため、NVIDIAのGPUが搭載していない私のPCではすぐに動かす事ができません。
そのため今回はGPUなしでも動かせる環境を提供してくれるGoogle先生の力をお借りします!
ということでGoogle Colaboratoryを使ってM2Detを動かしていきます。
例のごとくqijiezhao/M2Detの説明を参考に進めていきます。


Step1.前準備

Google Colaboratoryを開いたら先ずハードウェアのアクセラレータをGPUに設定しましょう。メニューバーの「ランタイム」→「ランタイムのタイプを変更」をクリック。「ハードウェア アクセラレータ」のプルダウンからGPUを選択して「保存」します。これで設定は完了です。
M2Det
それではコードを書いていきます。必要なモジュールをインストールし、上記githubからクローンを作成します。M2Detファイルに移動したらシェルを以下のように実行します。

!pip install torch torchvision
!pip install opencv-python tqdm addict
!git clone https://github.com/qijiezhao/M2Det.git
%cd M2Det
!sh make.sh

Step2.学習済モデルをGoogle Driveからダウンロードする(引用)

次に学習済モデルを入手します(とてつもなく学習に時間がかかるので出来合いのものを使用させていただきます)。githubの説明にも書いてあるようにbackbornはVGG-16とし、指定のGoogle Driveからダウンロードしてきます。ダウンロードが簡単にできる便利なもの(nsadawi/Download-Large-File-From-Google-Drive-Using-Python)を見つけたので引用させていただきます。

#引用開始
import requests
def download_file_from_google_drive(id, destination):
  URL = "https://docs.google.com/uc?export=download"
  session = requests.Session()
  response = session.get(URL, params = { 'id' : id }, stream = True)
  token = get_confirm_token(response)
  if token:
    params = { 'id' : id, 'confirm' : token }
    response = session.get(URL, params = params, stream = True)
  save_response_content(response, destination)
def get_confirm_token(response):
  for key, value in response.cookies.items():
    if key.startswith('download_warning'):
      return value
    return None
def save_response_content(response, destination):
  CHUNK_SIZE = 32768
  with open(destination, "wb") as f:
    for chunk in response.iter_content(CHUNK_SIZE):
      if chunk: # filter out keep-alive new chunks
        f.write(chunk)
#引用終了
%mkdir weights
directory = '1NM1UDdZnwHwiNDxhcP-nndaWj24m-90L'
adress = './weights/m2det512_vgg.pth'
download_file_from_google_drive(directory, adress)

これでM2Detフォルダの中に学習済モデルm2det512_vgg.pthがダウンロードできました。


Step3.判別の閾値を設定する(任意)

ここで一旦パラメータの調整を挟みます。YOLOでは判別の閾値が0.5以上の時にアノテーションすることにしていたのでM2Detでも同じ値にします。demo.pyの63行目を確認すると

def draw_detection(im, bboxes, scores, cls_inds, fps, thr=0.2):

thrの値がデフォルトで0.2になっているのでこの値を0.5に以下のように書き換えます。

!sed -i -e "63c def draw_detection(im, bboxes, scores, cls_inds, fps, thr=0.5):" demo.py

Step4.Google Driveにアップロードした動画ファイルをM2Detフォルダの指定ディレクトリにコピーする

後は判別させたい画像または動画をGoogle Driveからimgsフォルダに移動させてきましょう。なのでご自分で予めGoogle Driveに画像または動画をアップロードしておきましょう。今回は動画を使用しているので以下のようにマウントした後、任意の動画をコピーします。実行の際にオースコード(Auth code)が要求されるのでURLをクリックして表示されるコードを貼り付けます。

from google.colab import drive
drive.mount('/content/drive')
!cp /content/drive/My\ Drive/*.mp4 ./imgs #動画用

M2Det
これで必要なものは全て揃いました。

Step5.デモ

ここでdemo.pyの引数について確認してみます。demo.pyの17行目から24行目を確認すると以下のように記述されています。

parser = argparse.ArgumentParser(description='M2Det Testing')
parser.add_argument('-c', '--config', default='configs/m2det320_vgg.py', type=str)
parser.add_argument('-f', '--directory', default='imgs/', help='the path to demo images')
parser.add_argument('-m', '--trained_model', default=None, type=str, help='Trained state_dict file path to open')
parser.add_argument('--video', default=False, type=bool, help='videofile mode')
parser.add_argument('--cam', default=-1, type=int, help='camera device id')
parser.add_argument('--show', action='store_true', help='Whether to display the images')
args = parser.parse_args()

parser.add_argumentの直後に記述されている引数を実行の際に記述することで様々な使い方ができるようです。別途ダウンロードしてきた学習済モデルで動画を判別させるので以下のように実行します。

!python demo.py -c=configs/m2det512_vgg.py -m=weights/m2det512_vgg.pth --video VIDEO #動画用

実行すると動画のディレクトリを指定するように出てくるのでディレクトリを指定します(Step4でimgsフォルダにコピーしたならimgs/(ファイル名))
後は各フレーム毎に物体検出をしてくれるので待ちましょう。
M2Det

Step6.ファイルをダウンロードする

残念ながらmp4をchrome上で再生する術を知らないため、ローカルにダウンロードして再生することにします。以下のように2行で簡単にファイルのダウンロードができます。

from google.colab import files
files.download('imgs/<ファイル名>')

実装例

おわりに

今回M2Detを使用して動画の物体検出を行ってみました。リアルタイムの識別を検討する場合は限られた時間内に一定以上の精度を保証する信頼性がより重要となり、M2Detはこれを達成する一歩になるのでは無いかと思いました。YOLOやSSDについてもまだまだ改良されていくと予想しているので、引き続きリサーチしたいと思います。また、物体検出を利用した異常検知や店の空席率把握などに使えそうなので実装できたらまたブログ書こうと思います。

実装コード

https://colab.research.google.com/drive/1oSPhiGmZC-IeLnyoR2l-UIKIquP1i51g

その他、ドーナツを検知し、無人レジの実現に向けて検証もしており、現在、当社では技術の実用化に向けて様々な検証をしています。


Twitter・Facebookで定期的に情報発信しています!

概要

Adversarial ValidationはTrainデータとTestデータの分布が異なる際に、Testデータに似たValidationデータを作成するのに使われる手法です。
Kaggleなどのデータ分析コンペではTrainデータとTestデータの一部が与えられ、コンペ終了まではこの一部のTestデータに対するスコアのみ知ることができます。一部のTestデータだけを見てモデルを評価していると、全体のテストデータに対しては良いスコアが出ずに最終的に低い順位に終わることがあります。ですのでCross Validationなどを用いて求めたValidationデータに対するのスコアと一部のTestデータに対するスコアに相関があることが望ましい状態です。そのために重要なことはTestデータに似た分布を持つValidationデータを作成することです。


手法

最終的な目標はTrainデータとTestデータを分類するモデルを作成することです。

まずどちらのデータセットからのデータかをラベル付けするために、TrainデータとTestデータにそれぞれ新しい目的変数を与えます。例えばTrainデータには "1"を、Testデータには"0"を与えます。そしてTrainデータとTestデータを結合して、データがどちら由来か予測するモデルを作成します。
もしTrainデータとTestデータが同じ分布を持つとするとどちら由来かを予測できないはずです。逆にTrainデータとTestデータの分布が異なる場合は予測は容易になります。
予測結果からTrainデータとTestデータの分布が異なるようであれば、Testデータの分布に似たValidationデータを作成する必要があります。これはTrainデータのうち、モデルがTestデータに由来する確率が高いと予測したデータを選ぶことで作成できます。


それでは必要なライブラリをインポートして実装に進みましょう。

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
warnings.filterwarnings('ignore')
from tqdm import tqdm_notebook as tqdm

from sklearn.preprocessing import LabelEncoder
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
import lightgbm as lgb


TrainデータとTestデータの分布が同じ場合

まずデータセットを作成し、プロットしてみます。

X, y = make_classification(
    n_samples=10000,
    n_features=2,
    n_informative=1,
    n_redundant=0, 
    n_classes=2,
    n_clusters_per_class=1,
    class_sep=2.0,
    random_state=42
)

plt.scatter(X[y == 0, 0], X[y == 0, 1], s=10, alpha=0.5, label='class A')
plt.scatter(X[y == 1, 0], X[y == 1, 1], s=10, alpha=0.5, label='class B')
plt.legend(loc='upper right')
plt.show()

plot of dataset


このデータセットをTrainデータとTestデータに分け、Trainデータには "1"を、Testデータには"0"をそれぞれ新しく目的変数として与えます。その後、TrainデータとTestデータを結合して1つのデータセットに戻します。

X_train, X_test = train_test_split(X, test_size=0.33, random_state=42)

y_train = np.zeros(len(X_train))
y_test = np.ones(len(X_test))

X_all = np.concatenate([X_train, X_test], axis=0)
y_all = np.concatenate([y_train, y_test], axis=0)


これでTrainデータとTestデータが混ざったデータセットが出来上がりました。ここから新たに与えた目的変数を元にTrainデータとTestデータを分類するモデルを作成していきます。

X_train_adv, X_valid_adv, y_train_adv, y_valid_adv = \
    train_test_split(X_all, y_all, test_size=0.33, random_state=42, shuffle=True)

model = lgb.LGBMClassifier(
    n_estimators=1000,
    random_state=42)

model.fit(
    X_train_adv,
    y_train_adv,
    eval_set=[(X_train_adv, y_train_adv), (X_valid_adv, y_valid_adv)],
    eval_names=['train', 'valid'],
    eval_metric='auc',
    verbose=100)


このときのValidationデータを作成しモデルの性能を評価します。 ではモデルのパフォーマンスを見てみましょう。

ax = lgb.plot_metric(model.evals_result_, metric='auc')
plt.show()

plot of learing curve


結果を見ると、Validationデータに対してAUCはほぼ0.5あたりを示しています。AUCが0.5を示すということはモデルのパフォーマンスがランダムに分類するのと変わらないことを意味しています。これはモデルがTrainデータとTestデータをうまく分類できてないということです。つまりTrainデータとTestデータの分布が同じであることがわかります。


TrainデータとTestデータにの分布が異なる場合

次にTrainデータとTestデータの分布が異なる場合を見ていきましょう。

データはKaggleの2019 Data Science Bowlのデータを引っ張ってきました。データの中身や特徴量作成に関して、ここではコードだけにして割愛させていただきます。

test = pd.read_csv("../input/data-science-bowl-2019/test.csv")
train = pd.read_csv("../input/data-science-bowl-2019/train.csv")


def get_data(user_sample, test_set=False):
    all_assessments = []
    type_count = {'Clip':0, 'Activity': 0, 'Assessment': 0, 'Game':0}

    for i, session in user_sample.groupby('game_session', sort=False):
        session_title = session['title'].iloc[0]
        session_type = session['type'].iloc[0]

        if (session_type == 'Assessment') and (test_set or len(session) > 1):
            event_code = 4110 if session_title == 'Bird Measurer (Assessment)' else 4100
            all_attempts = session.query(f'event_code == {event_code}')
            num_correct = all_attempts['event_data'].str.contains('true').sum()
            num_incorrect = all_attempts['event_data'].str.contains('false').sum()

            features = {}
            features['installation_id'] = session['installation_id'].iloc[-1]
            features['title'] = session_title
            features['num_correct_attempts'] = num_correct

            features.update(type_count.copy())

            if test_set:
                all_assessments.append(features)
            elif num_correct + num_incorrect > 0:
                all_assessments.append(features)

        type_count[session_type] += 1

    if test_set:
        return all_assessments[-1]

    return all_assessments


compiled_train = []
for ins_id, user_sample in tqdm(train.groupby('installation_id', sort=False), total=17000):
    compiled_train += get_data(user_sample)

compiled_test = []
for ins_id, user_sample in tqdm(test.groupby('installation_id', sort=False), total=1000):
    test_data = get_data(user_sample, test_set=True)
    compiled_test.append(test_data)

X_train = pd.DataFrame(compiled_train)
X_test = pd.DataFrame(compiled_test)


特徴量作成の後にできたTrainデータとTestデータは次のようになっています。

display(X_train.head())
display(X_test.head())

heading of training and test dataframes


余分なinstallatio_idカラムは削除して、titleカラムのエンコーディングを行っておきましょう。

X_train = X_train.drop(['installation_id'], axis=1)
X_test = X_test.drop(['installation_id'], axis=1)

le = LabelEncoder()
le.fit(list(X_train['title'].values) + list(X_test['title'].values))
X_train['title'] = le.transform(list(X_train['title'].values))
X_test['title'] = le.transform(list(X_test['title'].values))


ここから先は上記のプロセスと同じくTrainデータとTestデータに新たな目的変数を与えて結合した後、TrainデータとTestデータが混ざったデータからそれぞれを分類していきます。

X_train['adv_target'] = 0
X_test['adv_target'] = 1
train_test_adv = pd.concat([X_train, X_test], axis=0).reset_index(drop=True)

train_adv, valid_adv = train_test_split(train_test_adv, test_size=0.33, random_state=42)
X_train_adv = train_adv.drop(['adv_target'], axis=1)
y_train_adv = train_adv['adv_target']
X_valid_adv = valid_adv.drop(['adv_target'], axis=1)
y_valid_adv = valid_adv['adv_target']

model = lgb.LGBMClassifier(
    n_estimators=1000,
    random_state=42)

model.fit(
    X_train_adv,
    y_train_adv,
    eval_set=[(X_train_adv, y_train_adv), (X_valid_adv, y_valid_adv)],
    eval_names=['train', 'valid'],
    eval_metric='auc',
    verbose=100)


ではモデルのパフォーマンスを見てみましょう。

ax = lgb.plot_metric(model.evals_result_, metric='auc')
plt.show()

plot of learing curve


Validationデータに対するAUCはおよそ0.93あたりで、TrainデータとTestデータの分布が同じ場合に比べモデルのパフォーマンスが良いことがわかります。これは今回用いたTrainデータとTestデータの分布が異なるため、モデルが容易に分類できるからです。

このようにして得られた結果から、TrainデータのうちTestデータである確率が高いと予測されたデータを取り出すことでTestデータに似たValidationデータを作成することが可能になります。またTrainデータとTestデータの分布が異なるかどうか見分ける指標としてAdversarial Validationを使うこともできます。


特徴量選択への応用

最後にAdversarial Validationを応用して特徴量選択を行う方法を紹介します。

まず先程のTrainデータとTestデータの分布が異なる場合に、予測に寄与した特徴量の重要度を見てみましょう。

plot of feature importance


これを見ると num correct attempts の重要度が高くなっています。これは num correct attempts がTrainデータかTestデータかの分類に大きく寄与していることを示しています。つまりTrainデータとTestデータの間でこの特徴量に乖離があることを意味しています。

これを受けて num correct attempts のカラムを削除してTrainデータとTestデータの分類を行ってみると、

new_X_train_adv = train_adv.drop(['num_correct_attempts'], axis=1)
new_X_valid_adv = valid_adv.drop(['num_correct_attempts'], axis=1)

model = lgb.LGBMClassifier(
    n_estimators=2000,
    random_state=42)

model.fit(
    X_train_adv,
    y_train_adv,
    eval_set=[(new_X_train_adv, y_train_adv), (new_X_valid_adv, y_valid_adv)],
    eval_names=['train', 'valid'],
    eval_metric='auc',
    verbose=100)

ax = lgb.plot_metric(model.evals_result_, metric='auc')
plt.show()

plot of learing curve


たしかにAUCスコアが低くなりTrainデータとTestデータの分類がしづらくなっていることがわかります。

このようにしてAdversarial Validationを応用することによって、TrainデータとTestデータで乖離している特徴量を見つけることができます。


まとめ

今回はKaggleなどの機械学習コンペで注目されているAdversarial Validationを紹介しました。Kaggleにおいて手元のバリデーションスコアとLeader Boardのスコアに乖離がある際に、適切なValidation setの作成や特徴量選択に役立ちます。実際に私もコンペで利用しており、今後ますます注目を浴びるのではないかと思われます。


Twitter・Facebookで定期的に情報発信しています!

【ネタバレあり】


皆さん今年のM-1グランプリご覧になりましたか? 今年はミルクボーイさんが見事歴代最高得点で優勝しました。本当におめでとうございます!


ミルクボーイさんといえば

「それコーンフレークやないかい!」

「いやほなコーンフレークちゃうやないかい!」

と一方の文章に対してもう一方がコーンフレークかどうかをつっこむ、というネタですよね。


そこでテレビを見ながら思ったわけです。

「これって、機械学習でできるんじゃね?」

与えられた文章に対して、それがコーンフレークについての文章かどうかを判別する、というのはいかにも機械学習ができそうなことです。

ということで作ってみました!

スクリーンショット 2019-12-27 16.40.46.png @1_milkboy
このツイッターアカウントは入力した文章に対して「それコーンフレークやないかい!」/「いやほなコーンフレークちゃうやないかい!」と突っ込んでくれます。


BERTを使ってみた

まずは、元データを用意します。
これはミルクボーイさんの漫才の中の言葉の他に、ウィキペディアの記事などから集めてきました。
コーンフレークなら1、そうでないなら0という風に値を指定していきます。
時間もなかったので、全部で70件ほどしか集まりませんでした...
image1.png
次に、学習機です。
文章の学習、ということで用いたのはBERTです。(BERTについてはこちらを参照
Googleさんが104ヶ国語に対応しているmultilingual BERTを公開しているので、改めて日本語を学習していく必要はありません。
日本語を学習済みのBERTを使って、元データを読み込ませてどういう分がコーンフレークなのか学習していきます。

train = pd.read_csv(text, header=0)
BERT_MODEL_HUB = "https://tfhub.dev/google/bert_multi_cased_L-12_H-768_A-12/1"

[途中略]

print(f'Beginning Training!')
start_time = datetime.now()
model.train(input_fn=train_input_fn, max_steps=num_train_steps)
print("Training took time ", datetime.now() - start_time)


学習が終わったところで、実際の文で試していきましょう!

今回は
「朝ごはんに食べると目が覚めるやつ」

「ごはんと食べるとおいしいやつ」
の2文で試していきます。

前者が「ほなそれコーンフレークやないか」、後者が「ほなそれコーンフレークちゃうやないか」の予定なのですが、元データが少ないので、「朝ごはん」と「ごはん」の違いに引っかからないかがポイントですね。


labels = ["ほなそれコーンフレークやないか", "ほなそれコーンフレークちゃうやないか"]

[途中略]

predict_text = ["朝ごはんに食べると目が覚めるやつ", "ごはんと食べるとおいしいやつ"]
predictions = getPrediction(model, predict_text)
predictions


結果がこちら!
image2.png
残念ながらどちらも「ほなそれコーンフレークやないか!」とつっこまれています...
やはり元データを増やさないと精度はまだまだ出ませんね。


Word2Vecを使ってみた

ということで今度はWord2Vecを使ってみました!(切り替えが早い...)
BERTはWord2Vecより性能が高いのですが、元データが小さい場合、Word2Vecでキーワードだけ拾ったほうがよいのではと思い試してみることにしました。
まずは日本語のWord2Vecを(http://www.cl.ecei.tohoku.ac.jp/~m-suzuki/jawiki_vector/)から引っ張ってきました。
BERTもそうでしたが、日本語に対して学習済みの機械が出ているのは非常に助かりますね!

次に、入力を処理していきます。与えられた文章の中から名詞と動詞のみを抽出し、単語のlistにします。

def counter(texts):
            t = Tokenizer()
            word_count = defaultdict(int)
            words = []
            for text in texts:
                tokens = t.tokenize(text)
                for token in tokens:
                    pos = token.part_of_speech.split(',')[0]
                    if pos in ['名詞', '動詞']:
                        # 必要ない単語を省く(実際の結果を見て調整)
                        if token.base_form not in ["こと", "よう", "そう", "これ", "それ", "もの", "ため", "ある", "いる", "する"]:
                            word_count[token.base_form] += 1
                            words.append(token.base_form)
            return word_count, words


続いて、この単語のlistとキーワード(今回はコーンフレーク)との相関度を計算します。
Gensimのライブラリは充実しているので一行ですみます。

score = self.model.n_similarity([keyword], words)


最後にこの数字が0.5以上なら「ほなそれコーンフレークやないか」、0.5以下なら「ほなそれコーンフレークちゃうやないか」を出力する、という形にしました。

if (score > 0.5):
          return("ほなそれコーンフレークやないか")
        else:
          return("ほなそれコーンフレークちゃうやないか")


これをキーワードは「コーンフレーク」、文章は「アフリカの名産品って言ってた」で試してみましょう。
文章の中から「アフリカ」「名産品」「言って」を抜き出し、それぞれと「コーンフレーク」との相関の平均を取ります。
するとなんということでしょう、「ほなそれコーンフレークちゃうやないか」と出力されるではありませんか!

さきほど失敗した「ごはんとめっちゃ合うって言ってた」でも試してみると、
今度は大成功です!


まとめ

今回Word2VecとBERTの両方を試してみて、ぱっと見たところWord2Vecのほうが結果が良いことがわかりました。
しかしこれは本当は苦肉の策です。単語だけを抜き出すより、文脈全体を考慮したほうがよいですし、0.5という敷居値も独断っと偏見でしかありません。それぞれの単語とキーワードの相関も足し合わせただけではホントは良くないかもしれません。そういった点で、最初にBERTを使ってみたのですが、いかんせん元データの数が少なすぎました。いずれ十分なデータ量がたまれば、BERTが活躍できる日が来るかもしれません。
最終的にはミルクボーイさんとコラボなんてしてみたいですね。
それではまた!皆様よい新年をお迎えください!


Twitter・Facebookで定期的に情報発信しています!

はじめに

まずは下の動画をご覧ください。
スクリーンショット 2019-12-27 17.18.19.png
スパイダーマン2の主役はトビー・マグワイアですが、この動画ではトム・クルーズがスパイダーマンを演じています。
これは実際にトム・クルーズが演じているのではなく、トム・クルーズの顔画像を用いて合成したもので、機械学習の技術を用いて実現できます。
機械学習は画像に何が写っているか判別したり、株価の予測に使われていましたが、今回ご紹介するGANではdeep learningの技術を用いて「人間を騙す自然なもの」を生成することができます。
「人間を騙す自然なもの」を作るには本物のデータがどのように生成されるのか理解しなければなりません。
例えば、猫の画像を生成するときに耳を3つ書いたりしません。なので猫の耳は2つであるということを学習しなければなりません。


GANによる成果物をもう1つ紹介します。こちらのサイトにアクセスすると人物の顔が出てきます。
ですが出てくる人物はこの世に存在せず、GANが生成した人物です。
ご覧になっていただいてわかるように不自然なところは何もありません。


1. GANとは

GANとはGenerative Adversarial Networksの略で敵対的生成ネットワークとも呼ばれ、2014年に発表されました。
特徴は2つのネットワークを戦わせることにあります。

Gをデータを生成するネットワーク(Generator)、DをデータがGから生成されたものか実際のデータかを判別するネットワーク(Discriminator)とします。
GはDを騙すような画像を生成できるように、DはGから生成されたデータを見抜けるように、競いながら学習をします。
論文では例として、Gを偽札を作る悪人、Dを偽札を見抜く警察としています。


全体のネットワーク構造は以下のようになっています。
deep-learning-for-computer-vision-generative-models-and-adversarial-training-upc-2016-5-638.jpg

Gを図中のGenerator、Dを図中のDiscriminatorとします。
Gは何かしらの確率分布 P_z (一様分布など)から生成されたデータ z (図中 Latent random variable)から、通常のネットワークのように重みをかけて本物と同じサイズの画像を生成します。
Dは入力として画像(図中 sample)を受け取り、本物か偽物かを判定します。

D(・) を「・が本物のデータと判断する確率」としたとき、GAN は以下のような評価関数を最小化するようにGとDのパラメータ θ_g と θ_d を更新していきます。
\begin{eqnarray*} \min _{G} \max _{D} V(D, G)=\mathbb{E}_{\boldsymbol{x} \sim p_{\text {data }}(\boldsymbol{x})}[\log D(\boldsymbol{x})]+\mathbb{E}_{\boldsymbol{z} \sim p_{\boldsymbol{z}}(\boldsymbol{z})}[\log (1-D(G(\boldsymbol{z})))] \end{eqnarray*}

2. アルゴリズム

パラメータθgとθdを更新する手順を以下に示します。
kはハイパーパラメータです。


1. 2~4をイテレーションの数だけ繰り返す
  2. (2-1)~(2-4)をkの数だけ繰り返す
    2-1. pzからm個のサンプル{z1,z2...zm}を取得
    2-2. 実際のデータからm個のサンプル{x1,x2,...xm}を取得
    2-3. θ
dを以下のように更新<

更新式1

  3. pzに従うm個のサンプル{z1,z2...zm}を取得
  4. θ_gを以下のように更新

\begin{eqnarray*} \nabla_{\theta_{d}} \frac{1}{m} \sum_{i=1}^{m}\left[\log D\left(\boldsymbol{x}^{(i)}\right)+\log \left(1-D\left(G\left(\boldsymbol{z}^{(i)}\right)\right)\right)\right] \end{eqnarray*}

更新式2

\begin{eqnarray*} \nabla_{\theta_{g}} \frac{1}{m} \sum_{i=1}^{m} \log \left(1-D\left(G\left(\boldsymbol{z}^{(i)}\right)\right)\right) \end{eqnarray*}


3. おまけ 学習の様子

zがpzに従うときG(z)がpgに従うとします。
概略は以下のようになります。

スクリーンショット 2019-12-26 13.58.30.png


GANの目的はpg = pdataとなることです。
つまり本物のデータが生成される分布pdataとpgが等しいため、理論上は見分けがつかないことです。
これを言い換えるとD(x) = 1/2 が成り立つことだとも言えます。
これは、Dが本物のデータxをを本物だと見分ける確率が1/2で、当てずっぽうで判断していることになります。


論文にはpgがpdataに近づいていく様子が載せられています。
スクリーンショット 2019-12-26 12.28.58-1.png


青のドット線 : D(x)
緑の線 : pg
黒のドット線 : 実際のデータxが従う確率分布p
data

  • a
    学習前の様子です。

  • b Dが上のアルゴリズム(2-3)の手順で更新された後です。

  • c Gを上のアルゴリズム4の手順で更新された後です。
    bの状態と比べて、pgがpdataに近づいた事がわかります。

  • d pg = pdataとなった様子です。

4.まとめ

GANは人を自然な画像を生成するだけでなく、最初に挙げたスパイダーマンのように2つの画像を自然に合成することもできるようです。
買おうか迷っている服を自分の体に合成して、擬似的に試着することもできます。
服の試着だけでなく、化粧品のお試しや、髪型が自分に合うのかなどを事前にわかっていると便利そうです。
今後はGANについて最新の傾向をつかめるようにしていきたいと思います。


Twitter・Facebookで定期的に情報発信しています!


"TASK2VEC"は2019年2月にsubmitされた論文の中で提唱された手法であり、「タスクをベクトル化する」手法です。 この手法が提唱されるまでは、"タスク間の関係を表現する"フレームワークが存在しなかったため、一部界隈で脚光を浴びました。
しかし、このTASK2VECの言わんとすることが理解出来ても、どういうものなのか正直ちょっとわかりにくいです。そこで今回は出来るだけ論文の内容をかみ砕いて解説したいと思います。

目次

1.TASK2VEC 概要
2.事前知識
3.TASK2VEC 手順
4.論文の実験結果
5.まとめ
6.参考文献


1.TASK2VEC 概要

上でも述べたように、"TASK2VEC"は「タスク」または対応するデータセットをベクトル化します。ここで言う「タスク」とはデータセットとラベルの組み合わせのことです。
この論文によると、事前学習によって得られたモデルを利用し、タスクの埋め込み表現、つまりベクトル表現を獲得します。 これによってタスクの間の類似度を算出でき、適切な事前学習済みモデルを選択できるようになるということです。
例えば、「犬」の画像認識を行うことを考える時、「人」の画像認識で用いたパラメータより「猫」の画像認識で用いたパラメータを使って画像分類した方が良さそうですよね。直感的にはこういうことです。

さらに具体的に見ていきましょう。ここでは次の節の事前知識を見ておくと良いです(特にFIMのところ)。
本論文では「probe network」と呼ばれるネットワーク(特徴抽出器)を用います。 この「probe network」はImageNetで事前学習させた唯一の特徴抽出器であり、この事前学習ののち、特定のタスクの分類レイヤでのみ再学習させます。 学習が完了したら、特徴抽出器で得られたパラメータのFIMを計算します。このFIMはタスクに関する重要な情報を含んでいるのですが、これについては後述します。
ここでは「probe network」という単一の特徴抽出器を用いているため、各タスクを固定長の、つまりクラス数などの詳細に依存しないベクトルとして埋め込むことができるということです。


活用事例

このTASK2VECですが、実際に社会に活用できることとして考えられるのが、

画像を分類したい→データ数が少ないので転移学習を使おう
→良い学習済みモデルないかな?TASK2VECで探してみよう!


などの一連の流れが考えられます。ちょっと抽象的かもしれませんが、つまりはサンプル数が少なすぎても諦めないで!という感じです。 (強化学習の考え方に近いかもしれません)

2.事前知識

転移学習(Transfer Learning)

この記事をご覧になっている方は、この「転移学習」について既にご存知かと思いますが簡単に説明します。 転移学習とは、ある領域(ドメイン)で学習させたことを、他の領域に役立たせ効率よく学習させることです。事前に学習させたモデルを学習済みモデルと言ったりします。 「データの時代」と言われるこの世の中ですが、データの入手が困難なケースもあります。そういった少ないデータ量で学習を進めていく際、この転移学習は真価を発揮します。 また数万〜数十万もの教師データを集め、各々にラベル付けを行うにはかなりの人件コストがかかります。このように、既にある(精度のいい)モデルを、別のものに使いまわす転移学習はこれからの時代必要不可欠でしょう。

転移学習のステップとして、
1.与えられたデータから、特徴量を抽出:
学習済みモデルの最終層以外の部分を利用して、データ内の特徴量を抽出します。ここで得られた学習済みモデルを「特徴抽出器」と言います。

2.抽出した特徴量を用いて、クラス分類する:
1.で実際に求めた特徴量を用いて、新しく追加したモデルに学習を施します。特に画像や音声を識別するモデルは他の分野に比べて流用しやすいため、転移学習が役立ちます。

この転移学習の可能性について、かの有名なcourseraの講師であるAndrew Ngは「機械学習の成功を今後推進するのは、教師なし学習、そして最近目覚ましい進化を遂げている強化学習でもなく、転移学習である」と言及しています。


メタ学習(Meta Learning)

メタ学習とは、「学習方法を学習する(learning to learn)」ことに他なりません。
人間で例えるなら、勉強をする際に教科書や参考書を読み込んだりしますが、ただ読むとしてもその方法は人によって様々です。 そこで、効率が良く理解しやすい読み方が分かれば勉強しやすいですよね。その方法を学習するのがここで言うメタ学習です。

ディープラーニングにおけるメタ学習は次の3つのステップに分けられます。

1.どのタスクでも、同じディープラーニングモデルを使う
2. 各タスク自体がどのようなものかを表す特徴ベクトルをディープラーニングによって抽出し、このベクトルと1.のモデルを使ってタスクを行う
3.各タスクで少数のデータを使って再学習させ、満遍なく良い結果が得られる1.のモデルを見つける

結果として、様々なタスクに特化したモデルが得られると言うわけです。


フィッシャー情報行列(FIM)

タスクを解くためには、入力\(x\)とそれに対応するラベル\(y\)の関係\(p_w (y|x)\)を学習する必要があります。 \(p_w (y|x)\)は重み\(w\)において入力\(x\)(例えば画像データ)が与えられた時、クラス(ラベル)が\(y\)である確率を示しています。
ここで、パラメータ\(w\)がこのタスクを解く際にどれほど重要な情報を含んでいるのか知るために、その摂動\(w'=w+\delta w\)について考えます。 \(p_w (y|x)\)と\(p_{w'} (y|x)\)が大きく異なるようであれば、そのタスクはパラメータに大きく依存していることがわかります。
これを計算する指標としてKLダイバージェンスと呼ばれるものがあります。その二次近似は、 \(\hat{p}\)を訓練データによって定義される経験分布とすると、 $$ \mathbb{E}_{x\sim \hat{p}}KL(p_{w'} (y|x) || p_w (y|x)) = \delta w \cdot F\delta w + \mathcal{o}(\delta w^2) $$ ここで出てきた右辺のFが、フィッシャー情報行列(FIM)と呼ばれるもので、FIMは以下の式で定義されます。 $$ F = \mathbb{E}_{x,y \sim \hat{p}(x)p_w (y|x)} [\nabla _w \log p_w (y|x)\nabla _w \log p_w (y|x)^T] $$ 数式がややこしくなってきましたが、FIMは確率分布の各パラメータ毎の勾配を計算し、その転置行列との積をとっています。また、FIMは確率分布空間上のリーマン距離(計量)であり、 結合分布\(\hat{p}(x)p_w (y|x)\)についてのある特定のパラメータ(重み、特徴量)を含んでいます。 確率分布はベクトルで、それをパラメータベクトルで(偏)微分すると行列となります。この時、行列のi行目は確率分布の全ての値をi番目のパラメータで微分したものとなります。 つまり、FIMの対角成分のみが、同じパラメータで微分したものの二乗が並びます。
これより、FIMにおける対応するエントリ(成分)が小さい値なら、そのタスクはパラメータに強く依拠していないことが分かります。また、FIMはタスクの(コルモゴロフ)複雑性にも関係していると言われています。
以上のことよりFIMをタスクを表す指標としているわけです。
しかし、異なるネットワークでFIMを計算すると比較ができないため、本論文では前述した「probe network」を用います。 また上の数式からも分かるように、全てのパラメータに対する勾配を計算しなくてはならないため、計算量が多すぎるという問題点があります。 これに対応するために、本論文では2つの仮定を置いています。

1.「probe network」内の異なるフィルター間には相関がないと(暗黙的に)仮定→FIMの対角成分についてのみ考える
2.それぞれのフィルターの重みパラメータは基本独立していない→同じフィルターの全ての重みに対し平均化を行う

これによって結果的に得られたものは、「probe network」内のフィルター数と一致した固定長ベクトルであり、 このベクトルを使ってタスク間の距離を計算していくのです。 本論文11ページ目の「Analytic FIM for two-layer model」に簡単な二層モデルでのFIM導出を紹介しているので、 興味のある方は是非参照してみて下さい。


3.TASK2VEC 手順

さてやっと本題に入れるわけですが、まずTASK2VECは大きく次のステップに分けられます

1.事前学習済みモデルによって得られるFIMを計算【2.事前知識参照】
2.FIMの対角成分のみを取り出し、固定長のベクトルを出力

行なっている作業は基本これだけで他のモデルと比較する際に、この出力されたベクトル間の距離を計算します。

ベクトル間の距離計算

このベクトル間距離をユークリッド距離で計量しようとすると、1.ネットワークのパラメータは異なるスケールを持つ、 2.埋め込まれたベクトルのノルムは、タスクの複雑性や計算に使われたサンプル数の影響を受けるといった問題が発生するため、 本論文では距離計算の手法として次の場合分けを行なっています。

◎Symmetric TASK2VEC distance【対称性あり】:
$$ d_{sym}(F_a, F_b) = d_{cos}\left(\frac{F_a}{F_a +F_b}, \frac{F_b}{F_a +F_b}\right). $$ ここで対称性ありの場合について、距離計算の際の頑健性を保つためコサイン距離を導入します。
\(d_{cos}\)はコサイン距離(類似度)、\(F_a\), \(F_b\)は2つのタスク\(a, b\)をベクトル化したもの(計算によって得られたFIMの対角成分)を表しています。 それぞれ\(F_a +F_b\)で割って標準化していることに注意してください。 例えば、iNaturalistにおける種間の分類学上距離(Tax. distance)とコサイン距離について、 以下の図右より、完璧にはマッチしてないですがタスクサイズ\(k\)が大きいほど良い相関(関係)があることが分かります。
自然言語処理
◎Asymmetric TASK2VEC distance【対称性なし】:
$$ d_{asym}(t_a \rightarrow t_b) = d_{sym}(t_a, t_b) - \alpha d_{sym}(t_a, t_0) $$ 次に非対称の場合についてですが、モデル選択の際は上記の転送距離(Transfer distance)が有効です。
一般的にImageNetのように複雑なタスク(データセット)から得られた学習済みモデルは良い性能を持っています。 本論文では、「タスクの複雑性は、"簡単なタスク\(t_0\)"の埋め込み表現によって得られるベクトルの大きさによって計算できる」 という考えをもとに、上記の計算式を導入しています。
この式が言わんとすることは、タスク\(a\)を用いてタスク\(b\)に転移学習させる際に、タスク\(a\)が複雑であればあるほど 良い結果がでるということです。つまり、タスク\(a\)とタスク\(b\)の類似性が高く、かつタスク\(a\)とタスク\(t_0\)の類似性が低いほど この距離は大きくなります。
ここで、\(t_a, t_b\)は2つのタスク、先ほど述べた\(t_0\)は簡単なタスク、\(\alpha\)はハイパーパラメータを表しています。 この\(\alpha\)はメタタスクをもとに選定されます。本論文の実験では、最適な\(\alpha\)がメタタスクの選定に関して 頑健性を持っていることが分かっています。(実験によるとprobe networkとして、ImageNetで事前学習させたResNet-34を使った時の\(\alpha\)は0.15)
【詳しくは本論文"3.1. Symmetric and asymmetric TASK2VEC metrics"参照】


MODEL2VEC【参考】

さて、上記のTASK2VECではタスク間の距離を算出することに成功しています。 しかしここまで読んでくださった読者様の中には、既にお気付きの方もいるでしょうがこのTASK2VEC、完全にモデルの詳細を無視してしまっています。
そこで、モデルが訓練されたタスクの埋め込みができるなら、そのモデルもベクトル化できるのではないか?と考えるわけです。
しかし、一般にそういったモデルの情報はブラックボックス化されてたりして分かりません。 そこで、同じタスクで異なる精度のモデルがあったら、タスクとモデル(アーキテクチャとトレーニングアルゴリズム)間の相互作用をモデル化するために、 2つの相互埋め込みを学習することを目標とすれば良いわけです。
具体的に本論文では、タスク空間に(似たタスク上でも良い精度を出すような)モデルを埋め込むために、メタ学習問題に関する次の公式を提唱しています。
\(k\)個のモデルが与えられた時、MODEL2VECによる埋め込み表現は、
$$ m_i = F_i + b_i $$ で与えられ、ここで\(F_i\)はモデル\(m_i\)をトレーニングするために使ったタスクをベクトル化したもので、\(b_i\)は学習済みの「モデルのバイアス」を表しています。
\(b_i\)は、タスク間距離によって与えられる最適なモデルを予測するための、k交差エントロピー誤差を最適化することによって得られます。 ここでタスク間距離は以下で定義されます。
$$ \mathcal{L} = \mathbb{E}[-\log p(m | d_{asym}(t, m_0), \cdots , d_{asym}(t, m_k))]. $$ トレーニング後、新しいタスクtが与えられた時、\(d_{asym}(t, m_i)\)を最大にするような\(m_i\)が最適なモデルというわけですが。。
あくまで参考程度に考えていただければ結構です。


4.論文の実験結果

使用データセット

まず本論文で使用するデータセットについて、簡単にまとめておきます。【右の数字はタスク数】

iNaturalist:生物を撮影した画像からなるデータセット。それぞれのタスクは種の分類タスクとなっている。【207】
CUB-200:鳥を撮影した画像からなるデータセット。それぞれのタスクは鳥類の分類タスクとなっている。【25】
iMaterialist:ファッション(服飾)画像のデータセット。服の分類に関するタスク(色、素材など)。【228】
DeepFashion:ファッション(服飾)画像のデータセット。iMaterialistと同じ、服の分類に関するタスク。【1000】

4つのデータ合わせて全1460のタスクで実験を行なっています。 これらのタスクで良い学習済みモデルを選択することに成功したTASK2VECですが、早速その実験結果を見ていきましょう。


学習済みモデル

先ほども述べましたが、本論文ではprobe networkとして、ImageNetで事前学習させたResNet-34を、 その後ファインチューニングしたものと、しないものとの2つで実験しています。

実験結果

本論文では4,100の分類器、156の特徴抽出機を使い、そして1,460の埋め込みを実験で行ったそうです(かかった時間は1,300GPU時間)。
再褐しますが、下図がiNaturalist, CUB-200, iMaterialistの3つのデータセットにおける各タスクを、t-SNEによって二次元のベクトルに落とし込み可視化したものです。(左図) 自然言語処理
データセットと相関のあるタスク(例えばiMaterialistだったらパンツの分類タスクなど)は、そのタスク間がうまく分離できており、きちんとグルーピングできています。 しかし右図のように入力ベクトルのみによって埋め込まれたものは、iMaterialistのタスクは1つのクラスタとしてまとまっています。 つまり、データセット内のタスク間を分離できていないということです。 やはりTASK2VECの方がよくタスク間の分離ができていますね。


誤差分布

次にiNaturalistとCUB-200の156の学習済みモデルから特徴量を抽出し、そのタスクの分類誤差を示したものを見ていきましょう。 自然言語処理
このヴァイオリン図において、縦軸はTest Error(テスト誤差)、横軸はそれぞれタスクを示しています。 赤の×がTASK2VECによってモデル選択を行なった場合の分類誤差、 青の△がファインチューニングしてないImageNetで事前学習させたものから抽出した分類誤差を表します。(赤×が低い値の方がいい)
まずこれらのタスクは、左から右へとベクトルのノルム(大きさ)が小さいものから順に並んでいます。 また右に行くに従って分類誤差が大きくなっていることから、TASK2VECによって得られるベクトルの大きさは、タスクの複雑性と正の相関があることが分かります。


サンプルサイズに対する依存性

私たちの興味のあるタスクが比較的少ないサンプル数しかない時、最適な特徴抽出器を見つけ出すことは特に重要になってきます。 次のグラフは、モデル選択においてサンプル数が変化した時、TASK2VECのパフォーマンスがどのように変わっていくかを表したものです。 自然言語処理 グラフはそれぞれ、
オレンジの点線:最も最適なモデルを選択した時
赤の実線:TASK2VECによって選択した特徴抽出器
赤の点線:ImageNetのみで事前学習させた特徴抽出器
青の実線:TASK2VECによって選択した特徴抽出器をファインチューニングしたもの
青の点線:ImageNetのみで事前学習させた特徴抽出器をファインチューニングしたもの
です。これより全てのサンプルサイズに対して、TASK2VECはImageNetのみで事前学習させたものより良い精度を出していることが分かります。
最後に、以下の最適誤差に関する表を見て下さい。 自然言語処理 まずMeta-taskとして、iNaturalistとCUB-200の二つのタスクを合わせた「iNat + CUB」、全てのタスクを混合させた「Mixed」について考えています。 ここで「Chance」は適当なモデルを選択した場合に得られた特徴抽出器で、この表よりChanceのように安価な(何も工夫してない)特徴抽出器よりも、 ImageNetのみで事前学習させた特徴抽出器の方が良い精度であることが分かります。 しかし、そのImageNetのみで事前学習させた特徴抽出器よりも、TASK2VECを用いてタスク間距離を測定し、 モデル選択を行なった方が更に良い最適なモデルが得られることが分かります。

5.まとめ

TASK2VECはタスク、もしくは対応するデータセットを固定長のベクトルとして表現する有用な方法です。
性質として、
1.そのベクトルのノルムは、タスクのテスト誤差やタスクの複雑性と相関がある。
2.埋め込みによるベクトル間のコサイン距離は、タスクの自然距離(例えば種間の分類学上距離、転移学習におけるファインチューニング距離)と相関がある。
などが挙げられます。
総括すると、TASK2VECに基づくモデル選択のアルゴリズムは、学習なしに最適な(もしくは最適に近い)モデルを提唱するため、 自分で一から力尽くで(brute force)最適な学習済みモデルを探す必要がない!ということです。とても画期的な考えですね。 さて本論文にもありましたが、タスク空間上のメタ学習はこれからの人工知能に向けての重要なステップとなるでしょう。
実際、このTASK2VECは完璧にタスクの複雑性や多様性を捉えているわけではないので、実社会で見ることは少ないかと思います。 しかし、このTASK2VECの考え方を基に更なる発展のため、私も勉強していきます。


6.参考文献

TASK2VEC: Task Embedding for Meta-Learning
転移学習とは?ディープラーニングで期待の「転移学習」はどうやる?
データがないのに学習可能? 最先端AI「メタ学習」がスゴい


Twitter・Facebookで定期的に情報発信しています!

最近は今までに増して機械学習を検討する企業が増えています。 しかし、導入検討にあたり、機械学習でなにを改善するのか/なにを解決するのかという、導入目的を決めあぐねているケースも多いと耳にします。

本記事では機械学習はどのような業種で、どんな目的で導入されようとしているのかを紹介し、機械学習の活用例と解決できる課題(導入効果)をお伝えします。

『こんな使い方が自社に役立つな』や『機械学習でこんなことをやりたい』を発見してもらえると嬉しいです。

検討段階のシフト

2018年にIBMがおこなった調査によると、企業の82%はAIの導入を検討しています。
また、AIの運用と最適化を開始している企業は、2016年と比較すると、33%増加しています。導入に向けて成果を上げている企業は概念検証のテストや実験の域を超えて進んでいます。

経営層の目の向く先は、

『機械学習を導入すべきか』
から
『どのようにして機械学習を導入するか』
へと移行しているようです。

機械学習は技術的な進歩がめざましいと紹介されていますが、それに沿うようにして機械学習への期待も膨らんでいます。

機械学習の導入・活用実績

機械学習の導入率はテジタル化が進んでいる業界で高く、そのスピードも今後上がっていくと見込まれます。

例えば金融サービス業界では既に16%の企業が 機械学習システムを運用または最適化し、次いで製造業が追いかけています。

しかし自動車やヘルスケア業界にもこの傾向は見られており、機械学習は今後も大きな期待をされていることがわかります。

機械学習に期待すること

情報技術 (IT) と情報セキュリティー (IS)が、最も優先すべき業務として挙げられています。

例えば 機械学習を利用したヘルプデスク仮想アシスタント、 プロセス自動化、脅威検知アルゴリズムの活用があります。
その他に、イノベーション、顧客サービス、リスクの領域があります。
イノベーション領域には戦略的な機会が不可欠ですし、顧客サービスの領域は多くの企業が仮想アシスタント機能を試験的に導入しています。 そしてリスクの領域では不正の防止と検知が重要です。

幅広い領域で機械学習は活用できますが、効果的な導入にするためにはどの領域で/何を達成するのかという設定が必須です。

コスト削減より、顧客満足度を重視

企業として売上増加はこの 2 年間で一層重視されるようになりました。

調査によると、経営層は顧客満足度と顧客維持率をAI投資の主な目標に掲げており、これはコストに対する考慮を大きく上回りました。
もちろんこれはコストが重要ではないという意味ではあり ません。

多くの 機械学習プロジェクトの中を見てみると、目的のひとつにはやはりコスト削減の要素が含まれているので、『コスト削減は当然で、次の視点として顧客満足度を重視している』とも言えます。
また、運用コストの削減も 3 番目に重要なものとされています。しかし、このランキングでの順位をを押し上げたのは最高財務責任者 (CFO) と財務部門かもしれません。

加えて、多くの企業は製品やサービス よりも顧客体験を重視しています。
何を売るかよりも、その製品やサービスを通じてどんな体験ができるか、ということです。体験は購入後だけではなく、購入前の検討時もその対象です。 

顧客体験の向上は、顧客に対面するその企業の担当者次第であることが少なくありませんが、
そのような場面で AIを的確に利用した仮想アシスタントを使用すれば、既存の専門知識を拡大して、顧客の質問により速く、正確に、しかも経済的に答えられるようになります。

機械学習活用例

ここまで、機械学習が活用されている業種と目的をお伝えしました。
次に業種ごとにお客様満足に繋がる機械学習の活用例をご紹介します。

製造業

『製造ラインでの不良品検知』


課題
食品製造ラインで不良品は手作業で弾いている。

  • 個人ごとに判断がばらつく場合がある
  • 同じ体勢で長時間いるため作業者への負荷が大きい


導入後
製造ラインにカメラを設置し、良品/不良品を自動で仕分けする。

  • 作業者は別の業務にあたることができ、より利益追求や改善が進んだ。
  • 生産性の向上も実現し、労働時間を短縮できた。


飲食業

『顧客の消費予測で廃棄、機会損失の減少』


課題
いつ、どれくらい売れるかを肌で感じ、仕入れをしている。

  • 店長のスキルで売上、利益が大きく異なる。
  • 仕入れを絞ると機会損失が生じ、仕入れを増やすと廃棄が多くなる。


導入後
過去の売上から未来の売上を予測する。

  • 廃棄や機会損失の減少
  • 常に欲しい物が適切量ある店舗で、顧客満足度も向上


小売業

『チャットボットでユーザー好みの商品をオススメ』


課題
ECサイトでの売上が伸び悩んでいる。

  • 試着ができないため、ユーザーは意思決定できない。
  • 電話での個別問い合わせはハードルが高く、利用されない。


導入後
ユーザーが質問に答えると似合う商品が分かるチャットボットを利用。

  • 廃棄や機会損失の減少
  • 常に欲しい物が適切量ある店舗で、顧客満足度の向上


『SNSから商品評価分析』


課題
商品のリアルな評価が不透明で新商品開発で悩んでいる。

  • どのようなシーンで、誰が商品が使われているか知りたい。
  • 口コミサイトや直接の評価は極端なものが多い。


導入後
SNSから自社商品が写っている写真を分析する。

  • 利用されている季節や雰囲気が分かり、より顧客に寄り添った商品開発が出来る。


おわりに

機械学習は幅広い活用方法があり、お客様ごとの活用方法の提案が必要です。
運用までこのような流れで進めることが多いです。
Process


アクセルユニバースではみなさまの課題やお困り事を一緒に解決していきます。
下記にご興味がありましたら、問い合わせ口からご連絡ください。

  • 活用事例についてもっと詳しく知りたい
  • 機械学習・深層学習は他になにが出来るのか興味がある


アクセルユニバースのご紹介

私達はビジョンに『社会生活を豊かにさせるサービスを提供する。』ことを掲げ、このビジョンを通して世界を笑顔にしようと機械学習・深層学習を提案しています。
例えば、現在人がおこなっている作業をシステムが代わることで、人はより生産性の高い業務に携わることができます。


acceluniverse


Twitter・Facebookで定期的に情報発信しています!

AIの進歩が目覚ましい近年、文章の文脈まで読み取ってくれるAIがあれば嬉しいですよね。
ビジネスの場面でも、クレームとお褒めの言葉を分類したり、議事録のアジェンダと中身が合っているかなど、文脈を判断できればAIの使える場はぐんと広がります。

文脈を機械が読み取るのは難しく、研究者も今まで苦労してきました。
しかし近年、ELMoとBERTという2つのAIが現れたことで、今機械学習は目覚ましい進歩を遂げています。
多くの解説記事は専門家向けに書いてあることが多く、要点だけをまとめたり、仕組みをわかりやすく説明した記事は多くありません。
今回の記事は、そういった「よくわからないけどもっと知りたい」「本質をつかみたい」という要望に答えるべく、最新のAIをできるだけわかりやすく説明することを目的としています。


目次

  • 今までのAI
  • ELMoとBERT ~新星の誕生~
  • 弱点と新たな新星


今までのAI

今までのAIは、単語一つ一つに対して数字を当てはめる方式をとってきました。
有名な例がWord2Vecの
「王」+「男」ー「女」=「女王」
という式です。上手に学習ができれば、このように単語ごとに数字を当てはめても他の単語との相関関係を表す事ができました。

しかし、大きな問題があります。
例えば、次の文を御覧ください。

「昨日から雨が降っている」

この文は、砂漠地域についての文章と熱帯地域の雨季についての文章では意味合いが違ってきます。
他にも、

「コストは2倍だが、利益は3倍だ。」

「利益は3倍だが、コストは2倍だ。」

の2つでは重点が違いますし、順番が違うだけで文章全体の意味合いが変わってきてしまいます。
つまり、単語ごとの数値だけではなく、文脈を考慮した数値を使わないとAIは文章を正確に判断できないのです。

ELMoとBERT ~新星の誕生~

そこで2018年に生まれたのがELMo、そしてその後継者のBERTです。
ELMoは文の単語を1語ずつ読み取り、単語の情報を徐々に蓄積させていく手法を使います。
以下の図を御覧ください。

image1.png

緑の箱はLSTMで、前の単語の情報を引き継いで新しい単語の情報を学習させています。(LSTMについてはこちらを参照
つまり「利益は3倍」というフレーズが、前に「コストは2倍だが」と書いてあるという情報をふまえた上でAIに学習されることになります。
当然、後ろ側が前を参照できるだけでは、前の単語にしっかりと文脈を反映させることはできません。そこで文章の単語を逆向きにして同じような学習をさせます。
image2.png シンプルなように見えますが、ELMoはこの手法を使うことで様々な記録を塗り替え、AIの進歩に大きく貢献しました。

その僅か数カ月後、2018年10月に今度はGoogleがELMoを改良したBERTを発表し、時代はBERTのものになりつつあります。
BERTが改良した点は、主な計算にLSTM(上図で緑の箱)の代わりにTransformer(下図でオレンジの箱)を採用したことです。

image3.png

Transformerとは強そう名前ですが、論文"All you need is Attention"において注目を浴びたAIの学習機で、Attentionと呼ばれるその名の通り「注意度」を考慮に入れた非常に強力なAIのモデルとされています。(Attention モデルについてはこちらを参照
LSTMより強力な部品を使っている分、BERTのほうがELMoよりも性能が高いというわけです。

BERTはコードが公開されているだけでなく、日本語を含めた104ヶ国語に対応しており、まさにGoogleの力を存分に発揮したAIとなっています。

文脈を読み取るとどのような課題に対応できるのでしょうか。
実際にBERTは

  • MNLI:含意関係の分類
  • QQP:質問内容が同じであるかを当てる
  • QNLI:質問と文が与えられ、文が質問の答えになるかを当てる
  • SST-2:映画のレビューに対する感情分析
  • CoLA:文の文法性判断
  • STS-B:2文の類似度を5段階で評価する
  • MRPC:ニュースに含まれる2文の意味が等しいかを当てる
  • RTE:小規模な含意関係の分類


で最高スコアを叩き出しています。


弱点と注意点

ここまで解説したように、BERTは文章の文脈を考慮に入れて文章を分類・生成できる強力なAIで、今後の応用が期待されています。
しかし弱点があるわけではなく、正しく理解しないとお金と時間の無駄になってしまいます。
今回の記事では要点のみを説明したので、細かい部分や数学は省略してあります。
また、BERTは文章をインプットし、文章を出力するAIです。なので実際の個別の課題を解く際はBERTの出力を更に分類したりするモデルが必要になってきます。
しかし言語全体の文脈感を反映させるにあたってやはり強力なAIと言えるでしょう。

また、BERTには弱点があります。
実際の学習では、文章の単語をランダムに隠し、そこを学習させることで精度を向上さています。
しかし実際の文章では文中の単語が隠されていることはなく、また複数の単語が隠されていた場合、それらの間の関係性を学習することができません。

例えば、
[単語]は2倍だが、[単語]は3倍だ。

というふうに隠されていた場合、文が正解として認識される単語の組み合わせは多数あります。なので本来の「コスト」「利益」という単語を学ぶよりも精度が下がってしまいます。
この弱点を克服したのが、今年(2019年)6月に発表されたXLNetなのですが、それはまた次回のブログ記事でご紹介致します。

以上、文脈を読み取ることができる最新のAIについて解説してきました。細かい部分は省略していますが、本質だけを突き詰めると意外とシンプルだという事がわかります。
文脈を読み取ることができれば、社会の様々な場面でAIがますます活躍することになるでしょう。
そのために複雑な数学を理解する必要はありませんが、AIの本質をしっかり把握しておくことで、変化の波に遅れることなく、AI活用の場を見出す事ができるのです。


アクセルユニバースの紹介

私達はビジョンに『社会生活を豊かにさせるサービスを提供する。』ことを掲げ、このビジョンを通して世界を笑顔にしようと機械学習・深層学習を提案しています。
例えば、現在人がおこなっている作業をシステムが代わることで、人はより生産性の高い業務に携わることができます。


当社ではみなさまの課題やお困り事を一緒に解決していきます。
下記にご興味がありましたら、問い合わせ口からご連絡ください。

  • 問い合わせ業務を自動化したい
  • 入力された文章を振り分けたい
  • 機械学習・深層学習は他になにが出来るのか興味ある


Twitter・Facebookで定期的に情報発信しています!

今回はデータを分析するという点で共通する経済学やデータサイエンスについて 概要を説明し、
経済学において機械学習を使うことの難しさについて説明します。
難しさと言っても、『活用できない』と否定をするわけではありません。
あくまでも活用していくことを前提に、気をつけたい点を紹介します。


目次

  • 経済学とデータサイエンスについて
  • なぜ経済学と機械学習が議論されるのか
  • 経済学で機械学習を利用する際の注意点
  • まとめ


経済学とデータサイエンスについて

そもそも経済学は、人がどんなものを買ったり、いくら貯金をするのかといった人の意思決定について仮説を立てて考えていく学問分野です。
分析する対象が人から、人が集まった国になれば、ニュースなどで見るGDPや為替といったテーマを扱います。
このように経済学が扱うテーマは幅広く、企業の経営課題や医療など多岐に渡ります。


近年はコンピューターが進化し、以前よりも多くのデータを扱えるようになったため、経済学的な仮説のモデルを実証分析するために統計的なアプローチからパラメータの推定、検証を行う計量経済学という分野が発展していきました。
このような流れから、経済学の中にデータドリブンな考えが入ってくることで、データから未来の行動を連想することが必要とされています。

Marketing


ここで機械学習を使ったデータサイエンスが想起されます。
集めたデータに対して、機械学習という統計的な手法を使い、未来の予測や分類を行います。
扱うテーマは広く、例えば、企業が持っているデータから課題を解決したり、医療データを使ったデータ分析も行われています。

若干の違いはあるものの経済学とデータサイエンスは、扱うテーマが近しく、経済学の分野でも機械学習を取り入れることが議論されています。


なぜ経済学と機械学習が議論されるのか

経済学は前述のように、人が関わるテーマを幅広く扱います。


機械学習では、今まで手に入らなかったビッグデータのような大量のデータを分析に使えるようになり、経済学でもそれまで使っていなかったデータで実証分析しようという動きがあります。
機械学習での予測や分類が、マーケティングや株価トレードなど経済学の分野の実用に結びつきやすかったためです。
そのため経済学的な仮説をビッグデータで実証分析する際に、計量経済学ではなく機械学習を使うアプローチが議論されました。
実際に『経済セミナー』(日本評論社、2019)でも「機械学習は経済学を変えるのか?」という特集が組まれています。


経済学で機械学習を利用する際の問題点

しかし、こうしたアプローチには問題点も存在します。


経済学は前述のように仮説ベース、モデルベースで考えることが多く、実証分析の前にあらかじめ説明変数等を理論から考えることが主流です。
しかし、機械学習は特徴量(説明変数)を自由に決め、精度の高さを追求するアプローチが主なものになっています。


両者の考え方がかなり異なっており、機械学習で発見した結果を経済理論で解釈する時点で、機械学習特有の、新たな発見は失われてしまう可能性があります。
また経済学の多くの目的が、予測ではなく「なぜそうなるのか」といった因果推論をおこなってきたため、結果の解釈を説明するのが苦手な機械学習とは、もともと相性が悪い点も無視できません。

Marketing

まとめ

以上のように、仮説ベースの経済学において機械学習を使う際は、両者の考え方の違いから機械学習のもつ利点を無くしてしまったり、経済学的に解釈できないといった問題が考えられます。
そのため経済学の分析で機械学習を分析につかう際は、こうした側面があることをしっかり認識したほうが良いでしょう。
※今回は広く経済学と機械学習の考え方を説明し、応用の難しさを説明しましたが、その上で機械学習を経済学分野で応用する例は近年増加しています。


参考文献

与田高典「経済分析ツールとしての機械学習」『経済セミナー』、
2019年2020年12月号1月号、23〜27ページ
今泉允聡「機械学習はデータを解釈できるのか?」『経済セミナー』、
2019年2020年12月号1月号、34〜39ページ


アクセルユニバースのご紹介

私達はビジョンに『社会生活を豊かにさせるサービスを提供する。』ことを掲げ、このビジョンを通して世界を笑顔にしようと機械学習・深層学習を提案しています。
例えば、現在人がおこなっている作業をシステムが代わることで、人はより生産性の高い業務に携わることができます。


当社ではみなさまの課題やお困り事を一緒に解決していきます。
下記にご興味がありましたら、問い合わせ口からご連絡ください。

  • 大量にデータはあるが活用方法に困っている
  • 機械学習・深層学習は他になにが出来るのか興味ある


Twitter・Facebookで定期的に情報発信しています!

〜普及に向けた課題と解決策〜に続き

 私が前回作成した記事である「海洋エネルギー × 機械学習 〜普及に向けた課題と解決策〜」では、海洋エネルギー発電の長所と課題とその解決策について触れた。今回はそこで取り上げた、

課題①「電力需要量とのバランスが取りにくい」、課題③「無駄な待機運転の時間がある」への解決策

~発電量・電力需要量予測~ ~機械学習を用いた制御~

を実装してみる。

 繰り返しにはなるが、この「発電量・電力需要量予測」と「機械学習を用いた制御」とは、まずカレンダー条件(時間帯、曜日など)と気温や日射強度などの気象条件を説明変数として電力需要量を予測し、電力需要量の送電にかかる時間分先の予測値と同量を発電するように発電装置を制御するという、極めて単純な制御である。前提として、電力は常に需要量と供給量(発電量)が同量でなければ、停電を起こしてしまうのであるが、この制御を行えば、需要と供給のバランスを常に保ちながら発電することができる。また発電装置の無駄な待機時間も削減され、設備稼働率も向上する。このようにして、課題①「電力需要量とのバランスが取りにくい」、課題③「無駄な待機運転の時間がある」を解決するのである。今回は発電方法を波力発電としてこれを実装する。


目次

  1. 今回の実装の設定
  2. 機械学習による電力需要量の予測
  3. 並進動揺型の波力発電装置の運動制御
  4. 考察
  5. 参考文献


1. 今回の実装の設定

1-1. どんな波力発電装置で実装するか

 まず波力発電装置の種類は表1、図1のように分類できる。

表1 波力発電装置の種類

スクリーンショット 2019-12-26 12.44.18.png スクリーンショット 2019-12-26 14.54.18.png

 図1波力発電装置の種類


 今回の実装では、垂直(上下)にのみ変位する並進動揺型の波力発電装置を考える。並進運動型の波力発電装置の特徴は、

  • 波に対する指向性がなく、他の発電装置に対して波向きの影響の点から優位である
  • 構造がシンプルで発電機構(PTO: power take off)も含め大部分が水中に没しているので、浮体本体の構造安全性や信頼性の点で有利である
  • 波浪荷重、発電荷重を下端で支えているため繰り返しの係留力が作用することになり、下部の構造強度に配慮する必要性がある
  • 発電装置が水面より下側にあることから、上部からの浸水に対しては十分注意が必要

 また、現在最も実用化に近いものと見られる波力発電装置は、米国のOcean Power Technologies社が開発した並進動揺型の波力発電装置「PowerBuoy」(図2)である。 スクリーンショット 2019-12-26 14.54.47.png

図2Ocean Power Technologies社の「PowerBuoy」


1-2. 実装の設定

 今回の設定は、1機の上下揺のみする並進動揺型の波力発電装置から、ある海沿いの一軒家に直接電力を供給するという状況を考える。波力発電装置から一軒家への送電時間は10分かかるとする。つまり上記の制御をこの波力発電装置に行うには、現在(時刻\(t\))の発電量\(P(t)\)が10分後(\(\tau=10~[分]\))の電力需要量の予測値\(P_{ML}(t+\tau)\)と等しくなる必要がある。


2. 機械学習による電力需要量の予測

 ある一軒家の電力需要量(電力使用量)を予測する時、本来ならば上記に示したようにカレンダー条件と気象条件を説明変数とするべきだが、カレンダー条件と気象条件、電力消費量のデータセットを手に入れることができなかったので、今回は特徴量を表3のようにしたデータセット(表4)を用いる。これは2016年1月11日17時00分から2016年5月11日16時50分までのデータセットである。

表3 データセットの特徴量

スクリーンショット 2019-12-26 16.11.02.png


表4 データセットの一部

スクリーンショット 2019-12-26 15.03.37.png


 初めに示しておくが、電力需要量は暑い夏や寒い冬など季節によって変動する。であるから正確に予測するためには少なくとも1年以上のデータ数が必要となるが今回はデータ数が1年に満たない。なので当然予測精度は悪くなると考えられるが、今回は実装手順を紹介したいので、精度については目を瞑る。
 予測モデルは時系列データに強いと言われているLSTMを用いた。すると予測結果は図3のようになる。破線はデータ値で、赤線が予測値である。但し値は0から1になるように正規化されているため、正規化された赤線の値を元に戻した値が\(P_{ML}(t+\tau)\)である。図3を見て分かるように電力需要量が多い時の予測値は実際の値とかなりずれているが、それは想定内で、それ以外の時は良く予測されている。この予測値を波力発電装置の制御に用いる。

スクリーンショット 2019-12-26 13.41.48.png

図3 予測結果


3. 並進動揺型の波力発電装置の制御

 まず、波浪中を自由に動揺する浮体(水面に浮く物体の総称)の問題は船舶流体力学の知識から、以下の二つの問題に分別することができる。

表5 波浪中を自由に動揺する浮体の問題の分類

スクリーンショット 2019-12-26 14.49.14.png


 ディフラクション問題において浮体に働く力には以下のようなものがある。但し、重力と浮力は釣り合っているとして除外する。

表6 ディフラクション問題において浮体に働く力

スクリーンショット 2019-12-26 14.49.41.png


 ラディエイション問題において浮体に働く力には以下のようなものがある。

表7 ラディエイション問題において浮体に働く力

スクリーンショット 2019-12-26 14.50.02.png


 当然ではあるが上下揺のみする並進動揺型の波力発電装置も浮体の一つであるから、ここでは浮体と呼ぶことにする。
 まず浮体の動揺を制御していない場合、波浪中の浮体の運動方程式は、浮体の上下方向の運動変位を\(z\)、上記で示したラディエイション力、復原力、波浪強制力の上下方向成分をそれぞれ\(F_{3}^{R}(\ddot{z},\dot{z})\)、\(F_{3}^{S}(\ddot{z},\dot{z})\)、\(F_{3}^{W}(\ddot{z},\dot{z})\)とすると、 \[ m\ddot{z}(t)=F_{3}^{R}(\ddot{z},\dot{z})+F_{3}^{S}(z)+F_{3}^{W}(t)\tag{1} \] と表せる。ここで\(F_{3}^{R}(\ddot{z},\dot{z})\)、\(F_{3}^{S}(z)\)、\(F_{3}^{W}(t)\)は数値計算または計測されていて既知であるとする。
 次に浮体の動揺を制御する場合、浮体の運動方程式は式に制御力\(G_{3}(t)\)を加えて、 \[ m\ddot{z}(t)=F_{3}^{R}(\ddot{z},\dot{z})+F_{3}^{S}(z)+F_{3}^{W}(t)+G_{3}(t)\tag{2} \] と表せる。この制御力\(G_{3}(t)\)を調節することで、望んでいる量を発電するように浮体を動揺させることができる。
 発電量\(P(t)~[W]\)は、発電機構の巻線抵抗\(R_{s}~[\Omega]\)、推力係数\(K_{t}~[N/A]\)を用いると、機械入力\(-G_{3}(t)\dot{z}(t)\)から発電ロス\(\cfrac{ R_{s} }{ K_{t}^{2} }G_{3}^{2}(t)\)の差として表せるので、 \[ P(t)=-G_{3}(t)\dot{z}(t)-\cfrac{ R_{s} }{ K_{t}^{2} }G_{3}^{2}(t)\tag{3} \] となる。
 この発電量\(P(t)\)を、機械学習(machine learning)で予測した時刻\(t+\tau\)の電力需要量\(P_{ML}(t+\tau)\)となるように制御したいので、 \[ P(t)=P_{ML}(t+\tau)\tag{4} \] とする。すると式\((3)\)は\(G_{3}(t)\)の二次方程式 \[ \cfrac{ R_{s} }{ K_{t}^{2} }G_{3}^{2}(t)+\dot{z}(t)G_{3}(t)+P_{ML}(t+\tau)=0\tag{5} \] となる。二次方程式の解の公式より、制御力\(G_{3}(t)\)は \[ G_{3}(t)=G_{3}(\dot{z})=\frac{ -\dot{z}(t)\pm\sqrt{ \dot{z}^2(t)-4\cfrac{ R_{s} }{ K_{t}^{2} }P_{ML}(t+\tau) } }{ 2\cfrac{ R_{s} }{ K_{t}^{2} }}\tag{6} \] と求まり、浮体の上下揺の速度\(\dot{z}\)の関数となる。この制御力\(G_{3}(\dot{z})\)を式\((2)\)に代入することで、浮体の動揺は\(P_{ML}(t+\tau)\)だけ発電するように制御される。


4. 考察

 上記で示したように制御することで、確かに需要と供給のバランスを常に保ちながら発電することができる。ただ、今回は実装の手順を示すことを目的として電力需要量の予測の精度については気にしなかったが、本来はここが極めて重要である。2章でも示したが、今回使用したデータは1年に満たないデータ数である。これでは電力需要量の朝、昼、夜の変化は捉えることができたとしても、季節の変化は捉えることができない。これが予測精度を落としている明らかな理由である。
 また、今回は10分間で送電が完了するという状況を考えたためそう遠くない未来の電力需要量を予測するだけであったが、実際波力発電装置が陸地からかなり遠い沖合に設置された場合、10分で送電できるとは考えられない。つまりもっと先の未来の電力需要量を予測できなければならない。実際に今回のデータセットで1時間先の電力需要量を予測してみたところ、かなり酷い精度になり、これでは波力発電装置の制御には使えないという結果となった。しかしこの原因もデータ数が足りないことであることは分かっている。季節の影響を捉えていないモデルで、未来を上手く予測できないのは当然である。
 上記二つの問題はデータ数を増やすことで改善できるので、長い期間の電力需要量のデータを入手次第、改めてやり直そうと考えている。
 問題はまだある。それは発電量が多い時、精度が悪くなることである。これは今のところ原因が分かっていないので、引き続き研究していく。
 また、今回は求めている発電量を発電できるような制御を行ったが、安全性については全く考慮していない。たとえ電力需要量と同量発電できたとしても、事故を起こしてしまっては元も子もない。なので、今回の制御に安全性の配慮を加えた研究も今後行っていく。


5.参考文献


Twitter・Facebookで定期的に情報発信しています!

本記事では以下のような使い方ができるチャットボットを紹介します。
スクリーンショット 2019-12-24 16.53.21.png


2019年に施行された働き方改革関連法により、残業時間の削減や多様な働き方が認められました。
今後も多くの人にとって働きやすい環境に変化し、さらに多様な働き方になることが予想されます。
そのため、現在は『業務時間を減少させつつ、利益は向上させる』生産性向上が求められています。
生産性向上のために業務を効率化し、無駄な業務時間をなくし、より利益を創出する活動に業務時間を充てることが重要です。


機械学習・深層学習はこのような作業を得意とします。

スクリーンショット 2019-12-24 16.34.51.png


チャットボットでできる業務効率化

今回は特に業務効率化に役に立つ『チャットボットでお客様問い合わせ対応事例』をご紹介します。
チャットボットは同じ作業を早くくり返すことを得意としていて、質問内容とその回答を事前に学習させておくことで、まるで人と会話しているかのように、ユーザーが入力した文言に対して適切な回答を返します。
スクリーンショット 2019-12-24 16.38.07.png


例えば、こんなシーンはありませんか?
ーーーーーーーー
お客様から電話やメールで問い合わせが多く、対応が追いついていない。
膨大な問い合わせ対応業務により本来おこなうべきのコアな業務にも影響が出ている。業務時間が増えるだけではなく、回答が滞ることによりお客様にも迷惑がかかり、機会損失にもなりかねない状態。
ーーーーーーーー


特定の製品についての金額の質問など、問い合わせの多くを似た内容が占めていませんか?そうであれば、機械学習・深層学習の得意な業務です。


お客様問い合わせ業務をチャットボットで実現!

お客様への回答を自動返答することができれば、問い合わせ担当者の業務負担は大きく軽減します。それだけではなく、お客様をお待たせすることなく、必要なタイミングで情報を伝えることができます。
そうすることで、担当者はよりコアな業務に集中できるようになり、売上向上や社内環境改善などのさらなる利益にもつながるでしょう。


また、チャットボットへの問い合わせは、資料請求やメールでの問い合わせのように、個人情報を入力する必要はありません。
そのため、ユーザーは気軽に質問ができ、さらには営業時間外でもチャットボットが質問に答えてくれます。
このようなユーザーにとって快適な体験で購入前にも顧客の満足度が高まるだけではなく、顧客との接点が増えることで信頼性の向上や商品・サービスの認知度アップにもつながります。


さらに、多くのチャットボットはコミュニケーション内容をデータとして残すことができますので、幅広いユーザーのニーズを把握することも可能です。
このようなユーザーのニーズからチャットボットの回答やサイトの情報を改善したり、商品・サービスの改善につなげたりすることも可能になるのです。

その他活用例

問い合わせ対応だけではなく、このような使い方もできます。

スクリーンショット 2019-12-24 16.45.06.png

社内ヘルプデスク

問い合わせがあるのは、お客様からだけではありません。社内から情報システム部や総務部への問い合わせは毎日発生しています。
日々の問い合わせは軽微で同じようなものが多く、チャットボットで問い合わせから回答までを完結させてしまうことができます。
問い合わせをする側も気軽に利用でき、確認不足によるミスを減らすことも出来るでしょう。


「なぜ?」原因の特定

上記2つの事例からチャットボットは、相手と会話するようにシステムとやり取りできるサービスです。ここの『会話』に着目し、原因の特定に活用することもできます。
例えば、ミスが発生した際の原因特定。
報告書を提出し、上司との会話で原因を発見し、今後の対策を決めていきます。
この会話をチャットボットでおこなうことで、スピード感のある原因の特定がおこなえます。また、(本来あってはならないのですが、)当事者は上司ではなく、システムと会話するわけですから、より素直な回答をすることができ、正確な特定がおこなえるでしょう。


ユーザーへのレコメンド

ユーザーが好みや生活習慣を入力することで、ユーザーに適切な商品をおすすめすることができます。
例えば、化粧品は人の好みが大きく分かれるだけではなく、流行りの移り変わりも大きく、化粧品購入の際は、ユーザーは悩み、今までと同じものを購入することで妥協することも少なくはありません。
チャットボットを活用すると簡単に、どこでも、自分にピッタリの化粧品を見つけることができます。


おわりに

チャットボットは業務効率化を進めることはもちろん、幅広い活用方法があり、お客様ごとにぴったりな活用方法をご提案いたします。


当社ではみなさまの課題やお困り事を一緒に解決していきます。
下記にご興味がありましたら、問い合わせ口からご連絡ください。

  • チャットボットについてもっと詳しく知りたい
  • 困っていることを相談したい
  • 機械学習・深層学習は他になにが出来るのか興味ある


アクセルユニバースのご紹介

私達はビジョンに『社会生活を豊かにさせるサービスを提供する。』ことを掲げ、このビジョンを通して世界を笑顔にしようと機械学習・深層学習を提案しています。
例えば、現在人がおこなっている作業をシステムが代わることで、人はより生産性の高い業務に携わることができます。


Twitter・Facebookで定期的に情報発信しています!

アクセルユニバースの栗木です。
今回実務の練習として、同じインターン生の入江君と共に模擬案件に取り組みました。
模擬案件とは、機械学習を用いることで実生活におけるどのような問題を解決できるかを考え、課題設定からデータの準備、前処理、学習、検証までの一連の作業を経験するための問題です。
今回の取り組みの中で僕達が取り組んた内容や理論を各ステップ毎に紹介していきたいと思います。記事は2部構成として、本記事では前半部分を記します。


Step. 1 課題設定

今回は無人レジの実現に挑戦します。
僕は並ぶことが苦手なので、どうにかレジの混雑を解消できないか考えました。
レジ処理は「いらっしゃいませー」「レジに商品を登録」「支払い」「ありがとうございましたー」の流れですよね。ここの「レジに商品を登録」をどうにかして効率化できれば、レジの混雑を解消でき、普及すれば、僕みたいな並びたくない族もたくさん買い物に行くはずです。


今回の目標は画像検出を用いてレジを打つことなくカメラに映すだけで合計金額を計算することとします。
画像を利用する価値を高めるためにタグが付けられない商品(食べ物)で、誰もが大好きなドーナツを対象とします。特にまだ無人化が進んでいないドーナツ屋さんの商品をトレーに載せた状態を想定しました。検出が成功すれば金額だけでなくカロリーなど+αの情報も表示が可能になりますね。


まずはじめにPart1ではひとつひとつのドーナツが何であるかを判定しました。先に結果だけお伝えすると、現時点で正答率が99%を超えていて今後の検討も楽しみです。


実際にシステムを作っていきます。まずは学習データを用意していきましょう。

Step. 2 学習データの準備

早速7種類のドーナツを購入し撮影を行いました。
角度や裏表を変えつつそれぞれ100枚の写真を撮りました。以下に写真の一例を示しておきます。
ちなみに撮影後においしく頂きました。^^

Donuts また、それぞれのドーナツの名前(ラベル)は以下とします。
8枚目の写真は物体検出する際にアノテーションされたデータが必要となるのでそのためのものです。アノテーションに関する詳細は後半の記事で説明したいと思います。


1.エンゼルフレンチ
2.ダブルチョコレート
3.エンゼルクリーム
4.ポン・デ・リング
5.オールドファッションハニー
6.ストロベリーカスタードフレンチ
7.チョコファッション
8.複数ドーナツ(物体検出用)

Step. 3 画像データの読み込み

学習のための画像データが準備出来たので、学習に備えてデータの読み込みとサイズを統一するためリサイズを行います。
今回はGoogle Colabratoryを使用するため、Google Driveに先程の画像をアップロードし以下のようにマウントすることでGoogle Colabratoryからデータにアクセス出来るようにします。
Google DriveにはDonuts Filesディレクトリを作成し、そこに先程の画像のうち複数ドーナツ以外の7種類の画像をディレクトリ毎にまとめてあります。(複数ドーナツの画像は後半で扱います)


from google.colab import drive  
drive.mount('/content/drive')

次にDonuts Files内の画像をディレクトリごとに読み込みリサイズを行います。

#必要なライブラリのimport
import os
import numpy as np
import glob
import cv2
from keras.utils import np_utils

IMAGE_SIZE = 100 #リサイズ後のサイズ指定

# Donuts Filesディレクトリから画像の読み込み及びリサイズ
def get_data_and_label(path):
  X = []
  Y = []
  label = {}
  i = 0
  for dir_name in os.listdir(path):
      label[dir_name] = i
      for file_path in glob.glob(path+'/'+dir_name+'/'+'*'):
        img = cv2.imread(file_path)
        img = cv2.resize(img,(IMAGE_SIZE,IMAGE_SIZE)) #100*100にリサイズ
        X.append(img)
        Y.append(i)
      i += 1
  X = np.array(X)
  Y = np.array(Y)
  X = X.astype('float32')
  X = X / 255.0 #RGBの値を正規化
  Y = np_utils.to_categorical(Y, len(label)) #One-hotベクトルの作成
  return X, Y, label

X, Y, label = get_data_and_label('drive/My Drive/Donuts Files')

これでデータの読み込みとリサイズは完了です。最後に精度の評価用にデータの分割を行います。

from sklearn.model_selection import train_test_split

# 学習データのうち20%を検証データにする
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.20)

データの準備が出来たので、実際にモデルの学習と精度の検証を行いましょう。
最終目標は物体検出を行うことですが、前半である本記事ではまず1枚の画像に対して1つのラベルの予測を行う画像認識を実装しどの程度分類出来るか確認します。

Step. 4 モデル構築&学習

今回の問題は画像認識なので、モデルはCNN(畳み込みニューラルネットワーク)を使用します。
CNNの詳細については多くの方が記事にされているのでそちらを参考にして下さい。
簡単に説明すると、CNNは畳み込み層、プーリング層、全結合層から成り立っており、まず畳み込み層では複数のフィルタを使用して画像を畳み込むことでエッジやパターンなどの特徴を抽出します。
次にプーリング層でデータサイズを減らしつつ平行移動などの処理に対するロバスト性を獲得し、最後に通常のディープラーニングと同様の全結合層でこれまでに抽出した特徴とラベルの関係性を学習します。
CNNは2012年の画像認識コンペ(ILSVRC)で圧倒的な成績を残して注目されて以来、急速に発展を続けているので是非色々と調べてみて下さい。
それではKerasを用いてモデル構築を行いましょう。KerasはバックエンドでTensorFlowを利用するディープラーニングライブラリラッパーです。

#必要なライブラリのimport
import tensorflow as tf
import keras
from keras.models import Sequential
from keras.layers import Dense, Activation, Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.pooling import MaxPool2D
from keras.optimizers import RMSprop  #最適化手法としてRMSpropを使用

# モデルの定義
model = Sequential()

model.add(Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(IMAGE_SIZE, IMAGE_SIZE, 3)))
model.add(MaxPool2D((2, 2), padding='same'))
model.add(Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(MaxPool2D((2, 2), padding='same'))
model.add(Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(MaxPool2D((2, 2), padding='same'))
model.add(Flatten())
model.add(Dense(64, activation='relu'))
model.add(Dense(len(label), activation='softmax', name='predicton'))

Kerasではモデルの構造をmodel.summary()から以下のように簡単に確認できるので非常に便利ですね。

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 100, 100, 32)      896       
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 50, 50, 32)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 50, 50, 64)        18496     
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 25, 25, 64)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 25, 25, 128)       73856     
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 13, 13, 128)       0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 21632)             0         
_________________________________________________________________
dense_1 (Dense)              (None, 64)                1384512   
_________________________________________________________________
predicton (Dense)            (None, 7)                 455       
=================================================================
Total params: 1,478,215
Trainable params: 1,478,215
Non-trainable params: 0
_________________________________________________________________

それでは最後にモデルの学習と評価を行います。

# モデルのコンパイル
model.compile(loss='categorical_crossentropy',
              optimizer=RMSprop(),
              metrics=['accuracy'])

#パラメータの指定
batch_size = 64
epochs = 20

# 学習
history = model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size)

# 検証データによるモデルの評価
print(model.evaluate(X_test, y_test))

最終的なlossと正解率は以下のようになりました。

loss = 0.02750563397655182
accuracy = 0.9927007299270073

正答率が99%を超えており非常に高いスコアとなりました。
今回はかなり問題設定が単純だったことと、本来は同じ種類であっても多くのドーナツを用意すべきところを1つのドーナツから学習データを作成したことがこのスコアにつながったと考えられます。

終わりに

ドーナツ検出に向けて前半である本記事では、目的を設定し画像を収集するところから単純な画像認識を行うところまでご紹介しました。
最近は画像認識を簡単に実装出来るので、是非身近なものなどの分類に挑戦してみて下さい。


さてドーナツの分類は高精度で行えることが確認できたので、後半はいよいよレジの無人化という課題に向けて検出に挑戦しようと思います。
後半では物体検出のアルゴリズムの概要や検出の様子を紹介したいと考えているので、後半もよろしくお願いします!


アクセルユニバース株式会社(以下当社)では、人が対応している業務を画像認識、音声認識、文字認識等を活用して効率化する機械学習ソリューション開発をおこなっています。
今回挑戦している無人レジだけではなく、人と会話するかのようにシステムに問合せができるチャットボットや、カメラの前の人が誰であるか判別できる認証システムも検討しております。

  • 機械学習でどんな事ができるのか興味がある
  • 課題と感じている業務がある
  • 効率化したい業務がある


上記のような方はぜひ問い合わせページにご連絡ください。


Twitter・Facebookで定期的に情報発信しています!

本記事では、スタッキングの仕組みについて解説します。

この記事を読めば、スタッキングの理解、実装が円滑になると思います。

この記事の対象者

スタッキングの仕組みが分からないけど実装してみたい人

記事の目的

スタッキングのシンプルな仕組みを知り、実装しやすくする。
どういうときにスタッキングが有効なのか、どのようなモデルを組み合わせればよいのかを知る。

※コード実装部分は書いていません!

スタッキングとは

スタッキングとはアンサンブルの手法の一つであり、モデルを積み上げていく方法です。

・クロスバリデーションを用いる
・目的変数の予測結果を特徴量として用いる
・アンサンブル手法でもあり特徴エンジニアリング手法でもある

といった特徴があり、trainデータとtestデータの分布が似ているとき、特に良い精度が出せます。

スタッキングの手順解説

以下がスタッキングの手順です。

  1. クロスバリデーションでtrainデータとtestデータの目的変数を予測する
  2. 1の予測をそれぞれの特徴量に追加する
  3. 1,2を色々なモデルで行う
  4. 1~2で追加した特徴量も含めて、testデータの目的変数の予測を行う

それでは手順について細かく見ていきましょう。

1. クロスバリデーションでtrainデータとtestデータの目的変数を予測する

クロスバリデーションでtrainデータとtestデータの目的変数をそれぞれ予測します。

①,trainデータを分割(fold1~4)し、分割の内の1つ(青の丸部分)を、それ以外の残りのデータ(オレンジの丸部分)を用いて予測する
②,オレンジ丸部分を用いてtestデータの目的変数(青の長丸)を予測する。
③,①と②を全ての組み合わせで行う

下の図は、①〜③を図にしたもので、クロスバリデーションのやり方です。
※trainデータの方ではtrainデータの目的変数の一部(分割の少数側)を予測するのに対し、testデータの方ではtestデータの目的変数の全体を予測していることに注意してください。
※trainデータの説明変数をtrainX、目的変数をtrainY。testデータの説明変数をtestX、目的変数をtestYとしています。

1枚目:fold2~4を用いて学習させたモデルでfold1のtrainYとtestデータ全体の目的変数を予測
スクリーンショット 2019-12-23 9.50.00.png

2枚目:fold1,3,4を用いて学習させたモデルでfold2のtrainYとtestデータ全体の目的変数を予測
スクリーンショット 2019-12-23 9.53.12.png

3枚目:fold1,2,4を用いて学習させたモデルでfold3のtrainYとtestデータ全体の目的変数を予測
スクリーンショット 2019-12-23 9.54.28.png

4枚目:fold1~3を用いて学習させたモデルでfold4のtrainYとtestデータ全体の目的変数を予測
スクリーンショット 2019-12-23 9.55.24.png

以上が全ての分割の組み合わせで各目的変数を予測するイメージです。
これでtrainデータとtestデータの目的変数の全体を予測することができました。(下図)

1枚目:クロスバリデーションでtrainデータの目的変数を予測したもの
スクリーンショット 2019-12-23 10.15.10.png2枚目:クロスバリデーションでtestデータの目的変数を予測し、4つの予測結果を平均します。
スクリーンショット 2019-12-23 10.15.19.png

2. 1で行った目的変数の予測結果をそれぞれの特徴量に追加する

見出しの通りですが、下図のように追加します。
スクリーンショット 2019-12-23 11.02.05.png

3. 1,2を色々なモデルで行う

1,2の作業、つまり、「クロスバリデーション→trainデータ、testデータの目的変数の予測→特徴量に追加」を色々なモデルで行いましょう。
複数のモデル(今回は3つ)で行ってみました。その結果、このような感じで特徴量が増えていきます。

スクリーンショット 2019-12-23 11.50.42.png

4. 1~3で追加した特徴量を含めて、testデータの目的変数の予測を行う

スクリーンショット 2019-12-23 11.50.03.png

スタッキングのコツ

ところで、
「どのようなモデルを組み合わせれば良いのだろう?」とか「最後の予測では全ての特徴量を含めたほうがいいの?」とか、疑問に思いませんでしたか?自分が社内のインターン生で勉強会を行った時、これらのような質問が飛んできました。

Q,どのモデルを組み合わせれば良いのですか?

A,ごめんなさいわかりません!後日調べます!

ということで、Kaggle本や様々なネット記事を検索して調べてみました。
結局、確立した方法はみつかりませんでした。色々な組み合わせを試してみて、精度の上がったものを選択するようです。
ただ、スタッキングはアンサンブル手法ですので、汎化性能があがるようにモデルを組み合わせるのが良いです。
例えば、相関の近いモデルどうしを組み合わせても汎化性能は上がりません。モデル同士の相関を調べてみて、組み合わせて実験するのが良いのではないでしょうか。

次の質問です。

Q,最後の予測では元々合った特徴量含めるべき?

A,場合によるのではないでしょうか...?(わかってない)

ということで、同じように調べて考えてみました。

・元々の特徴量を加えた場合
過学習しやすい。同じデータの使われる回数が増え過学習しやすくなります。
その代わり、元々合った特徴量と予測値の関係性を分析することができます。

・加えなかった場合
過学習しづらい。学習時間が短く済む。アンサンブルの目的として、汎化性能を高めることがあるので過学習しづらい点は評価できます。

加えた場合も加えなかった場合も一長一短あるようなので、時間があればどちらも試すのが良いのではないでしょうか。

最後の質問です。

Q,どういうときにスタッキングは使えるの?

A, trainデータとtestデータの分布が似ていれば精度が上がりやすいです。

なので、時系列データの場合は分布が異なる場合が多いので、注意が必要です。
分布が似ているかどうかは、"Adversarial Validation"を使えば判断できます。

まとめ

本記事では、スタッキングの仕組みを図を用いて簡潔に解説しました。

  1. クロスバリデーションでtrainデータとtestデータの目的変数を予測する
  2. 1の予測をそれぞれの特徴量に追加する
  3. 1,2を色々なモデルで行う
  4. 1~2で追加した特徴量も含めて、testデータの目的変数の予測を行う

以上の手順で実装することができました。

スタッキングの実装は、仕組みを知ってしまえば難しいことではないと思います。
ただし、スタッキングが良い影響をでるかどうか、どのモデルを混ぜるか、など扱うのが難しい手法です。

テクニカルな利用方法はKaggleのnotebookや技術本などで研究する必要がありそうです。

参考文献

門脇大輔・阪田隆司・保坂桂佑・平松雄司(2019)『Kaggleで勝つデータ分析の技術』 技術評論社

はじめに

 最近のAIは音声認識や翻訳においては高い精度を出すことができます。
例えばAIが英語から日本語に翻訳する時、私達日本人が読んで多少の違和感があったりもしますが英文がどんなことを言っているのか理解することはできます。  
もしも機械が言語を理解して、人間と違和感なく会話できたらどうでしょう。そのようなことが可能になると、機械がどのようにして言語を理解したかを見ることによって、人間には気づくことができなかった新たな言語に関する発見ができるかもしれません。
さらには私達が子供の頃、お母さんなどの周りの言葉を聞いて徐々に話すようになり言葉を理解し始めました。これがどのようなメカニズムで理解されているか発見できるかもしれません。また、極論を言えば人間が機械に言語理解を任せれば良いので人間は時間をかけて言語を勉強する必要もなくなるかもしれません。このブログでは機械が言語を理解するための学問に関して簡単に書きます。

目次

  • はじめに

  • 機械が言語を理解するためには

  • 自然言語処理とは

  • 自然言語処理でできること

  • まとめ

機械が言語を理解するためには

 機械が言語を理解するということは機械がただ翻訳できればよいというわけでわありません。機械が文から人間がどのようなことを伝えたいか理解するためにはどのような壁があるでしょう。

  • 人間が話したり書いたりした文章から意味を理解する

  • 意味を理解したら人間が必要としてる回答を見つける

  • 回答を見つけたら人間にわかるように伝える

などなど...

 上記で挙げたものは全て難しいです。このような壁を乗り越えるためにどうすればよいでしょう。そこで登場するのが自然言語処理です。

自然言語処理とは

 自然言語処理とは、先程箇条書きであげた壁を乗り越えるための学問で機械に言語を理解させることを目標にしています。自然言語というのは人工言語(人工的に作られた言語、プログラミング言語)と対比させた言い方で人間が普段使っている言語のことです。

Alt text

 簡単に自然言語処理の歴史を説明します。

 1940〜1960年ごろは黎明期と呼ばれ1946年に初めてコンピュータが誕生しました。当初の目的は、弾道計算や暗号解読などの軍事目的でした。このコンピュータが翻訳にも使えるのではないかとロックフェーラー財団のウィーバーが考えました。この考えをきっかけに米国内で機械翻訳への関心が高まり1952年ジョージタウン大学とIBMが共同で翻訳プロジェクトを立ち上げロシア語から英語への小規模な翻訳実験が始まりました。これが自然言語処理の始まりです。 

その後、米国はソ連の科学技術の実態を知るべくロシア語から英語の翻訳に関する研究に関して多額の研究予算を投入しました。これにより機械翻訳は進展していきました。この時代は、コンピュータの処理能力が十分でなかったことも関係し研究者が自由な発想で夢を膨らましていたそうです。
スクリーンショット 2019-12-20 18.35.10.png

 1960〜1990年頃は忍耐期と呼ばれ莫大な研究費をかけましたが、研究が進展するに連れ、問題の難しさが認識されるような状況になりました。
1966年には機械翻訳の現状と将来に関する調査結果をALPAC報告書と呼ばれる報告書にまとめ、そこには近い将来に機械翻訳をすることは困難であり、言語の理解を目指す基礎的な研究を行うべきである、という内容のものでした。この報告書を機に、米国では機械翻訳においてほとんど研究費が出なくなりました。
更にこの頃は、自然言語処理の研究の難しさが明確になり、チェスのような明確に定義された問題における探索などに興味の中心が移っていきました。

この頃の自然言語処理に関する重要な出来事といえば1967年のBrown Corpusの発表です。
これは米国の言語の使用を調査する目的で、電子化された文書として初の100万語規模のコーパス(簡単に言えばテキスト文書の集合にある種の情報を付与したものです)で、新聞、雑誌、書籍など様々なジャンルのテキストをバランスよく収集したものを発表しました。1970年頃からコンピュータの処理能力が向上し言語やテキストを扱う基本的な環境が整い出しました。しかし、機械翻訳に代表される知的処理についてはまだ実用には精度が足りない状況でした。
スクリーンショット 2019-12-20 18.54.35.png

 1990年頃から現在までは発展期と呼ばれ、この頃はインターネットが世界的に普及し、社会基盤になった時期です。Brown Corpusの経験に学び各地で数億語規模のコーパスが作られました。1993年にはBrown Corpusのテキストに解釈を与えたPenn Treebankが最初の論文として発表されました。これは今後の機械学習に基づく自然言語処理研究を牽引したデータになりました。機械翻訳においても1980年代後半から統計的機械翻訳の研究を行いました。しかし、当時のコンピュータの処理能力や対訳コーパスの不足により十分に研究は発展しませんでした。
ところが、1990年代後半あたりから計算環境や対訳コーパス環境が整い、米国が機械翻訳によって紛争地域の素早い情報収集をするなどの目的から再度、多額の研究費を出すようになったこともあり、2000年以降、機械翻訳研究の大きな進展が見られました。またこの頃は、音声自動翻訳システムいわゆる通訳システムの研究も始められました。日本では東京オリンピック・パラリンピックが開催される2020年を目標に実用システムの開発を目指しています。このような自然言語処理の発展を強く印象づける出来事として2011年、Watsonが米国の人気クイズ番組「Jeopardy!」で人間チャンピオンに勝利しました。Watsonは約3000個のCPUからなる並列コンピュータによって、自然言語による質問を理解し、ウィキペディアなどの大量の情報の中から適切な回答を選択するシステムでした。更に、自然言語処理に大きな技術革新として2015年頃から本格化し始めたニューラルネットワークです。ニューラルネットワーク自体は1940年代に提案されていましたが当時のマシンパワーでは計算力が足りず難しい状況でした。


2000年代に入り、マシンパワーの増大、ビックデータの利用、アルゴリズムの改良などから再び注目されました。2010年代に入り画像認識、音声認識などの様々なタスクで大きな精度向上が見られるようになりました。特に、ニューラルネットワークを用いた翻訳手法、ニューラル機械翻訳は大きな精度向上をもたらし、機械翻訳を一気に実用レベルの技術に押し上げました。
fabio-oyXis2kALVg-unsplash.jpg

 自然言語処理の現状としてDeepLearningの登場もあり、文章を単語単位に分割し単語がどのように並んでいるかパターンを捉えることや、似ている単語を把握する事ができます。これに関しては実用化もされていて有名なものだと新聞記事の単語の関係性などを機械が学習し記事の重要な部分を抜き出してまとめてくれる要約サービスがあります。しかし、機械が言語を理解することはDeepLearningを用いた最新モデルとされているBERT(バート)でさえ実現することはできませんでした。機械が言語を理解するにはまだまだ研究段階であり時間を必要としているのが現状です。

自然言語処理でできること

自然言語処理でできることを今回は3つ紹介します。

コールセンターの対応を自動化

コールセンターの業務はマニュアル通りに電話応対をし人間がマニュアルを参照し適切な回答を選択しています。マニュアルで対応できない質問に対しては後日回答や担当の者に電話をつなげるなどの対処が必要です。自然言語処理を用いれば今まで人がマニュアル通りに応対していたところを、機械で実現できます。音声認識により機械が質問を理解し、自然言語処理を用いて質問にあった適切な回答を選択します。

教育現場において生徒のSNSを分析しいじめ発見

SNS分析をする際も自然言語処理は有効です。自然言語処理の中の文書分類を用い、SNSに書き込まれた文章に対してこの文章はいじめに関係しそうな単語がどの程度含まれているか確率的に分析し、その確率が高いときはいじめに関係している文章とし、生徒のいじめ早期発見につなげます。

コンビニやスーパーでアンケートを自動で分類するシステム

コンビニやスーパー等においてアンケートを自動で分類する際もクラスタリングを用いることで可能です。大量のアンケートから項目ごとに似た回答をしているものをグループ化し、アンケートの分類を自動化する事が可能です。具体的な手法としてはK-means方というのがあり詳しくはこちらを参考にして下さい。

まとめ

最近の話題だと、東ロボくんというロボットが東大に入れるかというプロジェクトがあります。これは、機械が言語を理解できたら確実に合格できると言われています。あくまで想像ですが、入学後も常に成績トップで人間には到底かなわない存在になってしまうかもしれません。
それほど自然言語処理という学問はかなり難しいとされています。難しい分、研究が進み機械が言語を理解したら私達の常識が変わったり、人間の言語に対する理解が深まり様々な場面で応用できることが期待されており、私達はその難問に挑戦します。

参考文献

コンピュータで言葉を理解する言葉の意味を処理するとは?

人間と人工知能の違い

チャットボットAIの現状を解説!自然言語処理は今なにができるの?

自然言語処理〔改訂版〕 (放送大学教材) 黒橋禎夫著


Twitter・Facebookで定期的に情報発信しています!

はじめに

 今回は世の中のトレンドを用いた株価予測をしてみたいと思います。今までに得た機械学習などの知識を実生活に用いてみたいと思っており、お金を稼ぐという意味で株価予測が候補にありました。以前、個人的にFXの値の上下予測を5分単位、1時間単位などで、テクニカル指標を用いて試してみたことがあったのですが、テクニカル指標だけでは期待した精度は出ませんでした。

 ということで、世の中のトレンドも特徴量として取り入れてみようと思い立ち、トレンドに左右されそうな株価で予測してみることにしました。

 よって、トレンドの影響具合を確認することをゴールとします。銘柄も絞ったほうがトレンドに対する影響が出やすいと考え、今回は任天堂を採用しました。任天堂を選んだ理由は特にないです。

結果

2015〜2019までの株価データを用い、過去6週のデータで次週の株価が上がるか下がるかの予測をし、

2015〜2018のデータで2019を予測:正解率60.4%

となりました!

取り組みの過程

以下で、取り組みの流れを説明します。

データを持ってくる

 皆さんは、Google Trendsというサービスをご存知でしょうか?トレンドを定量化する方法に悩んだ末たどり着いた方法がこれです。

 あるワードを入力すると、過去にGoogleでそのワードが検索された頻度(正規化済み)を示してくれます。CSVファイルとしてダウンロードもできるため、今回はこのサービスを活用しました。手軽さがこのサービスの良い点ですね。 カテゴリごとに分けることもできる(金融、ショッピングなど)ため、いくつかに分けてみました。

 最大で5年間のデータが持ってこれるようですが、1週間ごとになってしまいます。データ量が減ってしまうため、ここは少し残念です...

date

前処理など

以下の写真のように複数のカテゴリのデータも用います。 まずライブラリをインポートし、

 import pandas as pd
 import numpy as np
 import matplotlib.pyplot as plt
 import seaborn as sns
 %matplotlib inline

トレンドと、任天堂の株価のデータを一つにまとめます。

trend = pd.read_csv("multiTimeline_all.csv", header=1)
trend.columns = ["date", "value_all"]
trend["date"] = pd.to_datetime(trend["date"])

for cat in ["art_entertainment", "beauty", "business", "finance", "game", "law", "news", "shopping"]:
    cat_trend = pd.read_csv(f"multiTimeline_{cat}.csv", header=1)
    cat_trend.columns = ["date", f"value_{cat}"]
    cat_trend["date"] = pd.to_datetime(cat_trend["date"])
    trend = pd.merge(trend, cat_trend, on=["date"], how="left")

import pandas.tseries.offsets
trend["date"] = trend["date"] + offsets.Day(2)

import codecs
stock_price = pd.DataFrame()
for i in range(5):
    year = i + 2015
    with codecs.open(f"7974_{year}.csv", "r", "Shift-JIS", "ignore") as file:
        stock_price_each_year = pd.read_table(file, delimiter=",", header=1)
        stock_price = pd.concat([stock_price, stock_price_each_year], axis=0)

stock_price = stock_price[["日付", "出来高" , "終値調整値"]]
stock_price.columns = ["date", "volume", "close_price"]
stock_price["date"] = pd.to_datetime(stock_price["date"])

matrix = pd.merge(trend, stock_price, on=["date"], how="left")
matrix = matrix.dropna(subset=["volume"])

トレンドのデータは毎週日曜日の日付になっていたので、2日遅らせて火曜日としました(月曜日は休日で株価のデータがない場合が多いため)。 ここから1〜6週間前のトレンドを特徴量として作ります。

new_fe = []
for i in range(6):
    for col in ['value_all', 'value_art_entertainment', 'value_beauty',
       'value_business', 'value_finance', 'value_game', 'value_law',
       'value_news', 'value_shopping', 'volume', 'close_price']:
        matrix[f"{col}_{i+1}_weeks_ago"] = matrix[f"{col}"].shift(i+1)
        new_fe.append(f"{col}_{i+1}_weeks_ago")
matrix = matrix.drop([3, 4, 5, 6, 7])

そして、このnew_feの特徴量を予測に使います。

matrix["close_price_diff"] = matrix["close_price"] - matrix["close_price"].shift()
matrix["binary"] = matrix["close_price_diff"].apply(lambda x: 1 if x >= 0 else 0)

目的変数も作りました。

ちなみに、目的変数と特徴量(使わないもの含む)の相関の上位です。

date

モデルのトレーニングと予測

 モデルはLGBMを用いました。時系列データであるためLSTMも使ってみたかったのですが、データ量が少ないため断念しました。今回のLGBMのmetricはAUCです。

import lightgbm as lgb
from sklearn.metrics import accuracy_score

params = {'objective': 'binary',
          'max_depth': -1,
          'learning_rate': 0.01,
          "boosting_type": "gbdt",
          "bagging_seed": 44,
          "metric": "auc",
          "verbosity": -1,
          "random_state": 17
}
X = matrix[new_fe]
y = matrix["binary"]

columns = X.columns
y_oof = np.zeros(X.shape[0])
score = 0

feature_importances = pd.DataFrame()
feature_importances['feature'] = columns

X_train, X_valid = X[:X.shape[0]//5*4], X[X.shape[0]//5*4:]
y_train, y_valid = y[:X.shape[0]//5*4], y[X.shape[0]//5*4:]

dtrain = lgb.Dataset(X_train, label=y_train)
dvalid = lgb.Dataset(X_valid, label=y_valid)

clf = lgb.train(params, dtrain, 3000, valid_sets = [dtrain, dvalid], verbose_eval=100, early_stopping_rounds=400)

feature_importances[f'fold_{fold_n + 1}'] = clf.feature_importance(importance_type="gain")

def my_binary(x):
    if x >= 0:
        return 1
    else:
        return 0

y_pred_valid = clf.predict(X_valid)
y_oof[valid_index] = list(map(my_binary, y_pred_valid))


print(f"AC: {(accuracy_score(y_valid, list(map(my_binary, y_pred_valid))))}")

del X_train, X_valid, y_train, y_valid

AUCと正解率は以下です。

date

特徴量重要度の上位は以下のようになりました。

スクリーンショット 2019-12-13 15.35.23.png

また、この予測した通りに取引した場合の結果も計算しました。

def my_profit(diff, ans, pred):
    if ans == pred:
        return abs(diff)
    else:
        return abs(diff) * -1
sum(matrix.iloc[int(X.shape[0]/20):, :][["close_price_diff", "binary", "pred"]].apply(lambda x: my_profit(x[0], x[1], x[2]), axis=1).values)

結果は以下です。

date

つまり、毎回100株の取引をすると30万円の儲けです!これはなかなか嬉しいですね

結果の考察

 データが240と少ないため、断定はできませんが、トレンドと株価には何かしらの関係があるのではないかと考えられます。

 特徴量重要度をみると、「取引量」のほか、「アート、エンターテイメント」、「金融」、「美容、フィットネス」などのカテゴリのトレンドが重要であったことがわかります。また、6週間前の値が特徴量として効いていたりもするようで、非常に興味深いです。少し追加で調べていきます。

 まず、Google Trendsから得られるのはあくまで検索数の上下であり、それは任天堂のプラスなトレンドもマイナスなトレンドも同時に反映しています。にも関わらず、なぜ上下を60%で予測できたのかについて考えました。僕はこれについて、カテゴリごとにトレンドを分けた特徴量を加えたからではないかという考えに至りました。上に記載した特徴量重要度をみてみると、value_all、すなわち全体の検索数の特徴量があまり予測に寄与していないことがわかります。

date

これはカテゴリごとの時間の変化での検索数(正規化済み)の上下の1部のグラフですが、カテゴリによって動きが大きく違います。

 つまり、任天堂にとってプラスなトレンドを表すカテゴリ、逆にマイナスを表すカテゴリがあるのではないでしょうか。例えば、アート、エンターテイメントの検索はマイナスよりプラスな意味での検索をする人が多く、法律の検索は告訴した、告訴されたなどのマイナスな検索が多そうです。

date

上の写真は法律カテゴリの検索数ですが、2018年1月付近に急増加しています。1月10日はコロプラが、12月22日付で特許権侵害に関する訴訟を任天堂より提起され、1月9日に訴状内容を確認したことを発表した日です。

まとめ

 トレンドの特徴量だけでここまでの精度が出るとは思っていませんでした。トレンドの測り方はGoogle Trends 以外にもツイッターなどのSNSがあるため、これらを増やしていくことで長期間での株価の予測は可能なのではないでしょうか。株価は様々なものに影響を受けるものであるため、どんな特徴量を足していくか?が重要だと思われます。


Twitter・Facebookで定期的に情報発信しています!

はじめに

今回はU-netの番外編でskip-conectionについてまとめようと思います。 前回のtensorflowで学習をさせてみた際に、skip-conectionがない場合、学習が遅いだけでなく精度が悪いことがわかりました。 skip-conectionが(おそらく)初めて使われたのが2015年12月に発表されたResNetで、ImageNet2015の分類コンペ(ILSVRC 2015)で1位になりました。


目次

  • ResNet以前
  • skip-conection
  • skip-conectionの効果
  • なぜskip-conectionが効くのか


1.ResNet以前

深層学習において層の数はとても重要な要素であり、ImageNetにおいてResNetが発表される以前は16~30層ほどの比較的深いモデルが主流でした。 そこで「層を深くすればするほど、精度は良くなるのか」という疑問が生まれますが、そう上手くはいきません。 なぜなら層を深くすることにより勾配消失問題が起きてしまうからです。 この勾配消失問題に対してBatch Normalizationが考案され、勾配消失が起きづらくなりました。

しかし、層を深くしていく中である深さで精度が頭打ちになり、更に層を増やすことで精度が著しく悪くなってしまいました。

Alt text

上の図を見ると18層のモデルに層を追加し34層にしても精度がほとんど変わらないどころか、むしろ悪くなっていることがわかります。


2.skip-conection

ResNetの著者は、上の図に現れている劣化現象は勾配消失によるものではなく重みの最適化に問題があると考えました。つまり層を深くしても最適化できず、層を深くした恩恵を受けられないと考えました。 そこで考案されたのがskip-conectionです。

Alt text

xを入力として、xに重みをかける(weighted layerを通る)関数をF(x)とします。 F(x) + xを最終的な出力としています。

skip-conectionを34層のモデルで行った様子は以下のようになります。 左が通常のモデル、右がskip-conectionありのモデル

Alt text


3.skip-conectionの効果

通常のモデルにskip-conectionを用いたものをResNetと呼ぶことにします。 上と同様にImageNetで精度を計算すると以下のようになりました。

Alt text 層が深いモデルの方が精度が良いことがわかります。 さらに重要なことに34層のモデルの学習時の精度(赤の細線)が、18層のモデルの学習時の精度(青の細線)よりもかなり良くなっていることがわかります。 これは劣化現象を上手く解決し、より深く学習できるようになったことを示しています。 (層を深くすることによる恩恵を受けられた。)


4.なぜskip-conectionが効くのか

Alt text xを入力としてH(x)を目標とする関数とします。 xに重みをかける(weighted layerを通る)関数をF(x)とします。 F(x) + xを最終的な出力とし、これを目標の関数H(x)に近づけます。

F(x) + x = H(x) の時(目標の関数に等しくなれた時) F(x) = H(x) - xとなることから、Fは入力xと目標とする関数H(x)の残差(residual)と等しいことがわかります。

つまりFそのものをHに近くなるように学習するのではなく、Hとxの残差を正確に予測できるように学習しています。

このようにするとHが恒等関数に近い時、FそのものをHに近づけるのは難しいですが、F+xを近づけることは簡単になります。 論文の筆者も劣化問題は目標の関数Hが恒等関数の時、重みに対して非線形である関数FでHに近づくことが難しいために起きていると主張しています。


まとめ

U-netでskip-conectionは畳み込みにより失われる物体の位置情報を保持する役目があり、skip-conectionが使われ始めた当初とは少しだけニュアンスが違うように感じました。 残差を予測するという考えは以前からあるようで、代表的なものだとGBDTが挙げられます。 こちらの記事も是非ご覧ください。

GBDTを小学生レベルの数学で直感的に理解する


参考

https://arxiv.org/abs/1512.03385


Twitter・Facebookで定期的に情報発信しています!

目次

  1. 海洋エネルギーとは?
  2. 海洋エネルギー発電の普及に向けた課題とその解決策
  3. 機械学習を用いた海洋エネルギー発電の課題への解決策
  4. これから私が取り組むこと
  5. 参考文献


1. 海洋エネルギーとは?

 海洋再生可能エネルギー(略して、海洋エネルギー)とは、洋上風力(図1)、波力(図2、3)、海流(図4)、潮流(図5)、潮汐、海洋温度差、塩分濃度差といった再生可能エネルギーを指す。地球表面の約70%は海で覆われているため、海洋エネルギーは非常に膨大で、決して枯渇することはないエネルギーである。我が国の200海里経済水域の面積は世界第6位であり、国民一人当たりの海域面積は主要先進国では最も大きい。このことからして、我が国が強力に開発すべき再生可能エネルギーは、海洋エネルギーである。

Ocean energy

図1 長崎県五島市の洋上風力発電装置「はえんかぜ」



Ocean energy

図2 Ocean Power Technologies社の波力発電装置



Ocean energy

図3 Wello Oy社の波力発電装置



Ocean energy

図4 IHIの海流発電装置



Ocean energy

図5 SIMEC Atlantis Energy社の潮流発電装置(これが海中に設置される)


 そもそも再生可能エネルギーとは、地球温暖化の原因である温室効果ガスを排出せず、環境にやさしく、枯渇する心配がないエネルギーのことである。地球温暖化が進行すると、

  • 高潮や沿岸部の洪水、海面上昇による被害
  • 大都市部への内水氾濫による被害
  • 極端な気象現象によるインフラ機能停止
  • 熱波による死亡や疾病
  • 気温上昇や干ばつによる食料不足や食料安全保障の欠如
  • 水資源不足と農業生産減少
  • 陸域や淡水の生態系、生物多様性がもたらす様々なサービスの損失
  • 海域の生態系、生物多様性への影響
    上記のような多くの問題が生じる。


 化石燃料(石油、天然ガス、石炭)による発電は、温室効果ガス(二酸化炭素など)を排出し、地球温暖化を進める発電方法である。また、資源に乏しい我が国は、エネルギー供給のうち、化石燃料が8割以上を占めており、そのほとんどを海外からの輸入に頼っている。特に東日本大震災後、エネルギー自給率は10%を下回っており、エネルギー安定供給の観点から、この改善を図っていく必要がある。


 再生可能エネルギーは国産のエネルギー源であるため、エネルギー自給率の改善にも寄与することができる。更に、東日本大震災による原発事故を受け、原子力発電所が東日本大震災並の地震に耐え得るには、設計の見直しが必要であり、今後安全対策費が高くなることが予想されるため、発電コストは今後も高くなる。また、放射性廃棄物の処理についてもまだ未解決の問題である。このことから再生可能エネルギーは今非常に注目を集めている。


 では、その再生可能エネルギー発電と言えば、太陽光発電や風力発電が現在主流であるが、これらに対抗できるほどのメリットが海洋エネルギー発電にあるのかと疑問を抱く方は多いかもしれない。太陽光発電は、夜間や雨・曇りの日などには発電できない。即ち、設備利用率(発電設備の実際の発電量が仮にフル稼働していた際の発電量の何パーセントほどであるのかを示す数値)が低い。それに対し、海洋エネルギー発電は、夜間でも、天候が多少悪くても稼働できるため、設備利用率は太陽光発電に比べて高い。


 また陸上の風力発電は土地や道路の制約があり、特に国土が狭く地形も複雑な日本では、風の条件が良い場所はどうしても限られ、景観や騒音の問題によって大型化できないのに対し、同じ風力でも洋上風力発電ではその心配はない。表1は再生可能エネルギーの設備利用率の比較である。海洋エネルギー発電には他の再生可能エネルギーより優れた点がある。

スクリーンショット 2019-12-12 12.32.39.png


2. 海洋エネルギー発電の普及に向けた課題とその解決策

 現在、海洋エネルギー発電は、まだ世界的にも研究開発もしくは実証研究の段階にあり、本格的な事業化に向けて、以下の課題を克服しなければならない。

スクリーンショット 2019-12-10 14.55.02.png
 まず、機械学習を活用しない解決策を課題毎に述べる。


<課題①「電力需要量とのバランスが取りにくい」>

  • 蓄電装置や電力の水素への転換などの蓄電方法の開発・改良を行う。



<課題②「発電効率が火力発電や原子力発電などに比べて低い」、課題⑥「発電コストが高い」>

  • 単機では発電効率が低く発電コストは高いが、数を増やすことで発電効率を向上させ、発電コストも下げる。(再生可能エネルギーは数が増えることで発電コストが急減する)

Ocean energy

図6 ドイツのブーテンディーク洋上風力発電所



<課題⑤「他の再生可能エネルギーと比べて実績が足りない」>

  • 水槽試験だけでなく長期的な実海域試験を単機だけでなく複数機で行う。
  • EMEC(欧州海洋エネルギーセンター)のような海洋エネルギーの実海域試験を行う研究所を我が国にも造る。

スクリーンショット 2019-12-10 17.26.12.png

図7 EMECの景観を配慮した波力発電テストサイトの変電施設(長崎海洋大使・海外先進地 派遣事業報告書)



<課題⑦「試験運転であっても国や地方自治体への計画・建設の許可が必要」>

  • 技術的課題、経済的課題、環境的課題をできる限り解決し、国や地方自治体の認可をもらえるようにする。



<課題⑧「航行や漁業などの海域利用者や地域の方々の理解が必要」>

  • 海域利用者と十分に協議し、周辺住民への情報の開示する。
  • 地域の活性化に繋がることを周辺住民へ伝える。
  • 発電機周辺には魚が集まってくるなど、漁業にもメリットがあることを伝える。

Ocean energy

図8 発電装置に付着した海藻に集まる魚



<課題⑨「辺環境や生物生態系への懸念」>

  • 実海域試験を行い、周辺環境や生物生態系への影響を調査し評価する。


3. 機械学習を用いた海洋エネルギー発電の課題への解決策

 海洋エネルギーの技術的課題を解決するためには当然、発電装置や蓄電装置、海底ケーブルなどの開発・改良を行う必要があるが、ここでは、太陽光発電や陸上風力発電で取り組まれている解決策を参考に私が考えた、機械学習(人工知能)を用いた解決策を紹介する。


<課題①「電力需要量とのバランスが取りにくい」、課題③「無駄な待機運転の時間がある」への解決策>

~発電量・電力需要量予測と制御~

 発電装置周辺の気象・海象データを説明変数として発電量を予測し、カレンダー条件(時間帯、曜日など)と気温や日射強度などの気象条件を説明変数として電力需要量を予測することで、需要と供給の差が確認できる。そして電力需要量の送電にかかる時間分先の予測値と同量を発電するように発電装置を制御すれば、需要と供給のバランスを保ちながら発電することができる。発電機の無駄な待機時間も削減され、設備稼働率も向上する。



<課題②「発電効率が火力発電や原子力発電などに比べて低い」への解決策>

~機械学習を用いた制御~

 例えば洋上風力発電や海流発電、潮流発電ならば、効率よく電力を取り出せる羽根の回転数が風速または流速によって異なるので、回転数を機械学習によって制御することで、発電効率を最大化することができる。
 また、これは私のアイデアではないが、波力発電装置の発電量の平均値が最大になるように機械学習(強化学習)を用いて制御するといった研究も行われている。



<課題③「無駄な待機運転の時間がある」、課題④「台風など局所的に厳しい海象条件下での安全性の懸念」への解決策>

~発電装置が遭遇する気象・海象を予測~

 発電装置が遭遇する気象や海象を事前に予測しておくことで、台風や大波が来る前に発電をやめ、安全を確保する状態に切り替えることができる。また台風や大波といった本当に稼働停止しなくては損傷してしまう場合以外は稼働することができ、無駄な待機時間が減少する。



<課題③「長いメンテナンスにより稼働時間が減る」、課題⑥「海上工事や潜水作業のコストが高い」への解決策>

~海中ロボットによるメンテナンス~

 メンテナンス時の潜水作業を人が行うのではなく、機械学習を搭載した海中ロボットが行う。 水中を自動運転したり、画像診断などによって腐食や付着物を検知するなど、メンテナンス作業を効率よく行い、発電装置の稼働時間を増やす。



<課題④「台風など局所的に厳しい海象条件下での安全性の懸念」への解決策>

~異常検知~

 発電装置に速度センサや加速度センサを設置して、発電機の運動を測定し、応力(単位面積当たりの力)センサを設置して、発電機の応力を測定することで、運動や応力のデータが得られ、それを説明変数として、発電機の異常検知をする。
異常を確認すると稼働停止するようにしておくことで、安全性が向上する。


4. これから私が取り組むこと

 私は何としてでも、海洋エネルギーを我が国で普及させたいと考えている。そのために今回海洋エネルギー発電の課題について取り上げてきた。そして3章で示したように、海洋エネルギーを普及させる方法の一つとして機械学習を用いる方法があり、私はこれに非常に興味を持ち、可能性を感じている。
 今後は、「機械学習を用いた海洋エネルギー発電の効率向上と制御」「機械学習を用いた発電装置などの運動する海洋構造物の安全性確保と評価」をテーマに研究を行っていく。具体的には3章で紹介した「機械学習を用いた制御」や「異常検知」について着目しようと考えている。また安全性の評価として機械学習を用いることができないかなど、海洋エネルギーに対する機械学習の新たな用途の探求も行っていく。
 このような私の研究によって、海洋エネルギー発電の課題が一つずつ解決して行き、海洋エネルギー発電が事業化することで、我が国だけでなく世界中のエネルギー問題が解決することを私は期待している。しかし、この研究を進めるためには海洋エネルギーに関するデータが必要であることは言うまでもない。


5. 参考文献


Twitter・Facebookで定期的に情報発信しています!

はじめに

前回の「画像セグメンテーションのためのU-net概要紹介」では画像のクラス分類のタスクを、画像のSegmentationのタスクにどう発展させるかを解説し、SegmentationのネットワークであるU-netの理論ついて簡単に解説しました。
今回はTensorFlowのSegmentationのチュートリアルを行いながら、実際にU-netを学習させてみたいと思います。
尚、本記事ではTensorflowの詳しい解説は行いません。
参考 : https://www.tensorflow.org/tutorials/images/segmentation

Segmentationとは

ある物体が画像内に含まれている時、画像のどこにあるのかを推定するタスクのことです。
言い換えると「画像のピクセルがそれぞれ何かを推定する」タスクのことです。
今回はOxford-IIIT Pet Datasetというデータセットを用いて学習を行い、ピクセルごとに以下のようなクラス分けを行います。

  • Class 0 : 動物のピクセル
  • Class 1 : 動物とその他の境界線のピクセル
  • Class 2 : その他のピクセル


目標は以下のような出力を得ることです。(左:入力画像 右:出力画像)
Alt text


ライブラリのインポート

import tensorflow as tf
import sys
from IPython.display import display
from IPython.display import HTML
from PIL import Image
# sys.modules['Image'] = Image 
from __future__ import absolute_import , division, print_function, unicode_literals
from tensorflow_examples.models.pix2pix import pix2pix

import tensorflow_datasets as tfds
tfds.disable_progress_bar()

from IPython.display import clear_output
import matplotlib.pyplot as plt


データの読み込み&可視化

dataset, info = tfds.load('oxford_iiit_pet:3.0.0', with_info=True)

def normalize(input_image,input_mask):
    input_image = tf.cast(input_image, tf.float32) / 255
    input_mask -= 1
    return input_image,input_mask

@tf.function
def load_image_train(datapoint):
    input_image = tf.image.resize(datapoint['image'],(128,128))
    input_mask = tf.image.resize(datapoint['segmentation_mask'],(128,128))

    if tf.random.uniform(()) > 0.5:
        input_image = tf.image.flip_left_right(input_image)
        input_mask = tf.image.flip_left_right(input_mask)
    input_image,input_mask = normalize(input_image, input_mask)
    return input_image, input_mask

def load_image_test(datapoint):
    input_image = tf.image.resize(datapoint['image'], (128, 128))
    input_mask = tf.image.resize(datapoint['segmentation_mask'], (128, 128))
    input_image, input_mask = normalize(input_image, input_mask)
    return input_image, input_mask

TRAIN_LENGTH = info.splits['train'].num_examples
BATCH_SIZE = 64
BUFFER_SIZE = 1000
STEPS_PER_EPOCH = TRAIN_LENGTH // BATCH_SIZE

train = dataset['train'].map(load_image_train, num_parallel_calls=tf.data.experimental.AUTOTUNE)
test = dataset['test'].map(load_image_test)

train_dataset = train.cache().shuffle(BUFFER_SIZE).batch(BATCH_SIZE).repeat()
train_dataset = train_dataset.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)
test_dataset = test.batch(BATCH_SIZE)

def display(display_list):
    plt.figure(figsize=(15, 15))

    title = ['Input Image', 'True Mask', 'Predicted Mask']

    for i in range(len(display_list)):
        plt.subplot(1, len(display_list), i+1)
        plt.title(title[i])
        plt.imshow(tf.keras.preprocessing.image.array_to_img(display_list[i]))
        plt.axis('off')
    plt.show()

for image, mask in train.take(88):
    sample_image, sample_mask = image, mask
display([sample_image, sample_mask])

Alt text


U-netの構築

U-netのencorder部分には今回のデータセットとは別のデータセットを学習したのMovileNetを用います。
MovileNetの重みは学習で更新しないように更新しておきます。
このようにすることU-netの精度を上げることができます。(転移学習)
decorder部分には未学習のpix2pixを用います。
pix2pixの重みは学習により更新されます。

OUTPUT_CHANNELS = 3

# encorder部分には学習済みのMovileNet
base_model = tf.keras.applications.MobileNetV2(input_shape=[128,128,3],include_top=False)
layer_names = [
    'block_1_expand_relu',
    'block_3_expand_relu',
    'block_6_expand_relu',
    'block_13_expand_relu',
    'block_16_project'
]
layers = [base_model.get_layer(name).output for name in layer_names]
down_stack = tf.keras.Model(inputs=base_model.input, outputs=layers)
# MovileNetの重みは固定
down_stack.trainable = False

# decorder部分にはpix2pixを用いる
up_stack = [
    pix2pix.upsample(512, 3),  # 4x4 -> 8x8
    pix2pix.upsample(256, 3),  # 8x8 -> 16x16
    pix2pix.upsample(128, 3),  # 16x16 -> 32x32
    pix2pix.upsample(64, 3),   # 32x32 -> 64x64
]

def unet_model(output_channels):

    # This is the last layer of the model
    last = tf.keras.layers.Conv2DTranspose(
        output_channels, 3, strides=2,
        padding='same', activation='softmax')  #64x64 -> 128x128

    inputs = tf.keras.layers.Input(shape=[128, 128, 3])
    x = inputs

    # Downsampling through the model
    skips = down_stack(x)
    x = skips[-1]
    skips = reversed(skips[:-1])

    # Upsampling and establishing the skip connections
    for up, skip in zip(up_stack, skips):
        x = up(x)
        concat = tf.keras.layers.Concatenate()
        x = concat([x, skip])

    x = last(x)

    return tf.keras.Model(inputs=inputs, outputs=x)


U-netの学習

実際にU-netが学習していく様子を眺めてみましょう。
epochが進むにつれ、正しく予測できているのがわかります。

class DisplayCallback(tf.keras.callbacks.Callback):
    def on_epoch_end(self, epoch,logs=None):
        clear_output(wait=True)
        ims.append([sample_image, sample_mask,
                 create_mask(model.predict(sample_image[tf.newaxis, ...]))])
        print ('\nSample Prediction after epoch {}\n'.format(epoch+1))

def create_mask(pred_mask):
    pred_mask = tf.argmax(pred_mask, axis=-1)
    pred_mask = pred_mask[..., tf.newaxis]
    return pred_mask[0]

def show_predictions(dataset=None, num=1):
    if dataset:
        for image, mask in dataset.take(num):
            pred_mask = model.predict(image)
            display([image[0], mask[0], create_mask(pred_mask)])
            ims.append([image[0], mask[0], create_mask(pred_mask)])
    else:
        display([sample_image, sample_mask,
                 create_mask(model.predict(sample_image[tf.newaxis, ...]))])
        ims.append([sample_image, sample_mask,
                 create_mask(model.predict(sample_image[tf.newaxis, ...]))])

ims = []
EPOCHS = 100
VAL_SUBSPLITS = 5
VALIDATION_STEPS = info.splits['test'].num_examples//BATCH_SIZE//VAL_SUBSPLITS

model = unet_model(OUTPUT_CHANNELS)
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
model_history = model.fit(train_dataset, epochs=EPOCHS,
                          steps_per_epoch=STEPS_PER_EPOCH,
                          validation_steps=VALIDATION_STEPS,
                          validation_data=test_dataset,
                          callbacks=[DisplayCallback()])

import matplotlib.animation as animation

def make_animation(ims):
    %matplotlib nbagg
    fig, (ax0, ax1, ax2) = plt.subplots(1,3,figsize=(14.0, 8.0))
    ax0.axis('off')
    ax1.axis('off')
    ax2.axis('off')
    ax0.set_title('Input Image')
    ax1.set_title('True Mask')
    ax2.set_title('Predicted Mask')

    ims2 = []
    for epoch,im in enumerate(ims):   

        im0, = [ax0.imshow(tf.keras.preprocessing.image.array_to_img(im[0]))]
        im1, = [ax1.imshow(tf.keras.preprocessing.image.array_to_img(im[1]))]
        im2, = [ax2.imshow(tf.keras.preprocessing.image.array_to_img(im[2]))]
        ims2.append([im0,im1,im2])
    ani = animation.ArtistAnimation(fig, ims2, interval=50, repeat_delay=1000)
    return ani

学習の様子

学習の様子を見てみます。epochが進むごとに精度が増していることがわかります。

Alt text

ani1 = make_animation(ims)
HTML(ani1.to_jshtml())


おまけ

U-netにはskip-conectionという手法が使われています。
encorder部分で畳み込みをして失ってしまった画像内の位置情報を保持する役割を持ちます。
U-netにskip-conectionが無い場合も比較してみましょう。

up_stack = [
    pix2pix.upsample(512, 3),  # 4x4 -> 8x8
    pix2pix.upsample(256, 3),  # 8x8 -> 16x16
    pix2pix.upsample(128, 3),  # 16x16 -> 32x32
    pix2pix.upsample(64, 3),   # 32x32 -> 64x64
]

def unet_model_no_sc(output_channels):

    # This is the last layer of the model
    last = tf.keras.layers.Conv2DTranspose(
        output_channels, 3, strides=2,
        padding='same', activation='softmax')  #64x64 -> 128x128

    inputs = tf.keras.layers.Input(shape=[128, 128, 3])
    x = inputs
    x = down_stack(x)
    x = x[-1]
    for up in up_stack:
        x = up(x)
    x = last(x)

    return tf.keras.Model(inputs=inputs, outputs=x)

ims = []
EPOCHS = 100
VAL_SUBSPLITS = 5
VALIDATION_STEPS = info.splits['test'].num_examples//BATCH_SIZE//VAL_SUBSPLITS

model = unet_model_no_sc(OUTPUT_CHANNELS)
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
model_history = model.fit(train_dataset, epochs=EPOCHS,
                          steps_per_epoch=STEPS_PER_EPOCH,
                          validation_steps=VALIDATION_STEPS,
                          validation_data=test_dataset,
                          callbacks=[DisplayCallback()])


学習の様子

こちらも学習の経過を眺めてみます。
skip-conectionがある場合と比べ、学習が遅いばかりか精度が悪いことがわかります。

Alt text


Twitter・Facebookで定期的に情報発信しています!

はじめに

こんにちは、システム部の譚です。
Google Colablatoryで、手書きの数字(0, 1, 2 など)から構成されているMNISTデータセットを使い、分類問題のニューラルネットワークを構築してみました。

目次

はじめに
モデルを構築する
おわりに

モデルを構築する

手順

1.TensorFlowのモデルを構築し訓練するためのハイレベルのAPIである tf.kerasを使用する。

from __future__ import absolute_import, division, print_function, unicode_literals

# TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import keras

# Helper libraries
import numpy as np
import matplotlib.pyplot as plt

print(tf.__version__)

2.訓練データとテストデータをダウンロードする。

fashion_mnist = keras.datasets.fashion_mnist

(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

3.後ほど画像を出力するときのために、クラス名を保存しておく。

mnist = keras.datasets.mnist

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

4.label nameをつける。

class_names = ['0', '1', '2', '3', '4','5', '6', '7', '8', '9']

5.データの前処理をする。
最初の画像を調べてみればわかるように、ピクセルの値は0から255の間の数値です。
ニューラルネットワークにデータを投入する前に、これらの値を0から1までの範囲にスケールするので、画素の値を255で割ります。

train_images = train_images / 255.0

test_images = test_images / 255.0

6.訓練用データセットの最初の25枚の画像を、クラス名付きで表示する。

plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i], cmap=plt.cm.binary)
    plt.xlabel(class_names[train_labels[i]])
plt.show()

7.モデルを構築する。 

model = keras.Sequential([
    # データのフォーマット変換
    keras.layers.Flatten(input_shape=(28, 28)),
    # 128個のノードのDense層
    keras.layers.Dense(128, activation=tf.nn.relu),
    # 10ノードのsoftmax層
    keras.layers.Dense(10, activation=tf.nn.softmax)
])

8.モデルのコンパイルをする。

model.compile(
# モデルが見ているデータと、損失関数の値から、どのようにモデルを更新するかを決定
optimizer=tf.keras.optimizers.Adam(),

# 訓練中にモデルがどれくらい正確かを測定します
loss='sparse_categorical_crossentropy',

# 訓練とテストのステップを監視するのに使用します
metrics=['accuracy'])

9.モデルの訓練

モデルは、画像とラベルの対応関係を学習します
model.fit(train_images, train_labels, epochs=5)
Epoch 1/5
60000/60000 [==============================] - 7s 111us/sample - loss: 0.2607 - acc: 0.9261
Epoch 2/5
60000/60000 [==============================] - 6s 105us/sample - loss: 0.1127 - acc: 0.9668
Epoch 3/5
60000/60000 [==============================] - 6s 103us/sample - loss: 0.0763 - acc: 0.9769
Epoch 4/5
60000/60000 [==============================] - 6s 103us/sample - loss: 0.0557 - acc: 0.9832
Epoch 5/5
60000/60000 [==============================] - 6s 104us/sample - loss: 0.0448 - acc: 0.9864

モデルの訓練の進行とともに、損失値と正解率が表示されます。このモデルの場合、訓練用データでは0.98(すなわち98%)の正解率に達します。

10.正解率を評価する。 テスト用データセットに対するモデルの性能を比較します。

test_loss, test_acc = model.evaluate(test_images, test_labels)

print('Test accuracy:', test_acc)
10000/10000 [==============================] - 0s 41us/sample - loss: 0.0717 - acc: 0.9777
Test accuracy: 0.9777

ご覧の通り、テスト用データの正解率は訓練用より少し低い結果でした。これは過学習(over fitting)の一例です。

11.予測する。

predictions = model.predict(test_images)
np.argmax(predictions[0])

今回の予測は合っていることが確認できました。

12.10チャンネル全てをグラフ化する。

def plot_image(i, predictions_array, true_label, img):
  predictions_array, true_label, img = predictions_array[i], true_label[i], img[i]
  plt.grid(False)
  plt.xticks([])
  plt.yticks([])

  plt.imshow(img, cmap=plt.cm.binary)

  predicted_label = np.argmax(predictions_array)
  if predicted_label == true_label:
    color = 'blue'
  else:
    color = 'red'

  plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                100*np.max(predictions_array),
                                class_names[true_label]),
                                color=color)

def plot_value_array(i, predictions_array, true_label):
  predictions_array, true_label = predictions_array[i], true_label[i]
  plt.grid(False)
  plt.xticks([])
  plt.yticks([])
  thisplot = plt.bar(range(10), predictions_array, color="#777777")
  plt.ylim([0, 1])
  predicted_label = np.argmax(predictions_array)

thisplot[predicted_label].set_color('red')
  thisplot[true_label].set_color('blue')

0番目の画像と、予測、予測配列を見てみましょう。

i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions, test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions,  test_labels)
plt.show()

予測確率は100%なので、すべて青で表示されました。
やはり数字に自信満々ですね。(チュートリアルのほうは、Fashion MNISTを使って若干赤かグレーも出てきました。)

13.予測の中のいくつかの画像を、予測値と共に表示する。

# X個のテスト画像、予測されたラベル、正解ラベルを表示します。
# 正しい予測は青で、間違った予測は赤で表示しています。

num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images): 
    plt.subplot(num_rows, 2*num_cols, 2*i+1)
    plot_image(i, predictions, test_labels, test_images)
    plt.subplot(num_rows, 2*num_cols, 2*i+2)
    plot_value_array(i, predictions, test_labels)
plt.show()

図のように、三行目の5の予測率が82%だった以外は、100%です。(これは手書きが悪かったですね)

おわりに

今回は試すことが多かったですが、これから学ぶべきことに気づけました。
例えば...

  • モデルのレイヤーとは。
  • モデルをコンパイルする際に、損失関数、オプティマイザ、メトリクスなどはモデルにどのような影響するのか。
  • ヘルパーライブラリnumpy、matplotlib.pyplotなどの具体的な使い方など。
    実際に扱ってみることで、機械学習に対する怖さはなくなり、今後も様々なモデルで実装していきたいと思います。

参考

Google Colablatory link 
TensorFlow はじめてのニューラルネットワーク:分類問題の初歩


目次

        

はじめに:Fairness in Machine Learningとは

皆さんに質問です。"Fairness(公平性)"とは何でしょう?


では、次の質問です。機械学習や使われるデータは"Fairness(公平性)"が担保されているでしょうか?


題名のFairness in Machine Learningとは『機械学習における公平性』を表しています。


機械学習や統計データと聞くと世間的には『データを使った結果(相関・因果関係、予測モデル) だから信頼できる!』と感じている方も多くいると思います。残念ながら、その考えは正確ではありません。なぜなら、データは『嘘を付くから』です。


加えて、機械学習や統計は完全に"objective(客観的)"だと考えられているかもしれませんが数字で表しても、数学を駆使しても、故意であろうとなかろうと、客観的とは限りません。


2018年アマゾン社(以下、アマゾン)のAI採用を例に見てみましょう(※同社は既にこの採用システムを打ち切っています)。アマゾンはコンピューターに過去の履歴書を学習させ、優秀な人材を採用していました。具体的には点数をつけどの人材がアマゾンにとって最適かの判断を基に採用活動を行いました。


しかしながら、技術関係の職種においてそれまでの多くの応募者(採用者)は男性だったため、AIが女性、もしくは、女性という単語が履歴書に入っているだけで減点の対象になっていました。その結果、数名の女性応募者は選考に落ちてしまいました。


もちろん、アマゾンはこれだけを採用の判断材料とはしていなかったでしょうが、結果としてAIが女性に対して不利な判断を導き出す結果になりました。


以上の例は機械学習における『バイアス』の一部です。データが既にバイアスを含んでいれば、相関関係や予測モデル構築の際にもその影響が出てきます。またデータに含まれるバイアスだけでなく、差別や機械学習モデルの公平性なども予測モデル構築、及び、その解釈に影響します。


この"Fairness in Machine Learning"に関する議論は機械学習技術が注目される前から存在していました。近年、その技術の発展とともに今機械学習界で最もホットなトピックの1つです。今回はそんな注目の話題を、Mehrabi氏達による論文"A Survey on Bias and Fairness in Machine Learning"(2019年9月公表)に基づき説明します。


まず、データにはどのような『バイアス』が含まれている可能性があるのか見ていきましょう。


データとバイアス

bias          

Mehrabi氏達はデータ変数特有の不均一性がバイアスを生じさせる、と述べています。御存知の通り、各データは多種多様な要素・手法を使って集められています。データの多様さに伴い、バイアスにも多くの種類が存在します。


Mehrabi氏達は同論文中にその他の研究を引用し23個ものバイアスの種類を挙げています。全部列挙し、説明すると膨大な量になるためいくつかに絞って紹介します


バイアスの種類

  • Historical bias(歴史的バイアス)

  • この歴史的バイアスはSuresh氏とGuttag氏による論文の中に登場しました。同氏達が最初に挙げた歴史的バイアス、簡潔に言うと、これまでに起こった出来事(歴史)が欲していない結果を生じさせることを意味しています。


    同氏達が例に挙げたのは"crime(犯罪)"です。欠点のない完璧な定義を『犯罪』に与えたとしましょう。そして犯罪率などのデータを分析した際、より貧しい住民ほど犯罪に手を染める、と結果が出たとします。


    結果を視た人は潜在的に『貧しい人は犯罪に手を染める』と考えてしまうようになります。これが歴史的バイアスです。


  • Population bias(人口バイアス)
  •          

    人口バイアスとは対象データが各グループ内においてデータ分布や数などが異なっている状態です。例えば、Hargittai氏は、どんな要素が人々の使用するSNSの種類決定に影響を及ぼしているかについて研究を行いました。


    その結果、人種、民族、若者に至っては両親の教育レベルなどによってSNSのユーザー層が異なると結論付けました(例:若者ユーザーの両親が経済的に豊かであればFacebookを使う傾向がある 等)。


    例えば、絶対的貧困層の需要(社会保障、教育 等)をFacebookを使い調査するとします。しかし、Facebookユーザーにはそれほど貧困に苦しんでいるユーザーはいません。もちろん、相対的貧困に苦しんでいる人々はFacebook上でも存在するでしょう。しかしこの例の調査は"絶対的"貧困層であり、相対的貧困層ではありません。


    したがって、上記のようなFacebook調査でもし仮に十分な数の意見が集まったとしても、それは絶対的な貧困層に対する間違った分析結果を導きかねません。


    このようにデータ分布に偏りがあれば、もちろん、それを使った分析は間違った予測を導き出してしまいます。


  • Cause-effect bias(因果バイアス)
  •          

    因果バイアスとは相関関係と因果関係を一緒だと考えることです。Mester氏はある記事に説明しているように、2つ(ないしはそれ以上)の要素が相関関係にあったとしてもそれらがいつも因果関係には至るとは限りません。


    同氏はECサイトのloyaltyメンバーを例に出しています。Loyaltyメンバーの顧客はLoyaltyメンバーでない顧客の5倍、購買しています。この結果Loyaltyメンバープログラムが成功したと結論づけても問題ないでしょうか?


    Loyaltyメンバーの顧客が同メンバーシップに興味があったのは間違いありませんが、そもそもLoyaltyメンバーになるような顧客はメンバーでなくてもその他の顧客に比べて5倍の金額の消費をしていたかもしれません。


    これ以外にもSocial bias(社会的バイアス)やPopularlity bias(人気バイアス)などその種類は様々です。参考文献からいくつか選んで読んでみてください。


      "Discrimination"(差別)とは?

      discrimination          

      この記事のタイトルは"Fairness in Machine Learning"なので、機械学習における"Fairness"(公平性)とは何なのかを述べなければなりません。


      しかし、当記事の基になっているMehrabi氏達の論文では、先にその対義語である"Discrimination"(差別)について論じています。そのためそれに習いまずはどのような種類の差別があるか見ていきましょう。

      差別の種類

      • Direct discrimination(直接的差別)

      • 直接的差別とは当人がどうしようもない要素によって望ましくない結果(面接や履歴書での不合格など)を受け取る状況です。


        例えば、とても優秀な1人の女性がある会社に従業員として働くために応募するとします。しかしその会社は彼女が女性であるため雇いませんでした。


        このように明らかにその人物には落ち度がない(能力や対人面接能力などに問題がない)にも関わらず、女性であるだけで雇われないのは明確な直接的差別です。


      • Indirect discrimination(非直接的差別)

      • 非直接的差別とは公平性が担保されているような要因が結果として差別を引き起こしている状況です。


        例えば、郵便番号。郵便番号は住所さえあれば誰でも平等に手に入ります。しかしそれは差別を引き起こす可能性を含んでいます。なぜでしょうか?住所によって振り分けられる郵便番号は、言い換えれば、人々が住んでいる地域を判別します。


        周りから疎まれているある特定の人種の人たちがどの地域に住んでいるか判別可能なため、ローンを組む際にその人種には許可を出さないなどもできてしまいます。このように一見、公平に見えるものからの間接的な差別の誘発を非直接的差別といいます。


        他にもSystemic discrimination(構造的差別)、Statistical discrimination(統計的差別)等が存在します。


      "Fairness"(公平性)とは?

      fairness          

      バイアスとは何か、差別とは何かの説明後、Mehrabi氏達はFairness(公平性)について様々な論文を基にまとめています。全部で10個も存在するためいくつか筆者が選んで紹介します。


      Fairness(公平性)の定義

      • Equalized odds(等しい確率)

      • 機械学習モデルによって導き出される答えが、センシティブ属性(人種、国籍、性別 等)による影響を受けない状態です。全員が等しくTrue positiveとFalse positiveの確率を受け取ることを指します。センシティブ属性について当記事では割愛していますが、参考文献からご覧いただけます。


      • Equal opportunity(機会均等)
      •  

        これも1つ目と類似しており、機械学習モデルによって導き出される答えがセンシティブ属性による影響を受けない状態です。全員が等しくTrue positiveの確率を受け取ることを指します。


      • Demographic parity
      •                                           

        センシティブ属性に関わらず、予測される結果(positive outcome)の確率は同じでなければなりません。

              

      この他にも様々な定義があります。ただこれもバイアスの種類と同様、膨大な数が紹介されているので全部は紹介しませんでした。

                             
                             

      まとめると、筆者の解釈は、機械学習モデルによって導き出す答えが個人のステータスやバックグラウンドに左右されない状態をFairness(公平性)だと考えています。


              

      Fairness in Machine Learningがなぜ重要なのか、Mehrabi氏達は論文内で議論しています。Fair(公平)でないデータやモデルを利用すれば、潜在的にある特定の人々が被害を受けるかもしれません。例えば、ある町で貧困に喘ぐ人と窃盗犯罪率が相関関係にあるとします。ここで機械学習において貧困者だから窃盗犯に違いない、もしくは、窃盗犯の確率が高いと結論付けられしてしまえば、そこにはFairness(公平性)は存在しません。


              

      このような問題は人々の潜在的差別意識にも働きかけてしまいます。貧困者=犯罪者と誤認してしまい貧困者に対する差別がより強まるかもしれません。短格的な考えに至ればホームレスに対する殺人を正当化するなど、間違った解釈をしてしまう可能性も否めません。


              

      私たち人が偏見や差別意識を持っているように、機械学習においても同じ問題が起こります。それらを極力防ぐために研究者や機械学習に精通する人以外もデータや予測モデルにおける差別やFairness(公平性)を認識することが重要ではないでしょうか?

      機械学習モデルをどのようにFair(公平)にするか

      fair         

      では、バイアスや差別をなくし、機械学習モデルにおいてFairness(公平性)を実現するにはどうすればよいでしょうか?


      同論文内では3つの方法(段階)が示されています。またこれに伴いMehrabi氏達は基本的な機械学習技術を例示しています。

      Fairness(公平性)のためのデータ処理方法

      • Pre-processing(前処理)

      • 差別がなくなるようにデータを編集します。前処理テクニックの特徴量作成、データ分類、次元削減(PCA)などが当てはまります。下記論文にデータの"Discrimination(差別)"を無くすための方法、その基となるアルゴリズムが書かれています。オープンソースなので興味のある方はぜひ一読してはいかがでしょうか?

        Kamiran and Calders, T. (2012) "Data preprocessing techniques for classification without discrimination"


      • In-processing(処理中)

      • データ処理中において差別を無くすような関数などをモデルに組み込みます。また関数だけでなくデータ分類や適した回帰モデルの使用によってFairness(公平性)の実現に近づきます。


      • Post-processing(後処理)

      • トレーニングデータに関与しないデータセットにのみ行う処理です。最後のpost-processingに関してはあまり意味を理解できませんでした。下記の論文が例のようですが、pre-processingやin-processingとあまり変わらない気も...。

        Hardt, M. *et al*. (2016) "Equality of opportunity in supervised learning"

        Pleiss, G. et al. (2017) "On fairness and calibration"


              

      恐らく、機械学習モデルが割り当てたラベルが適切でない場合の(例えば、カテゴリカル変数であるべきデータが連続変数になってしまっているので適切な変数を割り当てる)処理の仕方だと思います。加えてモデルが出した結果の可視化(visualization)なども含まれるそうで、幅広い意味でモデルが適した結果を出しているか確認する方法のようです。


              

      Mehrabi氏達はこれらの説明をした後、詳細な手法やどのモデルにどの操作を加えるといいかを提案しています。当記事では文字量や複雑さの関係から扱いませんが、興味のある方は同論文に目を通してみてください。25ページほどの論文でかなり読み応えがあります。


      おわりに

              

      "Fairness in Machine Learning"についての議論は機械学習やAIが浸透するに伴い、避けては通れません。


      『機械学習』と聞くと技術の問題やセキュリティの問題などがよく目に付きます。筆者の個人的意見ですが、そこにはデータや機械学習の判断が完璧である、という奢りが存在しているのではないでしょうか?


      データや機械学習を批判しているのではなく、それらはありとあらゆる問題点(注意すべき点)を含んでいると人々が自覚すべきだと考えています。なぜなら、冒頭でも述べたように全てのデータや予測モデルが客観性を担保しているわけではないからです。


      皆さんもこの機会に機械学習とFairness(公平性)について考えてみてはいかがでしょうか?


      参考文献、リンク

      Hardt, M. *et al*. (2016) "Equality of opportunity in supervised learning"

                             

      Kamiran, F. and Calders, T. (2012) "Data preprocessing techniques for classification without discrimination"


      Mehrabi, N. *et al*. (2019) "A survey on bias and fairness in machine learning "


      Pleiss, G. *et al*. (2017) "On fairness and calibration"


      Suresh, H. and Guttag, J. V. (2019) "A framework for understanding unintended consequences of machine learning"


      Statistical bias types explained - part2 (with examples)


      焦点:アマゾンがAI採用打ち切り、「女性差別」の欠陥露呈で



GBDTのひとつ、Catboost

GBDTという手法がKaggleなどでもメジャーなものになってきました。
今回はそんなGBDTライブラリの一つで比較的新しいCatboostについて見ていきます。
Catboostは、ロシア最大手検索エンジンサイトであるYandex社から2017年にリリースされ、11月29日現在v0.20まで公開されています。その革新さをいくつかあげられていたのでそれらをこちらの論文に沿いながら確認していきます。

目次

カテゴリ変数の扱い

勾配バイアスの扱い

決定木選定アルゴリズム

実際に動かしてみた


カテゴリ変数の扱い

前処理

機械学習にあたってカテゴリ変数を扱うときにはそれらを学習させるためにデータの前処理が必要です。
しかし、Catboostではそれらを内部で吸収し、自分で処理してくれます。
たとえば、低カーディナリティ(性別などのように該当する項目が少ない)カテゴリ変数に対してはOne-hotエンコーディングがなされることが一般的です。これは前処理時か、学習を始める際に変換されるものですが、Catboostでは学習時に後述するカテゴリ変数のコンビネーションでも使いうるので前処理をせずにそのまま渡すのが望ましいとされています。
また、ユーザIDのようにカーディナリティの高い変数を扱う際にはそれらの統計量(Target Statistics)を使いますが、これは訓練データの中だけで完結したものであるため、ターゲットリーケージ(target leakage)という過学習の危険性が非常に高いものになります。
そこで、Catboostではランダムにデータを選び、その中から統計量を取るという作業を繰り返し代用値を計算するという手法で対処されています。 具体的に以下の式で代用値が算出されています。
\(x_{\sigma_{p}, k} =\displaystyle\frac{\sum_{j=1}^{p-1}[x_{\sigma {_j}, k}= x_{\sigma _{p} , k}] Y_{\sigma j} + a \cdot P}{\sum_{j=1}^{p-1} [x_{\sigma _{j }, k} = x_{\sigma _{p} , k}] + a}\)

ここで、データセット{\({X_i, Y_i}\)}とし, \(X_i\)は\((x_{i, 1},...x_{i, m}\))のm次元ベクトルで表され、σは順列(どのデータを取るかの集合)、Pを重要度、aをPの重みとして計算されています。
重要度を足すのは頻度の低いカテゴリから生じるノイズを減らすことを目的としていて、回帰問題ではデータセットのラベル値の平均、二値クラス分類問題では真の先験的遭遇確率(True a priori distribution)がよく用いられます。
ここでの統計量の算定の仕方にもランダム性を用いることは、過学習回避に有効です。

カテゴリ変数のコンビネーション

Catboostでは、統計量を使った過学習回避としてもう1つカテゴリ変数を組み合わせる、新奇な手法で対処しています。
たとえば、音楽のレコメンド機能で、ユーザIDと、そのユーザが好きなジャンルという2つのカテゴリ変数があるとします。あるユーザーがロックを好んでいるというデータがあるときに、この2つを上述の代用値に置き換えると、この新しい代用値群は、新たな変数として過学習を気にすることなく使うことができるようになります。
しかしこのカテゴリ変数の組み合わせは、カテゴリ変数が多ければ多いほど指数関数的にその数を増します。
全てを考慮することはまだできないため、新たな木構造を生成する際に最初の枝に対しては組み合わせを考えず、それ以降について組み合わせを適用することである程度貪欲にそして正確性を保った結果が保証されています。
CatBoost

勾配バイアスの扱い

GBDTライブラリでは、新しい木を生成する際に、現在の木から、そして同じデータセットから勾配近似値を求めるため、真の確率分布と予測勾配値の確率分布の差異でを生むPrediction shiftという危険性を抱えています。
もう少し詳しくこの木を作る過程を見ていきます。
まず、どんな構造の木を使うかを選定し、それが決まったら葉に値を入れていきます。どの構造を使うかは、アルゴリズムが様々な種類を列挙し、それらに点数付けをして最良のものを選びます。ここで葉の値は勾配の近似値あるいはニュートン法によって一般的に計算されています。
この木の構造選定に際して起こるprediction shiftに対処するためにCatboostではOrdered Boostingという手法を取っています。Ordered Boostingは前回のブースティング段階で毎回新たなデータセットを個別にサンプリングして木を作っていきます。
毎回新たなデータセットを使うというのは限られたデータの中では不可能に思われますが、上述のカテゴリ変数のコンビネーションによってその数を確保することに成功しています。

決定木の選定アルゴリズム

Catboostでは、予測をOblivious Decision Treesを用いて行われています。
ここでObliviousは、全ての木で同様の分岐基準を使われていることを示しています。この木構造は均衡が取れていて過学習をしづらく、また後述する性質上実行速度が高速という特徴を持っています。
Oblivious Treesではそれぞれの葉のインデックスは深さと一致する2値ベクトルで表されます。モデル予測の際には、様々な数値データをバイナリ特徴量に変換して計算をします。
全てのベクトル特徴量は連続ベクトルBに保管され、葉の値は大きさ\(2^d\)(dは葉の深さ)のベクトルで保管されます。

実際に動かしてみた

実際のデータを用いたベンチマークが、公式のGithubにあります。
実行時のスコアから見ていきます。

Score


Default CatBoost Tuned CatBoost Default LightGBM Tuned LightGBM Default XGBoost Tuned XGBoost Default H2O Tuned H2O
Adult 0.272978 (±0.0004) (+1.20%) 0.269741 (±0.0001) 0.287165 (±0.0000) (+6.46%) 0.276018 (±0.0003) (+2.33%) 0.280087 (±0.0000) (+3.84%) 0.275423 (±0.0002) (+2.11%) 0.276066 (±0.0000) (+2.35%) 0.275104 (±0.0003) (+1.99%)
Amazon 0.138114 (±0.0004) (+0.29%) 0.137720 (±0.0005) 0.167159 (±0.0000) (+21.38%) 0.163600 (±0.0002) (+18.79%) 0.165365 (±0.0000) (+20.07%) 0.163271 (±0.0001) (+18.55%) 0.169497 (±0.0000) (+23.07%) 0.162641 (±0.0001) (+18.09%)
Appet 0.071382 (±0.0002) (-0.18%) 0.071511 (±0.0001) 0.074823 (±0.0000) (+4.63%) 0.071795 (±0.0001) (+0.40%) 0.074659 (±0.0000) (+4.40%) 0.071760 (±0.0000) (+0.35%) 0.073554 (±0.0000) (+2.86%) 0.072457 (±0.0002) (+1.32%)
Click 0.391116 (±0.0001) (+0.05%) 0.390902 (±0.0001) 0.397491 (±0.0000) (+1.69%) 0.396328 (±0.0001) (+1.39%) 0.397638 (±0.0000) (+1.72%) 0.396242 (±0.0000) (+1.37%) 0.397853 (±0.0000) (+1.78%) 0.397595 (±0.0001) (+1.71%)
Internet 0.220206 (±0.0005) (+5.49%) 0.208748 (±0.0011) 0.236269 (±0.0000) (+13.18%) 0.223154 (±0.0005) (+6.90%) 0.234678 (±0.0000) (+12.42%) 0.225323 (±0.0002) (+7.94%) 0.240228 (±0.0000) (+15.08%) 0.222091 (±0.0005) (+6.39%)
Kdd98 0.194794 (±0.0001) (+0.06%) 0.194668 (±0.0001) 0.198369 (±0.0000) (+1.90%) 0.195759 (±0.0001) (+0.56%) 0.197949 (±0.0000) (+1.69%) 0.195677 (±0.0000) (+0.52%) 0.196075 (±0.0000) (+0.72%) 0.195395 (±0.0000) (+0.37%)
Kddchurn 0.231935 (±0.0004) (+0.28%) 0.231289 (±0.0002) 0.235649 (±0.0000) (+1.88%) 0.232049 (±0.0001) (+0.33%) 0.233693 (±0.0000) (+1.04%) 0.233123 (±0.0001) (+0.79%) 0.232874 (±0.0000) (+0.68%) 0.232752 (±0.0000) (+0.63%)
Kick 0.284912 (±0.0003) (+0.04%) 0.284793 (±0.0002) 0.298774 (±0.0000) (+4.91%) 0.295660 (±0.0000) (+3.82%) 0.298161 (±0.0000) (+4.69%) 0.294647 (±0.0000) (+3.46%) 0.296355 (±0.0000) (+4.06%) 0.294814 (±0.0003) (+3.52%)
Upsel 0.166742 (±0.0002) (+0.37%) 0.166128 (±0.0002) 0.171071 (±0.0000) (+2.98%) 0.166818 (±0.0000) (+0.42%) 0.168732 (±0.0000) (+1.57%) 0.166322 (±0.0001) (+0.12%) 0.169807 (±0.0000) (+2.21%) 0.168241 (±0.0001) (+1.27%)

全ての結果でcatboostが1番良いスコアをマークしています(Log lossのため低いほどよい)。
また、ほぼ全ての結果においてcatboostのデフォルト値を用いた結果が、チューニング後の他ライブラリより高い結果となっています。

モデル評価時間

ライブラリ 所要時間
XGBoost 32Thread 4.89 s ± 223 ms per loop (mean ± std. dev. of 5 runs, 1 loop each)
LightGBM 32Thread 11.1 s ± 402 ms per loop (mean ± std. dev. of 5 runs, 1 loop each)
Catboost 32Thread 184 ms ± 806 µs per loop (mean ± std. dev. of 5 runs, 1 loop each)

こちらも他を圧倒しています。

モデル作成時間

test size catboost lightgbm xgboost
1000 0.069 0.002 0.011
5000 0.349 0.001 0.047
10000 0.770 0.001 0.089

初めてcatboostが遅れをとる結果になりました。 しかも相当のビハインドがあります。
これらのベンチマークは2年前のもので、Python2で書かれたものなので一概にこの結果が正しいと言えるかはわかりません。
そこでAmazonデータセットに対してデフォルト値で比較してみました。詳しいコードは以下を参照してください。


ライブラリ モデル作成時間時間 スコア
XGBoost 1.805s 0.7452
LightGBM 0.6343s 0.8326
Catboost 149.301s 0.8845

Catboostが圧倒的に時間がかかっているのがわかります。

まとめ

特段のチューニングなしでもかなり良い結果を得られるライブラリでした。
しかし、Catboostを使う際には適切なパラメータチューニングの上で相応のマシンスペックと時間の確保が必要になりそうです。
12/8から行われるneurIPSにも論文が出されるそうなので、そこでの発表も楽しみです。

参考文献

CatBoost: unbiased boosting with categorical features

CatBoost: gradient boosting with categorical features support

Mastering The New Generation of Gradient Boosting

CatBoost Document

LightGBM Document

XGBoost Document

Catboost Benchmarks


Twitter・Facebookで定期的に情報発信しています!

もくじ

機械学習の概要

  機械学習とは与えられたデータからデータに潜む規則性を自動的に発見し、データの分類や未知のデータの予測をコンピュータの計算手法を利用して行うことである。データから予測を行うとき、扱うデータによっては膨大な規則を用いたり、人力では見つけることの難しい規則が存在したりするので、人間だけでは予測が困難な場合があるが、それをコンピュータの計算に落とし込むことで予測が容易になる。機械学習を用いてデータの予測を可能にすることよって、以下の例のように私達の生活の中で大きな役割を果たしているのである。

  • 工場の製造ラインでの不良品検出
  • 株価の予測
  • ECサイトでのレコメンド機能

人工知能と機械学習の違い

 機械学習と並べて話題に出されるものとして、人工知能が挙げられる。人工知能とは人間が行っている言語理解や推論、問題解決などの知的な活動をコンピュータに行わせる技術である。人工知能と機械学習は、一見すると同じようなものに聞こえる。しかし、機械学習はある特定の分野においてデータに基づいて予測の結論を下すため、人工知能における人間の知的な活動のすべてを網羅しているわけではない。つまり、人工知能の一つのトピックとして機械学習が位置づけられる。 AIと機械学習の関係性

機械学習の種類

機械学習は主に以下の3種類に大別される。

  1. 教師あり学習
    教師あり学習とは予測するものの正解が分かっているデータに対して未知のデータの予測をする機械学習である。教師あり学習の中にはデータをカテゴリ別に分ける決定境界を引く分類と、カテゴリではなく、入力のデータからどのような値をとるか予測する回帰モデルを求める回帰の2種類の方法が存在する。工場の生産ラインで、部品の形状などから不良品かどうか判別するのは分類であり、今までの株価の変動から将来の株価を予測するのは回帰だと言える。 教師あり画像

  2. 教師なし学習
    教師あり学習に対して、教師なし学習正解の無いデータから情報を見つけることを目的とする機械学習である。教師なし学習はデータのみからグループ分け(クラスタリングなど)やデータの次元縮減(例えば、空間上の3次元のデータを平面上の2次元のデータとして写すなど)をすることで、データの隠れた構造を見つけ出す手法と言える。ECサイトでの顧客の購買行動から、一緒に買われているものを見つけ出して提案するレコメンドは教師なし学習である。

  3. 強化学習
    強化学習エージェントと呼ばれるシステムと環境とがやり取りをすることで行われる機械学習である。エージェントは何かしらの行動をすることによって環境から報酬を得ることができ、この報酬が最大になるように自身のシステムを改善していく 。ラベルや値などの決まった正解は無いが、エージェントの行動の出来を数値化して学習を進めていく。 強化学習

機械学習のプロセス

 ここで、機械学習がどのようなプロセスで予測まで行われるのか説明する。

  1. データの収集
    まず必要なのはデータの収集である。当然、データから何かを予測するためにはそのためのデータを集計しなければならない。
  2. データの前処理
    ほとんどの場合、実際に学習を始める前に、データに対して前処理を行っておく。機械学習を行う上では予測に必要な情報だけを抽出しておくことで、この後の学習の段階でコンピュータが行う計算を簡潔にすることができる。例えば用いるデータが画像ならば、画像のサイズの拡大や縮小、回転などすることで前処理を行う。 機械学習では予測したい情報に対して、それを特徴づける他の情報を特徴量と呼ぶ。そのため、前処理のことを特徴抽出と呼ぶこともある。
  3. 学習
    前処理によって抽出した特徴量を用いて学習を行う。予測したい情報に合わせて予測に用いる計算手法を選び、その後データを入力して結果を出力する規則算出する。この規則を作るために用いる計算手法やルールをモデルと呼び、ここで用いられるデータは訓練データと呼ばれる。この学習のモデルをどう構築するかによって予測の精度が大きく変わってくる。
  4. 精度の評価
    学習したモデルに対してどのぐらいの精度で予測が成功しているのか評価する必要がある。そのため先程学習で使った訓練データとは別に、テストデータを用いて精度を測定する。これによって、学習に用いてないデータに対しても良い精度が出ているか(汎化という)を確認する。精度が悪ければ、もう一度モデルの構築や場合によってはデータの収集に戻って学習を繰り返す。
  5. 未知のデータに対して予測
    良い精度のモデルが得られたのならば、それを用いて新たに得られる未知のデータに対して予測が行うことができる。

機械学習のこれからの発展

冒頭で示した例から分かる通り、機械学習は今もなお研究され続けられている分野であり、また今後も発展していく分野であることが分かる。最近ではPythonやRなどのデータサイエンスの分野で用いられることの多いプログラミング言語に便利なライブラリが用意されている。特にPythonは多次元配列の高速なベクトル演算を可能にするNumPyや、機械学習ライブラリとしてscikit-learn などを用いることで、オープンソースのライブラリを使って簡単に機械学習のプログラムを実装することができる。他にも表形式のデータ操作を可能にするpandasやデータの可視化を実現するmatplotlibも存在し、Pythonのライブラリの発展とともに、高度な機械学習プログラミングが可能となっていく。

まとめ

今回の記事では以下のことを述べた。

  • 機械学習の簡単な説明
  • 人工知能と機械学習の違い
  • 機械学習の3つの分類である教師あり学習、教師なし学習、強化学習について
  • 機械学習とPythonのライブラリの発展

機械学習は人間では困難な膨大なデータからの予測を可能にし、私達の生活の中で重要な役割を担っている。また研究がされていくことで、より機械学習が発展していきよりよいサービスが創造されていくに違いない。

「機械学習」


耳にすることが多くなった単語ですが、そもそも機械学習ってなんでしょうか。
AI(人工知能)との違いは?なにが出来てなにが出来ないのでしょうか?


本日は上記を解説し、実際に活用されている事例をご紹介します。


機械学習とは

機械学習はAIの1つの要素です。
AIの中に機械学習があり、機械学習にディープラーニング(深層学習)があります。


機械学習とは...

  • 大量のデータの特徴や法則を捉え、未知のデータを予測・分類する。
  • 分析の精度は100%ではないが向上させることができる。
  • 目的に応じて手法を使い分ける必要がある。


機械学習ができないこと

  • 企画立案などの新しいアイデアを生み出すこと
  • 喜怒哀楽を感じたり、自発的に考えること


機械学習が得意なこと

  • 同じ作業を繰り返しおこなうこと
  • 過去のデータを正しく学習すること
  • 大量のデータを分析すること
  • 人間がおこなうと時間がかかる膨大なデータを扱うこと


機械学習の分類と活用例

『機械学習が得意なこと』を分類し、ビジネスでの活用例を紹介します。


(1)「同じ作業を繰り返しおこなうこと」...作業を黙々とミスなくやってくれる「働き者」タイプ
 作業を確実にミスなく実施し、新たな労働力として人間を助けます。
人間がおこなっていた簡易な業務と代わることができるため、労働人口の減少や長時間労働の削減の問題の解決に役立ちます。
空いた時間を、利益を生むための営業活動や、さらに労働環境を良くするための検討時間に替えることができ、生産性の向上を後押しします。


▼活用例 機械学習事例

・無人レジ
レジで商品画像を読み取ると金額が算出されます。レジでの混雑緩和や人件費の削減に効果的です。
当社でも開発中で、下のアイコンから検討状況を確認できます。


(2)「過去のデータを正しく学習すること」...熟練者の技術を習得する「熟練社員」
 人員確保の困難や、少子高齢化における熟練者の大量退職によって、知の継承が懸念されている分野において、熟練者が保有している技術を再現できます。
技術、ノウハウの再現性を高めることで、退職への対応だけでなく、新人教育にも活用できます。


▼活用例
機械学習事例

・不良品検知/異常検知
 機械学習で画像や、振動、音などの信号などの違いを認識し、良品と不良品(または良品と差が大きい物)、正常と異常(または正常と差が大きいもの)を識別します。
・コールセンター問い合わせ業務
熟練者の回答や対応を、機械に学習させ、いつでも引き出せるようにすることで、顧客対応レベルを全体的に向上させます。

不良品検知


(3)「大量のデータを分析すること」...データを即時に読んで判断する「聖徳太子」
 人手を要し人間が苦手とする大量の情報、ビッグデータの分析をおこないます。


▼活用例 機械学習事例

・リーガル分析
 訴訟事案は毎年どんどん増え、大量のデータになります。六法全書や過去の訴訟事案のデータに検索タグ付けをおこない、自然言語処理を使い検索し、役立つ情報を瞬時に取り出し分析する、言わば「AI弁護士」、「AI裁判官」の役割をします。
   


(4)「人間がおこなうと時間がかかる膨大なデータを扱うこと」...人間にできなかったことをやってくれる「天才社員」
 予測や最適化など人間では実施に時間がかかり、且つ、担当が限られる業務をおこないます。人間では扱うことが難しい膨大なデータも機械学習で扱えます。


▼活用例 機械学習とは

・創薬
 新薬の開発には膨大な時間とお金がかかっています。それは病気に適合する物質(リード化合物)を発見するまでに、試行錯誤に途方も無い時間がかかっていることが原因の一つです機械学習を用いて過去の事例から適合度の高いリード化合物の構造式を探すことで、適合度の高いアタリを発見するまでの時間を削減します。このようにリード化合物を最適化するまでのサイクルを短くすることで、コスト削減をも実現します。


機械学習のこれから

 近年、少子高齢化による労働人口の減少や労働時間の削減などによって、十分な労働力の確保や業務効率化による生産性向上が課題になっている。


「機械学習」と「AI」。
どちらも単に「計算処理の早いコンピュータ」ではなく、「人間のようなコンピュータ」といった感覚のもので、人間の代わりに24時間働いてくれたり、作業をミスなく実施したり、人間には不可能なことを実現します。


 機械学習は既に研究段階から実用化の段階に進み、あらゆる産業に変化をもたらしています。これから更に機械学習は世の中を豊かにする技術として受け入れられ、運用されていくため、今後は機械学習をどのくらい活用できるかが、社会やビジネスの発展に直接影響することも考えられます。

  「機械学習は人間の仕事を奪う」


という意見もありますが、「機械学習ができないこと」で挙げたように、企画立案や戦略を立てることは人間の仕事です。人間による戦略や企画に機械学習を活用する、といった役割分担になっていくでしょう。
そのため「人間 VS 機械学習」ではなく、「人間 with 機械学習」で発展していくと予想されます。


本記事でご覧いただいたように、AI・機械学習は幅広い活用方法があり、お客様ごとの活用方法が必要です。
当社ではみなさまの課題やお困り事を一緒に解決していきます。
下記にご興味がありましたら、問い合わせ口からご連絡ください。

  • AI・機械学習の導入を考えている
  • 活用事例についてもっと詳しく知りたい
  • 他になにが出来るのか興味がある


当社、アクセルユニバースの紹介

私達はビジョンに『社会生活を豊かにさせるサービスを提供する。』ことを掲げ、このビジョンを通して世界を笑顔にしようと機械学習・深層学習を提案しています。
例えば、現在人がおこなっている作業をシステムが代わることで、人はより生産性の高い業務に携わることができます。


acceluniverse


参考文献

・梅田 弘之『エンジニアなら知っておきたいAIのキホン 機械学習・統計学・アルゴリズムをやさしく解説』インプレス、2019年
・南野 充則『未来IT図解 これからのディープラーニングビジネス』MdN、2019年


Twitter・Facebookで定期的に情報発信しています!

アクセルユニバース株式会社(以下 当社)では『機械学習・深層学習で世界を笑顔にする』を掲げ、人が対応している業務を画像認識、音声認識、文字認識等を活用して効率化する機械学習ソリューション開発をおこなっています。

今日は世界を笑顔にしたい私が
「ドラえもんのひみつ道具があれば、みんな笑顔になるのではないか!?」
と機械学習を活用してひみつ道具の実現を考えてみました。


目次

  • ひみつ道具の検討
  • 実現したいこと
  • 結果と今後


ひみつ道具の検討

ずばり、今回実現を検討したいひみつ道具は「ムードもりあげ楽団」です。 ひみつ道具の実現
出典:ドラえもんのひみつ道具を一つもらえるとしたら
人の気分を盛り上げる楽団ロボット。その時の気分によって楽曲を演奏してくれます。
人は嬉しい時には楽しい音楽、悲しい時には悲しい音楽が聴きたくなるものです。
今回は人の声から感情を判定し、適切な音楽が流れる仕組みを検討します!


実現したいこと

人間の発した音声からその時の感情を判定し、適切な音楽が流れる仕組みです。
ひみつ道具の実現
実現するために、システムが人の発語を聞き取り感情を分析し、予め決めておいた感情群に判定します。そして判定された感情によって異なる音楽が流れることが必要です。
今回は機械学習の範囲の、感情分析〜判定を考えていきましょう。感情の変化は音声の韻律特徴に表れるので、韻律特徴により4つの感情[喜び/悲しみ/怒り/フラット]に分類します。
いくつか文献を読んでこのように計画しました。文献は最後に紹介します。

ひみつ道具の実現

データの準備
複数の人から発声データを集め、音の高さ・強さを時系列データにし、適当な長さに分割する。
学習データ : 話者と面識のある人が音声データを聴き、感情を判定(ラベル付け)し、分割する。

モデル
SVM(Support Vector Machine)
未学習データに対する高い汎化性能があり、高い認識性能が認められている。
SVMについて当社ブログ/最初に学ぶ 2分類SVMモデルの基本

評価
交差検証法(クロスバリデーション)
膨大なデータを用意することが難しく、また人の声のため学習にムラがあるかも、と懸念し汎化を高めるために、全てを学習データとして扱う本法を挙げる。
少し計算に時間がかかるかも...。


結果と今後

今回は計画だけで実装はしていませんが、愛知工業大学での結果は精度60%程度で判定できています。
「短時間発話からの音声感情認識のための音声データ選択法に関する検討」
音声データを短く切ることで、特徴として捉える範囲が減り、似たグラフの動きを誤判定してしまうようで若干精度が低下しているようです。
別の研究だと、音声データだけではなく、表情も感情判定に使用し、こちらは精度68%〜70%と結果が出ています。
また、一度判定させたものに結果をフィードバックすることでさらなる精度向上も見込めると思います。


どうやら実現可能性は多いにありそうなので社内でウケが良ければ実装に向けて進めていきます!
ドラえもんひみつ道具シリーズはシリーズ化したいので面白いひみつ道具やお気に入りがあれば是非コメントください。


当社ではインターン生が取り組んでいることを技術ブログで紹介しています。
文系学部2年生の私が「SIGNATE」初参加で上位8%に入った話論文 Attention Is All You Need から Attentionモデルの解説等が公開されています。
定期的にメルマガでも情報配信予定なので、問い合わせページに「メルマガ登録希望」とご連絡ください。


参考

平井有三:"初めてのパターン認識"森北出版 2012
小野谷信一 長屋優子 : "表情と音声を用いたサポートベクタマシンによる感情認識"2014
短時間発話からの音声感情認識のための音声データ選択法に関する検討
SVMを用いた自発対話音声の感情認識における学習データの検討

はじめに

現代社会には、音楽というものが氾濫しています。
そして多くの人は音楽を聞くというと、生演奏されているものを聞くことよりもCDやサブスク型サービスなど、一度デジタルなデータになったものをアナログデータへ変換して視聴することの方がよっぽど多いでしょう。 このデータ化によって普段聞いているだけでは気づかないような、特徴、性質に目を向け、そういった見えなかったデータを使い既存のものをもっと充実させる、新しいものを作り出すことはできないでしょうか。 この記事ではそういった取り組みや手法の一端を紹介できればと思います。

目次

MIRとは

特徴量

機械学習x音楽の実用例

参考文献

MIRの現状

こういった音データ(特に音楽)から情報を抽出、分析する分野は、MIR(Music Information Retrieval)と呼ばれています。 ISMIRという世界規模のMIRに関する研究が発表される学会があり、2019年は20周年という大きな区切りの年でした。しかし、そこで発表された論文の一つの中で法的制限によって研究が進めづらく、また大企業とそれ以外とで資金面の違いから多様な研究が阻害されることによる再現性の危機等が指摘されています。 また、日本のGoogleで2019年11月現在MIRでと検索しても1ページ目に音楽分野のMIRの記事は出てこなく、あまり広く普及しているとはいえないのが現状でしょう。(MIRという略語が他にも多く当てられているということもありますが・・)

特徴量

このブログは技術ブログなので実際に使われている特徴量(データを扱う際にデータの特性を数値にしたもの)、またその抽出に関していくつか紹介していきます。 ここでは例としてヴィヴァルディの四季から春の第1楽章と冬の第2楽章のデータを扱っていきます。
Spring
scenary-spring.jpg

Winter
winter-image
spring.png winter.png

下グラフは、それぞれの信号をサンプリング間隔(sr=22050)でグラフ化したものです。 春は振れ幅が大きいところと小さいところがはっきりと分かれているのがわかります。 一方、冬は全体的に振れ幅が小さく、また曲自体も穏やかな印象を受けます。

1.平均平方2乗エネルギー(Root Means Square Energy)

EがErrorではなくEnergyなので読むときに注意が必要な値。単にRMSと書いている場合もあります。 表すものは単純にその音楽がどのくらいのエネルギー(音の大きさ)をもっているかをあらわし、下記スペクトル流動と相性が良いとされています。 オリジナルの波とそのまま比べると大きさだと見比べづらいので、0-6秒までをプロットします。 spring-rmse おおよそオリジナルの波と同じ形を描いています。 エネルギーが大きいところは、激しいと読み替えることができるように思えます。しかし、その考え方でこの特徴量を利用すると大きな落とし穴があります。 春のヴァイオリンソロ部分(1:57〜)は、オリジナルの波を見てみると、振れ幅が小さくなっています。 しかし、だからといって穏やかなわけではありません。しかし、rmseを使うと、ソロパートなど、合奏に比べ音量が負けやすいところは数値が小さくでてしまいます。 結局、この特徴量はどれだけ音が大きいかということしかわかりません。

2.ゼロ交差率(Zero Crossing Rate)

音の波が正から負に変化する頻度を表した数値で、ノイズ量(不安定さ)を表す一つの手法とされています。 オリジナルのグラフは、波が潰れてしまっているので拡大して見てみます。 spring-extended Springの1秒からsr=300まで(約0.01秒)ののグラフです。 波が単純でないので分かりづらいですが、この区間の場合だとZCR=8となります。 しかし、高音は元々波の間隔が狭いため、高音が多い曲では適切に動作しません。

3.短時間フーリエ変換(Short Time Fourier Transform: STFT)

曲によって演奏時間は違い、それらの異なる長さのデータを扱うために、一定の時間(短時間)に対して離散フーリエ変換(一般的に高速フーリエ変換)を行い、それを繰り返すことによって、どのように曲が展開されているかを知る手法です。 フーリエ変換の概要については、省略しますが、簡単に言うと、オリジナルのグラフのように振れ幅(正確には無次元量)と時間軸で表されているものを、一定の時間内に、どのくらいの強さの振動がどのくらいあるかに変換する手法です。 STFTによって求められる周波数スペクトル(どの周波数の音がどれくらいあるか)を用いて下で紹介するようなMSCCなどへと発展できます。
spring-stft winter-stft

4.定Q変換(Constant-Q Transform)

STFTでは扱う時間を増やすと多くの周波数を含むことができる可能性があるため一般に周波数分解能は高くなりますが、時間間隔が長いためにその中で起こっている変化をとらえにくくなるというジレンマを抱えています。 定Q変換では、この問題に対応するために分析する周波数間隔を人間の耳が感じているとされているように対数的に設定します。 つまり、人間の耳と同じように特定の周波数(低域)に対しては敏感に分析し、そうでないところ(高域)は荒く分析対応するのが、定Q変換の考え方です。 これによって効率よく必要なデータ分析が行なえます。
spring-conq winter-conq
上記フーリエ変換後のスペクトログラムに比べ人間の耳に聞こえやすい音域が強調され広がっているのがわかります。 C4はト音記号の一番低いド(普通のド)で、 約261.626Hzとされていて、オクターブ上がるごとに約倍音(平均律のため誤差が生じる)になります。

5.ログメルスペクトログラム(Log-melspectrogram)

単にメルスペクトログラムと言われていることもあります。 上記1や2(1が主流)で得られた振幅スペクトルをメル尺度(実際の音と人間の音高知覚の差異を吸収したもの)で扱うためにメルフィルターバンクを適応たものです。
spring-log-mel winter-log-mel
前提となる考え方が定Qと同じく人間の耳に適応させた特徴量を作り出すことを目的としているためスペクトログラムは似ていますが、低域に対してブーストされていないため、定Qを下にずらした形となっているのがわかります。

6.メル頻度ケプストラム係数(Mel Frequency Cepstrum Coefficients: MFCC)

ケプストラム(Cepstrum)はスペクトル(Spectrum)の最初の4文字をひっくり返した造語とのことで、スペクトル信号をフーリエ変換した結果であるそうです。 上記3の値を離散コサイン変換し、その値の低次元成分部分で構成されています。 また、この値はもともと喋り声などのデータに使われていた特徴量で、離散コサイン変換の段階で空間的特性を削除するため、ディープラーニングの際に適さないのではないかという主張もあります。
spring-mfcc winter-mfcc
たしかに、定Qやログメルと比べると変化のある面積が少なくなっています。

機械学習×音楽の実用例

ずらずらといくつか紹介しましたが、一体これらの値を用いてどういったことができるのでしょうか。 例えば、今音楽を聞く手段として、ひとつの主流な形になっているものとしてサブスクライブ型サービスがあります。 定額で契約期間中数千万曲の中から好きなだけ好きなものを聞けるという画期的なサービスです。 しかし、やはりこれだけの曲数があると何を聞くか迷い結局同じ曲を聞くにとどまることが多いでしょう。 そこで各社は、様々な方法でレコメンド機能を実装しています。多くは、その曲を聞いた他の多くのユーザーがよく聞いている曲が選ばれています(協調フィルタリング)。しかし、これでは話題の曲など普段そういった曲を聞かないような人も聞いている曲では正しいおすすめはできないでしょう。 音楽サブスクライブ配信大手のSpotifyではこれに加え、音声データを用いた学習を活用しています。純粋にその曲に似ている、同じ雰囲気の曲を探しだし、Discover Weeklyで他社に先んじた高精度のレコメンド機能を提供しています。 また、今年の3月にgoogleが適当に音を数個与えるとそれに対して和音を足して"バッハっぽい音楽"を作り出すというシステムを発表しました。 このように機械学習は、既存のものを踏襲しつつ新たなものを発見したり生み出すことができ、今まで気が付かなかった可能性にも気づかせてくれるのです。


定期的にメルマガでも情報配信をしています。
ご希望の方は問い合わせページに「メルマガ登録希望」とご連絡ください。

参考文献、使用音源

  • (Anniversary paper) Data Usage in MIR: History & Future Recommendations
  • Notes on Music Information Retrieval
  • [Python]ただひたすらにフーリエ変換[備忘録]
  • MFCC(メル周波数ケプストラム係数)入門
  • LibROSA Document
  • [Python] Constant-Q 変換(対数周波数スペクトログラム)
  • Deep Learning for Audio Signal Processing
  • JSYMBOLIC 2.2: EXTRACTING FEATURES FROM SYMBOLIC MUSIC FOR USE IN MUSICOLOGICAL AND MIR RESEARCH
  • COMPOSER RECOGNITION VASED ON 2D-FILTERED PIANO-ROLLS
  • Spotify's Recommendation Engine
  • Googleが機械学習で誰でもバッハっぽく作曲できるGoogle Doodleを公開中

  • The Four Seasons(Vivaldi) by John Harrison with the Wichita State University Chamber https://freemusicarchive.org/music/JohnHarrisonwiththeWichitaStateUniversityChamberPlayers/TheFourSeasons_Vivaldi 協奏曲第1番ホ長調 RV 269「春」(La Primavera)第1楽章 協奏曲第4番ヘ短調 RV 297「冬」(L'Inverno)  第2楽章

    この記事では、3ヶ月前までデータサイエンスと無縁だった私が、
    マイナビの家賃予測コンペで上位8%(スコア14953)に達した解法について紹介したいと思います。

    始めまして、 アクセルユニバース株式会社、インターンの土井です。

    SIGNATE SIGNATE

    ここで紹介するSIGNATEの解法は、私が始めて間もないこともあり、シンプルな解法ばかりです。
    幅広いレベルの方の参考になれると思います。


    コンペの概要

    SIGNATE https://signate.jp/competitions/182


    東京23区における賃貸物件の家賃予測が目的です。
    少ないカラムに多くの情報が詰められており、このままでは有効にモデルを適用することができません。
    丁寧に各カラムの前処理を行い、いかに有効な特徴量を作り出すかがこのコンペの肝です。


    目的

    私がこのコンペに参加した理由は以下の通りです。

    • SIGNATE(Kaggle)の流れを理解したい
    • 短期間で実績を残したい
    • 上位者発表会でスカウトされたい


    以下がその結果です。

    • pythonの基礎文法が書けるようになった
    • SIGNATE(Kaggle)の全体の流れを把握した
    • データサイエンス、プログラミングが楽しくなった


    残念ながら発表会に参加できる順位に達しませんでしたが、短期間で成長できる素晴らしい経験でした。
    ここからは、上位8%に達するための具体的な解法を時系列に沿って10月1日から解説していきます。


    SIGNATE SIGNATE


    前処理

    実はこの期間、スコアが全く上がりませんでした。

    SIGNATE SIGNATE

    下位20%くらいだったような。 スコアが上がらない原因がわからず、3週間ひたすら前処理を行います。

    この期間の終盤の頃は、前処理をもう一度やり直してみたり、綺麗に書き直してみたりと、 スコアに関係のないことばかりをしていました。(おかげでコーディング力は爆上がり)

    使っていたモデルはRandom Forestで、モデルに関する知識が無かったためパラメータは全てデフォルトです。


    モデル作成

    スコアが上がらず悩んでいたときに、運命の出会いがありました。

    Lightgbm

    テーブルデータコンペではLightgbmが強いという情報があったので、
    モデルをLightgbmに変え、パラメータもkaggleのnotebookを参考に調整しました。

    そしてモデルを回してみると、

    SIGNATE SIGNATE


    ・・・・・・・???? 前処理をひたすらしていた3週間を嘲笑うかのようにスコアが上がりました。

    この時点ではほとんど特徴量エンジニアリングはしていません。
    Lightgbmの破壊力、恐るべしです。


    特徴量エンジニアリング part1

    ようやく前処理が終わったので、本格的な特徴量エンジニアリングのステップに入ります。
    主に以下のような特徴量エンジニアリングを行いました。

    • 数値変数×カテゴリ変数
    • 数値変数×数値変数
    • TargetEncoding


    数値変数×カテゴリ変数

    数値変数同士を組み合わせた特徴量生成は思いつきやすいのですが、カテゴリ変数と組み合わせた特徴量も実は強力です。
    例として、各カテゴリごとに対する数値変数の平均や標準偏差を計算し、特徴量にします。

    SIGNATE SIGNATE

    0行目の「Breadthtomeanmoyoristation」が「0.590665」というのは、
    西巣鴨駅の近くにあるこの賃貸は、西巣鴨駅の賃貸の平均の面積の0.59倍であることを示しています。
    このように、周辺の賃貸と比較した面積の大小を表しています。

    他にも色々な組み合わせが考えられます。

    • 部屋の面積×住所
    • 部屋の面積×部屋の間取り
    • 部屋の階数×最寄り駅


    数値変数×数値変数

    これは、2つの数値変数を乗除することで新たな変数を生み出します。
    その例として、以下のカラムをつくりました。

    • 部屋の広さと部屋の間取りで一部屋あたりの面積を求める
    • 賃貸の面積 * 階数を計算する


    TargetEncoding

    TargetEncodingは、目的変数を利用して特徴量エンジニアリングを行います。

    SIGNATE SIGNATE

    例えば、各駅に対する賃料の平均を計算した値を特徴量にします。
    ただし、この方法は正しい処理(Leave One Outなど、ここでは割愛)を行わないと精度が落ちてしまう可能性があります。

    以上の特徴量エンジニアリングを行うと、以下のスコアが出ました。
    モデルはLightgbmのままです。

    SIGNATE SIGNATE


    特徴量エンジニアリング part2

    SIGNATEのフォーラムを見ると、「地価データを利用した」という情報を公開されていたので、早速取り入れてみました。

    SIGNATE SIGNATE

    地価データも価格への影響が強く、スコアに貢献してくれました。

    SIGNATE SIGNATE

    これが私の最終提出スコアです。


    解法まとめ

    モデル

    Lightgbm


    特徴量エンジニアリング

    • 数値変数×カテゴリ変数
    • 数値変数×数値変数
    • targetencoding


    最後に

    家賃予測コンペでは、他のコンペでもよく使用される基本的な手法を行うことで、上位8%まで上がりました。
    私のようなKaggle初心者は、Kaggleで紹介されている高度な解法を理解し活用することが難しいので、
    データの特徴を深く理解し、基本的な解法を最大限に活用することが効果的です。

    これからも、データサイエンティストとしてKaggleコンペにたくさん参加し、Kaggleの解法についてアウトプットしていきたいと思います。


    Twitter・Facebookで定期的に情報発信しています!

    目次

    1. このブログの対象者
    2. 地震コンペの概要
    3. 私が地震コンペを始めた理由
    4. Kaggle初心者が地震コンペをやるまで
    5. 地震コンペの情報収集
    6. 参考にするNotebookの解読
    7. 特徴量の作成
    8. モデルの作成
    9. 結果
    10. 考察
    11. 今後


    1. このブログの対象者

    • Kaggle初心者
    • Kaggle入門者用のTitanicや住宅価格コンペの次に挑戦したいが進め方に悩んでいる人
    • 地震コンペ(LANL Earthquake Prediction)のような時系列の信号データの分析に興味を持っている人


    2. 地震コンペの概要

     このコンペは、地震の研究でよく使用される実験装置から得られる「音響データ(acousticdata)」のみを使って、実験室で発生する「地震までの時間(timeto_failure)」を予測するコンペである。訓練データは一つのセグメント(一つの実験データの一部分)で、図1のように「音響データ」と「地震までの時間」から成る。

    訓練データ

     テストデータは2,624個のセグメント(それぞれseg_idが与えられている)で、各セグメント毎に1つのcsvファイルから成るため、2,624 個のcsvファイルから成り、図2のように「音響データ」のみで構成されている。また2,624 個のcsvファイルは1つのフォルダに入っている。

    テストデータ

     この2,624個の各セグメント(各segid)に対して、図3から4のように「地震までの時間」を予測し提出することが目的である。ここで注意すべきなのはsumplesubmission.csvのsegidの順番と2,624個のテストデータが入っているフォルダのsegidの順番が異なっていることである。しかし順番は異なっているが、共に2,624個のseg_idが正しくあるので心配する必要はない。

    samplesubmission

    提出ファイル


    3. 私が地震コンペを始めた理由

    • わたしは以前から「海洋波の波高予測」といった時系列の信号データの分析を行っている。その分析方法はその信号データのみを特徴量として分析する方法である。この方法をここでは「直接法」と呼ぶことにする。私は時系列の信号データの分析方法としてこの「直接法」以外を知らないため、今回地震コンペにチャレンジすることで、新しい手法を知ることができ、今後の分析に活かせるのではないかと思ったからである。

    • また地震コンペで扱う「音響データ」は時系列の信号データであるが、世の中の多くのデータは時系列であり、時系列データの分析をできるようになると、ありとあらゆる現象の分析が行えるようになる。なのでその練習の一環として、地震コンペを行うことにした。


    4. Kaggle初心者が地震コンペをやるまで

    ▼必要なスキル

    • Pythonの基本構文が書ける能力
    • 機械学習の学習モデルの種類を知っており、実装できる能力


    ▼地震コンペをやる前にやった方が良いKaggle

     Kaggleの基礎や提出方法などを分かっておくために、深堀りはせずとも以下をやっておいた方が良い。

    • Titanic

     私はネットで「Kaggle Titanic 入門」などと検索し、コードを理解して参考にした。

     スコアが0.8を超えると、Kaggleの力がある程度付いたとよく評価されている。

    • 住宅価格コンペ

     私はネットで「Kaggle 住宅価格 前処理」などと検索し、コードを理解して参考にした。


    5. 地震コンペの情報収集

    • まずは何かを参考に

     本来ならば、自力で提出できるのがベストであるが、私は地震コンペをやると言っても何から始めていいのか、特徴量をどうするか悩んだので、まずは既存のものを参考にすることにした。

    • ネット検索は使えない

     地震コンペはTitanicや住宅価格とは異なりマイナーなコンペなので、ネット検索では地震コンペについてしっかりと解説していたり、コードが書いてあるサイトがない。地震コンペに限ったことではないが、Titanicや住宅価格以外のコンペはネット検索をしても良い解説サイトは多分ないだろう。

    • Notebooksを参考に

     そこで参考にすべきなのがKaggleのNotebooksだが、当然英語で、読み進めていくには時間がかかる。また問題は英語で書かれていることだけではない。Notebooksは人によっては全く文字を書いて解説せず、ただコードを貼っている人もいる。人が書いたコードは、自分の書き方とは当然異なるので、本当に読めない。

    • 良いNotebookを見つけるには

     では、読みやすいNotebooksはどうやって探せばよいのか。まずはNotebooksの右上にあるSort byの所を、Most Votesにすると良い。良いNotebooksと投票されたものが上から順に並んで表示される。しかし、必ずしも一番上に表示されたNotebookが良いとも限らない。なので上から順にNotebookを見ていく。上から順に見て行き、英語ではあるができるだけ解説文が多いNotebookを探すとよい。コードだけのNotebookは上級者にしか読めないだろう。また、パッと見でコードの構文の形がなんとなく分かるものを選ぶとよい。この段階ですぐにコードの内容がすぐに理解できる必要はない。ただ構文の形がなんとなく分かるだけで、自分の書くコードと似ている可能性が高いのでよい。


    6. 参考にするNotebookの解読

    • 参考にするNotebookの決定

     こちらのNotebookを最初に選んだ。後半部分は解説文はないし、コードもよく分からない。だが、前半部分は解説文があり、コードもなんとなく構文の形が分かるので、これを選んだ。

    • 全部コピペして提出

     そしてまず上記URLのコードをコピペして提出してみた。これは念の為、エラーが出ずに正常に実装でき、採点されるかを確認するために行った。 コピペしてもエラーが出て実装できないNotebookもあるのでこの作業はしたほうが良い。今回は正常に実装でき採点されたので特に問題はなかった。

    • 解説文の解読

     ここからが私の勉強である。Notebookの解説文をgoogle翻訳を使いながら読んだ。

    • コードの解読

     その後Notebookのコードを上から解読していった。この作業が最も気合がいる作業であるが、読みにくくないNotebookを選んだため、なんとか読むことができた。ただ全ては理解できていない。特に後半の学習モデルの作成部分はよく分からない。そこでこれは私の工夫だが、特徴量を作り上げ、訓練データとテストデータの作成する部分だけNotebookを参考にすれば、後はなんらかの学習モデルを使用して学習すればよいのであって、学習モデルまで参考にする必要はないので、後半部分を解読することはしていない。つまり私は前半の特徴量を作り上げ、訓練データとテストデータの作成する部分だけNotebookを解読した。


    7. 特徴量の作成

     まず、モジュールや関数を読み込み、次にtrain.csv(図5ではearthquake_train.csvと改名している)を読み込む。

    スクリーンショット 2019-11-05 14.10.09.png

     次に訓練データの特徴量を図6のように作成する。「音響データ」の特徴を保持して加工する必要があるため、当然、平均や標準偏差といった統計量を用いるのだが、時系列データであるので、「音響データ」150,000個毎の各セグメントの統計量を特徴量としていく。例えば、「音響データ」の0から149,999個目の統計量を一行目、150,000から299,999個目の統計量を二行目としていく。そしてその統計量を24種類扱う。このように信号データの特徴を保持して新しい特徴量を作る方法をここでは「間接法」と呼ぶことにする。

    trainデータ trainデータ特徴量作成コード

     訓練データの特徴量の作成と同様に、テストデータも図7のように特徴量を作成する。但し、samplesubmission.csvとtest.csvはearthquakesamplesubmission.csv、earthquaketest.csvに改名している。

    testデータ特徴量作成コード


    8. モデルの作成

     まず図8のように、訓練データとテストデータの正規化を行う。ここで理由は分からないが、In [6]において、 scaler.fit(X_test) というコードを加えてしまうと精度が落ちることが分かったので、図8では加えていない。

    データ正規化コード

     その後、学習モデルはNotebookを参考にせず、図9のようにLightGBMを採用した。但し、LightGBMのパラメータだけはNotebookでLigghtGBMを行っているであろう箇所の値と同じにした。

    モデル作成コード モデル作成コード


    9. 結果

     上記のコードを実装することで、図10のようにスコアが1.65885となった。

    結果画像


    10. 考察

     今回は上記のURLのNotebookを参考に地震コンペを行ってきたが、このNotebookには同じ人が作成した第二弾 があり、ここでは今回作成した特徴量に加え、更に多くの特徴量を追加して、精度を上げている。つまり、特徴量を増やし、「音響データ」の特徴をより正確に統計量として抽出することによって精度が上がるのではないかと私は考えている。


    11. 今後

     この地震コンペは、使用できるデータとして、一つの時系列の信号データしか与えられていない。このような場合、その信号データを唯一の特徴量と見なす「直接法」(LSTMなどの時系列データに特化したモデルを使用するなど)は当然あるが、実際にやってみるとデータ数が非常に多いため処理しきれなかった。つまり「音響データ」をそのまま使うというのはなかなか厳しい事が分かる。そこで、今回参考にしたNotebookのように、その信号の特徴を抽出して統計量にし、それを特徴量にするという「間接法」が有効であった。

     今後も私は時系列データの分析を主に行って行くが、このような状況に出会った場合、「直接法」だけでなく、「間接法」というアプローチもあるということを念頭に入れて分析にあたりたいと思う。また逆に、今のところLSTMによる「直接法」で地震コンペの処理はデータ量が多すぎるためできていないが、なんとかできる方法がないのか今後も探ってみたいと思う。


    当社では定期的にメルマガでも情報配信をしています。
    ご希望の方は問い合わせページに「メルマガ登録希望」とご連絡ください。


    Twitter・Facebookで定期的に情報発信しています!

    U-netとは

    U-netはFCN(fully convolution network)の1つであり、画像のセグメンテーション(物体がどこにあるか)を推定するためのネットワークです。

    生物医科学(biomedical)の画像のセグメンテーションを行うために2015年に発表されました。

    (論文URL : https://arxiv.org/abs/1505.04597)

    この記事では、まずU-netの中で行われている処理についてを1〜4章でまとめ、それらの組み合わせであるU-netをまとめたいと思います。

    目次

    1.Semantic segmentation

    2.fully convolution network(FCN)

    3.deconvolution

    4.skip-connection

    5.U-netの仕組み

    1.Semantic segmentation

    画像のピクセルそれぞれをクラス分類するタスクです。

    (MNISTなど)画像のクラス分類と異なるのは、画像全体をクラス分類しない点です。

    ピクセルごとのクラス分類ができると、以下のような出力を得られます。

    Alt text

    by https://devblogs.nvidia.com/image-segmentation-using-digits-5/

    2.fully convolution network(FCN)

    一般的なCNNでは畳み込み層と全結合層がありますが、FCNはこの全結合層を畳み込み層に置き換えたものです。

    全結合層を畳み込み層に置き換えることで、「物体がなにであるか」という出力から「物体がどこにあるか」という出力になります。

    Alt text

    by https://arxiv.org/abs/1411.4038

    画像上部分が画像全体のクラス分類で、画像下部分はヒートマップで猫がどのあたりにいるかネットワークが把握していることがわかります。

    3.deconvolusion

    1つ上の画像のヒートマップは入力画像に畳み込み処理を何度も行い、とても小さくなっています。

    これに1番上のような出力が得られるような処理を行なっていきます。

    このような処理を「up sampling」といい「deconvolution」が有名です。

    日本語だと「逆畳み込み」といい、畳み込み処理の逆処理だと思ってください。

    CNNで畳み込み層のフィルターの要素を学習していくように、逆畳み込み層のフィルターも同じように学習できます。

    4.skip-connection

    畳み込み処理を加えていくと、ネットワークが「物体が何であるか」についての特徴を抽出していきますが、poolingの影響で「物体がどこにあるか」についての特徴は失われていきます。

    畳み込み処理を行なった後で、逆畳み込みを行なっても物体の位置情報は満足に復元できない場合があります。

    それを解決するのがskip-connectionです。

    これは畳み込みを行なった後、特徴マップを保持しておいて、後で逆畳み込みをする画像に足し合わせる処理です。

    上で提示した車の画像に用いると以下のようになります。

    Alt text

    by : https://devblogs.nvidia.com/image-segmentation-using-digits-5/

    推定する領域(色のついた部分)がシャープになっていることがわかります。

    5.U-netの仕組み

    U-netには上でまとめた

    ・fully convolution network(FCN)

    ・deconvolution

    ・skip-connection

    が使われています。

    構造は以下のようになっています。

    Alt text

    by : https://arxiv.org/abs/1505.04597

    左右対象でアルファベットの「U」に似ていることから、「U-net」と呼ばれているそうです。

    大雑把に左側の処理では画像の畳み込みを行い、右側では逆畳み込みをskip-connection(中央矢印)からの情報を参考に行なっているイメージです。

    まとめ

    U-netの内部で行われる処理について、ざっくりと説明しました。

    まとめると・・・

    ・画像全体のクラス分類(MNISTなど)からFCNとdeconvolutionを使い、物体の位置情報を出力できるようになった

    ・skip-connectionを用いて畳み込みによって失われる位置情報を保持しておくと、より精密な領域を出力できる

    ・U-netは上記2つを上手く組み合わせている

    こちらの記事ではPythonで実装を行い、学習している様子を紹介しています。


    定期的にメルマガでも情報配信をしています。
    ご希望の方は問い合わせページに「メルマガ登録希望」とご連絡ください。


    Twitter・Facebookで定期的に情報発信しています!

    現在、多くの業界でAI・機械学習の重要性が増加しています。

    背景のひとつに労働人口の減少による人手不足があります。帝国データバンクの調査によると、「正社員不足」状態の企業は全体の50.3%を占めています。
    人手不足も解消のためには、業務自体を削減すること、または業務を人から代替する必要があります。

    ここでは人間の目の代わりとなり、判断をおこなう機械学習である画像認識技術を紹介します。

    スタンフォード大の研究者らがAI関連の研究開発や経済、教育、各国の動向など多様なデータをまとめた「AI Index」の2019年版では、ここ1年半でクラウドインフラで大規模な画像分類システムを学習させるのに必要な時間が、2017年10月の約3時間から2019年7月の約88秒に短縮され、同様に学習させるコストも下がったと報告されています。 時間・マシンスペックの制限が徐々になくなることで機械学習の画像認識分野のビジネス活用はますます注目されていきます。


    目次


    機械学習での画像認識とは

    画像からパターンを認識し、何が写っているのか判断することが画像認識です。光景の知覚・認識をコンピュータがおこなうことで、人間がおこなうはずであった画像の判別や物体の検出などを自動化することができます。

    例えば、動物が写っている写真をその動物ごとに分類することもできますし、製造業でのシーンでは正解とは違うもの(不良品)を見つけることもできます。本記事の最後でも紹介しますが、画像認識は様々な分野でも応用できることと、ディープラーニングの登場で精度が向上したこと、高性能なモデルの開発で学習(構築)時間を削減したことから急速にビジネス活用が進みました。

    元々はロボットにおいて外界にある物体検出の手段として考えられた画像認識技術でしたが、1970年代における人間の知識をプログラムとして直接書く方式から、画像の形、色、動きなどの幾何学的な特徴を認識する方法にシフトして大きな進歩を遂げています。

    技術の発展により、画像認識はAI(人工知能)が活用される一分野として現在も急速に発展しています。それでは画像から物体を検出しそれが何であるか判定する仕組みをご紹介します。


    画像認識の仕組み

    一般的な画像認識のプロセスをご紹介します。

    Image recognition


    画像認識のモデルの構築

    画像認識をおこなう際、「画像のどこに何が写っているのか」を認識するためのモデルが必要です。機械学習を用いて学習データからこのような検出・判別するモデルを構築します。モデルをあらかじめ構築しておいて、認識する画像に対して判別結果を出力する仕組みを作ります。


    特徴抽出

    モデルで実際に画像を判別する際には、画像の中から 特徴抽出する必要があります。画像の局所的な特徴の抽出や画像に含まれるノイズの除去などを、画像処理の手法や統計的な手法によっておこないます。判別に必要のない情報を除いた上で、判別結果を計算することができます。


    プーリング

    抽出した特徴はいくつかの一定の大きさの領域にまとめた後、プーリング と呼ばれる処理でまとめられた領域を1つの値で代表します。画像の空間的な情報を削除し、判別に必要な情報のみを残します。


    分類

    特徴抽出・プーリングの実施後には、事前に用意していたモデルによって画像を判別します。

    また、ディープラーニングに代表される学習手法は特徴抽出・プーリングの処理をひとまとめにして、それらの手順をさらに繰り返すことで認識精度を高めています。


    画像認識技術の4つの活用事例

    文字認識

    画像認識の代表的な活用事例です。文字の書かれた画像から文字の領域を抽出し、どの文字か推測します。この技術で文章読み取りが自動になり、転記作業の負担を軽減します。

    Image recognition

    手書き書類・メモを文字起こししていませんか?社内は紙の書類で溢れていませんか?

    業務を効率化し生産性を向上するためには、紙の情報ををデータ化することが不可欠です。顧客データから自社製品が強い顧客像を割り出したり、売上データから来期の売上予測をしたりと、利益につながるデータの二次活用は勿論、紙の保管場所を削減します。

    画像に写る物体を理解し、それが何かというラベル(正解)を割り当てる過程を 物体認識 と呼びます。


    医療画像認識による診断支援

    医療分野においても画像認識は活用されています。医師が医療画像を見ることで病変を判断する過程を、コンピュータである程度自動化します。最近では医師でさえ見抜けない腫瘍の変異をコンピュータが画像の中の領域を抽出し、判別する事例もあります。これにより、病変時は発見までの時間短縮、診断ミスを低減します。

    医療画像での変異発見は 物体検出 と呼ばれ、画像の中の変異の領域を抽出することを セマンティックセグメンテーションと呼びます。


    インターネット上の画像検索

    インターネット上で画像認識を身近に感じるのは、この 画像検索 だと思います。入力された文字列あるいは画像と類似する画像を検索する技術であり、データベースに保存された画像から似たような画像を検索します。

    Image recognition

    画像検索は具体的な判別を行う インスタンス認識 によってラベル付けをします。あらかじめラベル付けしておくことで瞬時に内容や見た目の近い画像を見つける類似画像検索が可能です。


    自動車の自動運転

    今後、さらに発展が予測される画像認識の活用分野のひとつとして、自動車の自動運転が挙げられます。自動車に搭載されたカメラによって外部の状況を判断し、自動車に運転をさせる技術です。カメラから受け取った画像を認識させることで、人間が難しい操作をすることなく搭載されたコンピュータが運転することが可能になります。

    自動運転では静止した画像だけでなく、その時系列情報も必要です。この時系列情報を利用した画像認識を 動画像認識と呼びます。


    まとめ

    今回はこれらのことをご紹介しました。

    • 画像認識とは何か
    • 画像認識技術の活用事例
    • 画像認識の仕組み


    画像認識は2020年東京オリンピックで採用されたりと、今後浸透していく機械学習の技術です。応用方法の豊富さと進歩の速さがあいまって、「 AI搭載家電」など、急激に導入検討が進んでいます。


    当社はAI・機械学習を活用したソリューションをご提案しています。

    • 自社にあるデータを2次活用したい
    • 画像データを活用したAIを作成したい
    • 既にAIシステムを利用しているが思うような効果が得られていない
    • 機械学習ではなにが出来るのか興味がある


    このようなご相談は画面右上の[お問い合わせ]までご相談ください。


    アクセルユニバースの紹介

    私達はビジョンに『社会生活を豊かにさせるサービスを提供する。』ことを掲げ、このビジョンを通して世界を笑顔にしようと機械学習・深層学習を提案しています。

    • ミッション(存在意義)
      私達は、情報通信技術を使って万物(全ての社会、生物)の暮らしをよりよくすることに貢献し、 それを加速させることを使命とします。

    • ビジョン(目標とする姿)
      社会生活を豊かにさせるサービスを提供する。

    • バリュー(行動規範)

      1. 変化を求め、変化を好み、変化する
      2. 自分の高みを目指してどんどん挑戦する
      3. お客様と一蓮托生でプロジェクトを進める


    acceluniverse


    参考文献

    原田達也(2018) 『画像認識』 講談社

    平井有三(2018) 『はじめてのパターン認識』 森北出版


    Twitter・Facebookで定期的に情報発信しています!

    はじめに

    最近天気が不安定で、急な雨が多くまいっています。(しかも冬の雨はツライ。)
    ついつい出かける時に傘を持たずに、夜、雨に降られることも多いですよね。
    現在、Pythonを使った機械学習を勉強しているので、kaggleだけではなく、実際にテーマを決めて何か簡単な実装をしてみたいと思い、今回は気象庁のデータを使って ある日に雨が降っている or いないという2値の予測を実装をします。
    自分で作ると愛着が湧いて、ちょくちょく予測して傘を忘れずに済むだろう。そして濡れることはもうないだろう!をモチベーションに頑張ります。


    目次


    気象庁のデータを収集し、整える

     予測するためにデータの収集から始めましょう。中々扱いやすいデータが無いので困りますが、気象庁が提供している気象データがかなり綺麗なのでこのデータを採用します。このデータは過去の気象データで地点、期間、項目(雨量、風速など)を選択しエクセルのCSVファイルでダウンロードしてくれるのでとっても便利でした。そこで平均気温(℃)、天気概況(昼:06時~18時)、降水量の合計(mm)、日照時間(時間)、平均風速(m/s)、平均蒸気圧(hPa)、平均湿度(%)、平均雲量(10分比)がかなりを取り、東京の1日毎の1年分のデータを使うことにしました。
     データを読み込んだときにいらない情報もあったのでこんな感じでデータを整えました。

    Alt text
     今回は、ある日に雨が降っているかどうかを予測するので降水量の合計(mm)を正解データ(目的変数)としましょう。雨の定義としては、その日の降水量の合計が0mmより大きい、つまり少しでも降ったら雨、降水量の合計が0mmならば雨でないとします。また特徴量(線形回帰では説明変数などと呼ばれています。機械が学習するために使う要素です。)としては先程あげたデータの降水量の合計以外を使ってみます。天気概況に雨があるので人が雨と判断することは簡単です。しかし、機械は「天気が雨だと降水量が0でない」ということを判断できません。人間にとって簡単なことほど機械が行うのは難しく、天気概況を特徴量に含めた時、どのように学習してくれるか検証することも面白いですね。
     予測するためによく使われているAnacondaのjupyterNotebook、Python3.7を使います。手始めにデータを読み込んで表示させましょう。

    Alt text
     もう少しデータを扱いやすく直します。天気概況ですが、文字情報のため扱いにくいです。そこで「晴」→4、「曇」→3、「雨」→2、「それ以外」(雪など)→1と数値化してしまいましょう。また、正解データになる降水量の合計に関しても降水量があれば1、なければそのまま0にしましょう。

    Alt text
     上のようにデータを整えればOKです。データを整える際はプログラミングがあまり得意でなければそのままエクセルのファイルの数値を1つずつ変えれば問題ないと思います。(データ量が膨大だったらプログラミングを書きましょう。)プログラミングを書いてデータを整えるのもプログラミングの良い練習になると思います。


    線形回帰で実装する

     ここまで来たらついに予測ができます。
     まずは、年月日以外のすべてのデータを説明変数、降水量の合計を目的変数として線形回帰してみましょう。今回はライブラリを使って実装します。

    Alt text
     少し教師あり学習(線形回帰のように正解データがある学習)について説明します。教師あり学習ではデータを訓練用のデータと評価用のデータに分ける必要があります。
     訓練用のデータというのは機械に学習させるための材料になるものです。このデータをもとに機械は学習をします。そしてその学習をしたモデルを用いて評価用のデータを評価します。最後にその評価結果ともともとの正解データを見比べてどれだけあっているかが精度として出るわけです。

     つまり、pythonで実装する際もデータをどれくらいの割合で分けるか機械に指示する必要があります。そのライブラリがIn [9]の2行目「from sklearn.modelselection import traintest_split」です。1行目のライブラリは線形回帰のライブラリになります。
     実装した結果が次のようになりました。

    Alt text
    精度は、0.4781...となっているので約48%。ということはほぼ半分なので全然予測ができていません...。
     せっかく頑張っても最初はこんな感じです。ここで少しだけ上のプログラミングに関して補足します。In [11]の1行目の部分で訓練データと評価用データに分けています。今回は、「 test_size = 0.2」としているので全データに対して訓練データが80%、評価用データが20%としています。このデータは訓練データ、評価用データのどちらに割り振られるかランダムなので評価するごとに同じ結果は出ません。振り分けられ方によっては精度が上下することもあるので、正確な精度を出したいときは何回か実装してその平均を取ります。

    実装結果から精度UPするために

     線形回帰をした時、精度が約52%でした。この精度になった原因としては以下が考えられます。

    ①過学習してしまった。
    ②データが少ない。
    ③2値に分類するのにそもそも線形回帰の相性が悪い。

    以上3点が思いつきました。順番に見ていきましょう。
     まず①について、そもそも過学習というのは説明変数の相性が悪かったり説明変数が多すぎて機械が誤って学習してしまうことです。誤って学習してしまうことで、精度が悪くなってしまいます。そこで、説明変数を見直しましょう。例えば、日照時間は長ければ、気温が高くなりそうのなので気温のデータだけあれば大丈夫そうです。また、平均蒸気圧は気温に依存して決まるそうなのでこれもいらなそうです。そこで日照時間と平均蒸気圧をなくして予測してみましょう。その結果は、

    Alt text

    精度は、0.5585...なので多少上がりました。


     次に②については、データが少ないと機械もうまく学習することができません。1年分のデータから3年分のデータに増やして実装してみました。

    Alt text

    ①の説明変数も減らして実装したのですが精度はほぼ変わらなかったですね。
     最後に③についてです。線形回帰は最小2乗法を用いた最もシンプルな回帰モデルですが、今回の精度の結果からあまり2値に分類するのには適したモデルではないのかもしません。そこで、2値分類する際に有名なモデルとして、ナイーブベイズやロジステック回帰です。ロジステック回帰にして実装してみましょう。

    Alt text
    これも①の説明変数も減らして実装すると、精度はすごく上がりました。
    皆さんもいろいろ実験してみてください。

    まとめ

     今回は、線形回帰を用いて雨が降るかどうかを予測しました。先程の精度UPについて考察する所では、以下のようにして精度を上げることができました。

    • 特徴量(説明変数)をうまく選ぶ

    • モデルを変えてみる

     他にもデータを見直し、もっと学習に合うようにデータを直して精度を上げます。このような作業をデータの 前処理(特徴量を選択するのも前処理です)と言います。前処理は知識やセンスが問われ、うまくできると精度がとても上がります。そして、人によってやり方も様々なので正解もありません。この精度を競うコンペも行われていて、有名所はkaggleSIGNATEがあります。コンペで優秀な成績を納めれば懸賞金も貰えるのでチャレンジしてみて下さい!

    参考文献

    気象庁

    Anaconda

    kaggle

    SIGNATE


    定期的にメルマガでも情報配信をしています。
    ご希望の方は問い合わせページに「メルマガ登録希望」とご連絡ください。

    はじめに

    ニューラルネットワークの学習の目的は、損失関数( loss function )の値をできるだけ小さくするようなパラメータを見つけることに他ならない。これは言い換えれば最適なパラメータを決定するという点で最適化問題に帰着されるが、ニューラルネットワークの最適化はそのパラメータの数の多さから大変複雑な問題として扱われる。

    今回はSGD, Momentum, AdaGrad, Adamと呼ばれる4つのパラメータ更新手法を紹介し、最後にMNISTデータセットを用いてこれらの更新手法を比較していく。

    ※Pythonで用いているコードは『ゼロから作るディープラーニング(オーム社)』を参考にしている。

    SGD(Stochastic Gradient Descent)

    SGD(確率的勾配降下法)は、勾配方向へある一定距離だけ進むことを繰り返すという単純な方法である。以下はSGDのparameter更新式である。(以下、Lは損失関数)

    Deep Learning

    但し偏微分は損失関数の勾配を表している。これをPythonのクラスとして実装すると以下のようになる。

    Alt text

    確かに実装は簡単であるが、関数の形状が等方向でないと非効率な経路で探索してしまうという欠点がある。例えば、

    Deep Learning

    という関数についてこのSGDを適用してみよう(以下この関数を用いて各手法における最適化問題を解く)。その前にこの関数の形状及び勾配を下記に示す。

    SGD SGD


    この勾配はy軸方向に大きく、x軸方向には小さいことが分かるだろう。しかし、今この関数の最小値は明らかに(x, y)=(0, 0)であるのに、上で示した勾配は多くの場所で(0, 0)方向を指していない。

    実際、この関数にSGDを適用した結果(初期値(x, y)=(-7.0, 2.0))は以下のようなジグザグした動きをし、これはかなり非効率な経路である。

    SGD

    このSGDの非効率な探索経路の根本的な原因は、勾配の方向が本来の最小値ではない方向を指していることに起因している。 この欠点を改善するために、続いてMomentum, AdaGrad, Adamの3つの手法を紹介する。

    Momentum

    Momentumとは「運動量」という意味で物理を知っている人なら馴染みの深い言葉だろう。Momentumのparameter更新式は次のよう。

    Deep Learning

    Momentumは簡単に言う\とSGDに慣性項αvを付与したものである。αはハイパーパラメータであり、前回の更新量にα倍して加算することでparameterの更新をより慣性的なものにする狙いがある。

    今回もPythonのクラスとしてMomentumを実装してみる。

    Alt text

    vは初期化時には何も保持しないが、update()が初めに呼ばれるときに、parameterと同じ構造のデータをディクショナリ変数として保持する。

    ではこのMomentumを用いてさっきの関数の最適化問題を解いてみよう。結果は下図。

    Momentum

    SGDよりもジグザグ度合いが軽減されているのは一目瞭然であるが、一体何故だろうか。x軸、y軸についてそれぞれ考えてみよう。

    x軸方向: 受ける力は小さいが、常に同じ方向に力を受けるため、同じ方向へ一定して加速する

    y軸方向: 受ける力は大きいが、正と負の方向の力を交互に受け止めるため、それらが互いに打ち消し合い、y軸方向の速度は安定しない。

    これよりSGDのときと比べてx軸方向により早く近づくことができジグザグの動きを軽減できる。

    AdaGrad

    ニューラルネットの学習においてはラーニングレートηの値が重要になってくる。この値が小さすぎると学習に時間がかかりすぎてしまうし、逆に大きすぎても最適解にたどり着かずに発散してしまう。

    このラーニングレートに関する有効なテクニックとして、学習係数の減衰( learning rate decay )という手法がある。これは簡潔に言うと、学習が進むにつれてラーニングレートを小さくするというものである。

    最初は"大きく"学習し、次第に"小さく"学習する手法で、ニューラルネットの学習ではよく使われる。parameter更新式は以下のよう。

    Deep Learning

    ここで、変数hにおいて⦿は行列の要素ごとの積を意味し、上式のように経験した勾配の値を2乗和として保持する。そして、更新の際に、hの二乗根で除算することにより学習のスケールを調整する。

    これは、パラメータの要素の中でよく動いた(大きく更新された)要素は、ラーニングレートが小さくなることを表している。 実際にpythonのクラスとしてAdaGradを実装してみる。

    Alt text

    最後の行で1e-7を加算しているのは、self.h[key]の中に0があったときに0で除算してしまうことを防ぐためのものである。 では実際にさっきの関数にAdaGradを適用してみよう。

    AdaGrad

    これより、さっきのSGD, Momentumよりも効率的に最小値に向かっているのが分かる。y軸方向には勾配が大きいため最初は大きな更新ステップとなっているが、その大きな動きに比例して更新のステップが次第に小さくなるように調整される。

    Adam

    Adamは2015年に提案された新しい手法であり、直感的にはMomentumとAdaGradを融合したような手法である。この2つの手法のメリットを組み合わせることで、効率的にparameter空間を探索することが期待できる。

    また、ハイパーパラメータの「バイアス補正」が行われているのもAdamの特徴である。(詳細はこちらADAM: A METHOD FOR STOCHASTIC OPTIMIZATION)

    更新式はやや複雑であるので、今回は割愛するが勾配降下法の最適化アルゴリズムを概観するに掲載してあるので、興味のある方はぜひ見てほしい。

    実際にpythonのクラスとしてAdamを実装してみる。

    Alt text

    Adamを用いて先の関数の最適化問題を解いてみよう。結果は以下のよう。

    Adam

    ソースコードは以下。

    Alt text

    この比較実験では、5層のニューラルネット、各隠れ層100個のノードを持つネットワークを対象にした。また活性化関数としてReLUを使用した。

    上のグラフより、SGDよりも他の手法のほうが速く学習できていることは見て容易だろう。さらにAdaGradのほうが少しだけ速く学習が行われているようである。

    しかし、この実験はハイパーパラメータ(ラーニングレートなど)の設定や、ニューラルネット自体の構造(何層にするか)によって結果は変わってくることに留意せよ。

    しかし、一般的にはSGDよりも他の3つの手法の方が速い学習を行い、より高い認識性能を誇ることもある。

    以上4つの手法を紹介したが結局どれを用いるのがベストなのか?残念ながら全ての問題で優れた手法は今のところなく、それぞれに特徴があり、得意不得意な問題があるのが現状である。

    実際、多くの研究において今でもSGDは用いられているし、他3つの手法も十分に試す価値がある。結局、自分の好きなように色々試して、最良の手法を見つけていく他ないであろう。


    定期的にメルマガでも情報配信をしています。
    ご希望の方は問い合わせページに「メルマガ登録希望」とご連絡ください。

    参考文献

    『ゼロから作るディープラーニング(オーム社)』

    Optimizer:深層学習における勾配法について

    各手法におけるパラメータ更新経路

    はじめに

    クラスタリングはマーケティング手法としても使われている。
    見込み顧客へ適切な施策を行うために、似た顧客同士をカテゴリ分けする必要があり、それをセグメンテーションという。
    セグメンテーションのために機械学習の手法としてクラスタリングが使用されている。

    k-meansクラスタリング(以下、k-means法)は複数個のデータをcentroids(重点)からの距離に応じて、あらかじめ決めたk個のクラスタに分ける非階層クラスタリング、及び、ハードクラスタリングの手法の1つである。

    階層・非階層クラスタリングの詳細については以下のブログを参考にしてほしい。 (アクセルユニバース株式会社技術ブログ、富田、2019

    クラスタリングのため目的変数無し(ラベル無し)の場合のみこの手法は利用可能である。本記事は「k-means法とはどういったものか」に焦点を当て、方法やその過程について書いている。そのため数学的な要素は最小限に留めている(k-means++法やシルエット関数の計算方法等)。これらの数学的アプローチは今後の記事、もしくは、後述の参考文献をご覧いただきたい。

    k-means法の実行方法

    まず最初に各データからそれらが属するクラスタの重点までの距離を定義しなければならない。クラスタは全データの中で似たもの同士の集合体であり、その判断は各データから重点の距離を基に行われる。これにはsquared Euclidean distance (ユークリッド距離の2乗)がよく使われる。他にもユークリッド距離を用いたクラスタ内誤差平方和(SSE)を最小化する方法や、マンハッタン距離、マハラノビス距離等も使われており、データ分析の当事者が最適だと考えるものを選ぶ。

    Alt text 各データから重点のユークリッド距離の誤差を最小限にする方法の一例。引用元: (https://data-flair.training/blogs/k-means-clustering-tutorial/)

    次にクラスタの数を決める。K-means法を行う際にはあらかじめ全データを何個のクラスタに分けるか定める必要がある。この個数に関して最適解は無く、データ分析者自身が判断しなければならない。極端に言えば、データ分布を観た後に直感的に個数を決めてもそれが間違っているのかどうか分からない。しかしながら、もちろんそれでは説得力に著しくかける。求められているのはクラスタ内誤差平方和(SSE)を最小化するなどして、できるだけ類似度の高いデータを集めたクラスタ数を決める。以下のような方法がより良いクラスタ数を導き出すために使われている。

    ・エルボー法(elbow method) SSEから判明する歪みに基づき、最も適したkの個数を導き出す方法である。歪みの最も大きくなった地点のkを最適解と見なす。下記の場合はk=4。

    Alt text

    ・シルエット法 (silhouette method) シルエット分析(silhouette analysis)とも呼ばれ、クラスタ内のデータの密度をプロット化し、最適なkの数を判断する。シルエット係数(silhouette coefficient)は−1から1の範囲で表され、1に近いほどクラスター間の距離が遠く、しっかりとクラスターが分けられていることを表す。各バーがおよそ均等な幅になるようにクラスタ数を設定する。

    Alt text

    以上のような方法でクラスタ数を決めたら、各クラスタの重点が動かなくなるまでになればk-means法は終了である。

    k-means法のためのPythonコード(Hastie *et al*., 2017 参照)

    #ランダムにデータセットを作成。
    from sklearn.datasets import make_blobs
    import matplotlib.pyplot as plt
    X,y = make_blobs(n_samples=300,
                     centers=4,
                     cluster_std=0.6,
                     random_state=0)
    plt.scatter (X[:,0], X[:,1], c='white', marker='o', edgecolor='black', s=50)
    plt.grid()
    plt.tight_layout()
    plt.show()
    

    Alt text

    #エルボー法を使い適したクラスタ数を求める。
    from sklearn.cluster import KMeans
    distortions = []
    for i in range(1, 10):
        km = KMeans(n_clusters=i, 
                    init='k-means++', 
                    n_init=10, 
                    max_iter=350, 
                    random_state=0)
        y_km = km.fit_predict(X)
        km.fit(X)
        distortions.append(km.inertia_)
    plt.plot(range(1, 10), distortions, marker='o')
    plt.xlabel('Number of clusters')
    plt.ylabel('Distortion')
    plt.tight_layout()
    plt.show()
    
    #シルエット法を使い適したクラスタ数を求める。
    import numpy as np
    from matplotlib import cm
    from sklearn.metrics import silhouette_samples
    
    km = KMeans(n_clusters=4, 
                init='k-means++', 
                n_init=10, 
                max_iter=350,
                tol=1e-04,
                random_state=0)
    y_km = km.fit_predict(X)
    
    cluster_labels = np.unique(y_km)
    n_clusters = cluster_labels.shape[0]
    silhouette_vals = silhouette_samples(X, y_km, metric='euclidean')
    y_ax_lower, y_ax_upper = 0, 0
    yticks = []
    for i, c in enumerate(cluster_labels):
        c_silhouette_vals = silhouette_vals[y_km == c]
        c_silhouette_vals.sort()
        y_ax_upper += len(c_silhouette_vals)
        color = cm.jet(float(i) / n_clusters)
        plt.barh(range(y_ax_lower, y_ax_upper), c_silhouette_vals, height=1.0, 
                 edgecolor='none', color=color)
    
        yticks.append((y_ax_lower + y_ax_upper) / 2.)
        y_ax_lower += len(c_silhouette_vals)
    
    silhouette_avg = np.mean(silhouette_vals)
    plt.axvline(silhouette_avg, color="red", linestyle="--")
    
    plt.yticks(yticks, cluster_labels + 1)
    plt.ylabel('Cluster')
    plt.xlabel('Silhouette coefficient')
    plt.tight_layout()
    plt.show()
    
    

    シルエット係数の計算

    silhouette_vals = silhouette_samples(X, y_km, metric='euclidean') y_ax_lower, y_ax_upper = 0, 0 yticks = [] for i, c in enumerate(cluster_labels): c_silhouette_vals = silhouette_vals[y_km == c] c_silhouette_vals.sort() y_ax_upper += len(c_silhouette_vals) color = cm.jet(float(i) / n_clusters) plt.barh(range(y_ax_lower, y_ax_upper), c_silhouette_vals, height=1.0, edgecolor='none', color=color) yticks.append((y_ax_lower + y_ax_upper) / 2.) y_ax_lower += len(c_silhouette_vals) silhouette_avg = np.mean(silhouette_vals) plt.axvline(silhouette_avg, color="red", linestyle="--") plt.yticks(yticks, cluster_labels + 1) plt.ylabel('Cluster') plt.xlabel('Silhouette coefficient') plt.tight_layout() plt.show()
    #k-means法によるクラスタリングのプロット
    from sklearn.cluster import KMeans
    km=KMeans(n_clusters=4,
              init='k-means++',      
              n_init=15,
              max_iter=350,
              tol=1e-04,
              random_state=0)
    y_km=km.fit_predict(X)
    
    plt.scatter(X[y_km==0,0],
                X[y_km==0,1],
                s=50,
                c='lightgreen',
                edgecolor='black',
                marker='s',
                label='cluster 1')
    plt.scatter(X[y_km==1,0],
                X[y_km==1,1],
                s=50,
                c='orange',
                edgecolor='black',
                marker='o',
                label='cluster 2')
    plt.scatter(X[y_km==2,0],
                X[y_km==2,1],
                s=50,
                c='lightblue',
                edgecolor='black',
                marker='v',
                label='cluster 3')
    plt.scatter(X[y_km==3,0],
                X[y_km==3,1],
                s=50,
                c='coral',
                edgecolor='black',
                marker='x',
                label='cluster 4')
    plt.scatter(km.cluster_centers_[:,0],
                km.cluster_centers_[:,1],
                s=200,
                marker='*',
                c='red',
                edgecolor='black',
                label='centroids')
    plt.legend(scatterpoints=1)
    plt.grid()
    plt.tight_layout()
    plt.show()
    

    Alt text

    k-means法の欠点

    1. 初期値に依存する。
    2. 外れ値の影響を受けやすい。
    3. 各データが1つのクラスタにしか所属できない。
    4. クラスタの個数をあらかじめ決定しなければならない。(クラスタの個数に正解はない。)

    さいごに

    以上がk-means法についてである。今回は数学的要素を最小限に抑え、同手法がどのように成り立っているかに重きを置き紹介した。クラスタリングの中で最も有名と言っても過言ではないk-means法は、データサイエンスや機械学習をやる上で必ず目にするだろう。加えて、クラスタリングはWebマーケティングや画像処理等にも活用できるなど利用用途は幅広く知っておいて損はない手法だろう。


    定期的にメルマガでも情報配信をしています。
    ご希望の方は問い合わせページに「メルマガ登録希望」とご連絡ください。

    参考文献

    DATAFLAIR TEAM (2019) 『Data Science K-means Clustering: In-depth Tutorial with Example』Retrieved from LINK .

    Hastie, Trevor et al. (2009)『The Elements of Statistical Learning: Data Mining, Inference, and Prediction Second Edition』. (杉山将 他 訳)

    Pelleg, Dan and Moore, Andrew (2000) 『X-means: Extending k-means with efficient estimation of the number of clusters』. Morgan Kaufmann.

    Raschka, Sebastian and Mirjalili, Vahid (2017)『Python 機械学習プログラミング』. (株式会社クイーブ 訳). インプレス.

    VanderPlas, Jake (2016) 『Python Data Science Handbook: Essential Tools for Working with Data』.

    平井有三(2012)『はじめてのパターン認識』. 森北出版株式会社.

    Attention は "Attention is all you need" (Vaswani et al, 2017)で一躍有名になった手法ですが、実はこの論文の前からあった概念です。今回はこのAttentionの技術について、またこの論文について解説していきたいと思います。

    1 Attentionの概念

    Attentionとは、「注意」とあるように、画像や文章の特定の部分に注意を向けるよう、学習させていく方法です。人間の場合を考えてみましょう。私たちが何かを見るとき、全ての部分を同じように観察しているわけではありません。犬の絵があれば、「犬の顔」「犬の手足」「犬の尻尾」を認識して犬だと識別できるのであって、毛の一本一本や肋骨の形に注目している人は少ないでしょう。これと同じことを機械にさせることができれば、より人間に近い形で画像や文章を認識することができます。これがAttentionの一番の動機であり定義の一つです。

    具体的にこれがどのようにモデルに表現されているかを知るには、まずSeq2Seqモデルを少し理解するのが良いと思います。

    1-1 Seq2Seq モデル

    Seq2Seqモデルは文章解析のために作られたモデルで、Encoderと呼ばれる入力を処理する部分と、Decoderと呼ばれる出力を処理する部分に分かれています (Sutskever, 2014)。従来のニューラルネットワークでは、元となる文章をまとめて機械に取り込むので、画像などの情報は処理できても、文章や会話のような順番(sequence)が重要となる入力に関しては上手く学習することができませんでした。そこで、入力の順番の情報も出力に反映させられうようにSeq2Seqが開発されました。

    具体的には、EncoderとDecoderにRNNの一種であるLSTMを使います。詳しくはLSTMの記事を読んで頂けると早いですが、sequenceを処理できるRNNの中でも、多少距離が開いていても対応できるLSTMを使うことで、最大限に入力sequenceの情報を出力に反映させることができます。

    attention

    1-2 Attentionモデル

    しかし、Seq2Seqには大きな限界があります。それは、入力の情報は結局最後には一つにまとめられて、固定された大きさのベクトルとして出力に引き渡される、という点です。これを解決し、さらに柔軟なモデルにするために、Attentionが開発されました(Bahdanau 2015)。言葉では分かりにくいので、具体的に図と数式で見ていきましょう。

    attention

    まず、従来のSeq2Seqのように各単語ごとにencoder(青)とdecoder(赤)からマシンの状態(state)を出力します。そして、推測したい言葉(target)から計算された出力(ht)を全てのencoder出力(hs)と組み合わせ、関連度(a_t)を算出します。

    Alt text

    このscoreの出し方は様々あり、後述のtransformerモデルの中では内積が使われています。

    次に、この関連度でencoderに重りをつけ、「文脈」(context)を割り出します。

    Alt text

    そして、もう一度Decoderのtargetと文脈を組み合わせて、decoderの隠れ層の最終出力を決定します。

    Alt text

    最後に、このdecoderの結果を用いて最終出力を決定します。

    Alt text

    ここで鍵なのが、attentionの度合いを決定するa_tが毎回更新される、という点で、Seq2Seqにはない柔軟性を取り入れることに成功した、というところです。データのどこにattentionを向けるのか、機械に学習させることで、より早く、高い精度を達成することができます。

    2 Attention is all you needのモデル

    では、Attention is all you need (Vaswani, 2017)について見ていきましょう。上で触れたように、attention自体はこれ以前からある概念ですが、この論文の革新的なところは、余分な部分を取り除き、attentionのみで学習しても、高い精度がでる、という点でした。以下、論文で実装されているtransformerモデルについて解説したいと思います。

    2-1 モデルの仕組み

    モデルの中心にあるのはattentionなので、元データ(memory)と検索をかけたい入力(input)の関連度を計算します。 逆に言うと、それしかしません。

    下の図で見てみましょう。memoryをkeyとvalueに分けるという工夫以外は、基本的にattention_weightを算出し、valueと組み合わせているだけです。以前のように先にRNNを通したりする必要はないのです。Attentionの仕組み自体は上で解説しているので、数式などは省略しますが、順番に見ていきましょう。

    Alt text

    2-1-1 input, memory

    Alt text

    入力はinputとmemoryの二つに分けられています。それぞれtensorで、shapeは[batch_size, length, depth]となっています。例として、

    Alt text

    というデータがあったとします。この場合inputlength=4, memorylength=3になります。 実際、自然言語等のデータを使う場合、多少の下処理が必要になってきます。

    まず、文章をいくつかのトークンに区切り、さらにそれを数値に変換していきます。

    Alt text

    これでnumpy arrayに変換すれば、処理が可能になります。

    2-1-2 query, key, value

    Alt text

    ここで先ほどの入力がquery, key, valueというattentionの中心になる情報に変換されます。queryはinputからくる、「検索をかけたいもの」になります。上の例でいうと、「猫」というのが検索をかけたいものであり、できればそれと関連する言葉が「結果」として出てきてほしい、ということになります。keyはこの検索をかけるときに、memory内のトークンと検索をかけるqueryがどの程度近いのかを図るための索引のようなものです。そして、keyの索引を参考に、対応する適切なvalueをアウトプットします。

    なぜ、わざわざmemoryをkeyとvalueに分けるのでしょうか。元となった論文Miiler et al, 2016 によると、memoryを二つに分けることで、keyとvalueの間の非自明な変換によって高い表現力が得られる、ということです。つまり、keyとvalueの関係性が我々に理解のできないようなものであっても、うまく対応できるのです。

    2-1-3 attention weight

    上記のqueryとkeyから、attention weightと呼ばれる、関連度を計算していきます。この重みが大きいと、query中の言葉とkey中の言葉の関連度が高い、ということになります。

    Alt text

    まず、queryとkeyの関連度を取ります。上の図では内積をとっていますが、これは内積注意(Dot-Product Attention)と呼ばれる手法で、Attention is all you need内で使われている手法になります。他にも、加法注意(Additive Attention)と呼ばれるものもあり、その場合はqueryとkeyをFFN(Feed Forward Network)に通してattention weightを求めます。一般的に内積注意の方がFFNのパラメーターを調整する必要がなく、処理も速いと言われています。

    次に、内積をsoftmaxにかけます。これは一つのqueryに対してweightの合計が1.0になるようにするためです。Softmax関数は入力に大きな値があるとgradientが0に近くなり、学習が遅れてしまいます。そこで、queryとkeyの次元が大きいほどlogitが大きくなることに注目して、queryの大きさを次元に従って小さくすることが一般的です。具体的には、

    Alt text

     と調整します。

    2-1-4 output

    最後に、このように得られたattention weightをvalueと掛け合わせることで、出力を決定します。

    Alt text

    以上がこのモデルの基本構造になります。このモデルの要は1-2で触れたquery, key, valueに入力を分け、queryからvalueを導き出す、というところにあります。

    2-2 Attentionの種類

    Attentionには大きく分けて2種類あります。

    1つ目は、inputとmemoryが全く同じデータの場合です。これはSelf-Attentionと呼ばれます。

    2つ目は、inputとmemoryで違うデータを使う場合です。これはSourceTarget-Attentionと呼ばれます。

    Self-Attentionでその言語の構造を学習した後で、SourceTarget-Attentionで新しい文章に対して予測を行うことができる、というイメージです。なのでTransformerモデルも含め、両方のAttentionを組み合わせているモデルがほとんどです。

    2-3 Transformerに付け加えられた工夫

    ここからはAttention is all you needで実装されたTransformerモデルを中心に、基本的なAttentionに加えてどのような工夫がなされているのか、解説していきたいと思います。

    下図の通り、transformerにはattention以外に様々な要素が加え得られています。左側がdecoderと呼ばれる、self-attentionを主に使い文章自体の構造を学習していく部分で、右側がencoderと呼ばれる、self-attentionとsourcetarget-attentionを組み合わせ、新たなmemoryに対するアウトプットを求める部分になります。

    attenntion


    Attention Is All You Needより引用

    2-3-1 Multi-head Attention

    論文では、行くつもの小さなAttentionを並列に繋げると、パフォーマンスが上がったと言われています。それぞれのAttentionをheadと呼ぶので、Multi-head Attentionと呼ばれています。Attention is all you needでは、全体として512次元のtensorが使われていて、この総数はheadの数によりません。head=4ならば各headのデータ次元は128になりますし、head=8ならば64次元になります。

    2-3-2 Masking

    上でAttention weightの計算方法をご紹介しましたが、maskは特定のkeyに対応するattention weightを0にするために使います。入力にあたるlogitに対し、値を-∞に設定することで、softmax時の値が0になります。

    Maskを使う動機は主に

    ・padを無視したい

    ・decoderのself-attentionの段階で情報を先読みできないようにするため

    の2つがあります。

    2-3-2-1 padを無視したい

    Inputやmemoryにおいて、batchごとのトークンの数は様々です。例えば、

    attention

    のように、長さが1, 3, 2 とばらつきがあります。

    そこで長さを揃えるためにpadで埋めることになります。

    Alt text

    しかしattention weightの計算をするとき、padの分は計算から除外したい、と考えます。なぜなら、padの数はbatch内の他の文の長さによって影響されるので、本来干渉するべきでない情報が影響し合うことになるからです。そこで、softmaxの結果を0にして影響を避けよう、というのがmaskの目的です。

    2-3-2-2 decoderのself-attentionの段階で情報を先読みできないようにするため

    Transformerのdecoderでは、self-attentionが行われる部分があります。しかし、新たなアウトプットを予測する部分ですから、自分自身をmemoryにしてしまうと、先の答えが見えているのと同じになってしまいます。今までに得た情報のみで推論するように、先のattention weightを全て0にしてしまいます。

    Alt text

    2-3-3 Hopping / Position-wise Feedforward Network

    このmulti-head attentionを複数組み合わせたり、FFNを挟むことで、さらに学習精度が上がります。Attention is all you needでは、2048次元の中間層と512次元の出力層からなる2層の全結合ニューラルネットワークを使用しています。

    Alt text

    2-3-4 Wrapper

    TransformerにはLayer Normalization, Attention Dropout, Residual Connectionなどの正規化が行われており、これらをまとめてwrapperとして実装しています。これらの措置は主に学習速度を上げたり、学習精度を高めたりするための措置です。

    2-3-5 Positional Encoding

    Attentionは、そのままではトークンの順序を情報として学習に使うことができません。このままでは語順が反映されなくなってしまうので、Positional Encodingを足します。Attention is all you need では、

    PE(pos, 2i) = sin(pos/1000^{2i/d})

    PE(pos, 2i+1) = cos(pos/1000^{2i/d})

    としています。その理由として、相対的な位置(PE{pos+k})をPE{pos}の線形代数で表現できるため、学習がしやすいだろうからです。

    以上、attention及びtransformerモデルについての解説でした。


    アクセルユニバース株式会社(以下当社)では、人が対応している業務を画像認識、音声認識、文字認識等を活用して効率化する機械学習ソリューション開発をおこなっています。
    「機械学習について」機械学習とプロセス


    また、定期的にメルマガでも情報配信をしています。
    ご希望の方は問い合わせページに「メルマガ登録希望」とご連絡ください。

    参考文献

    Attention Is All You Need

    作って理解する Transformer / Attention

    ディープラーニングブログ/論文解説 Attention Is All You Need (Transformer)


    Twitter・Facebookで定期的に情報発信しています!

    クラスタリングとは

     クラスタリングとは、異なる性質を持った多くのデータから類似性を見て自動的に分類する、機械学習の教師なし学習における手法のこと。(複数のコンピュータを連動させることにより、1台のコンピュータとして利用できるようにする技術を言うこともある)
     マーケティングでは、顧客層の特性分析や店舗取り扱い商品の構成分析に利用されており、多くの顧客や商品を分類し、どのような顧客が多いのかを明確にし、ターゲットを決定する。

     クラスタリングとクラス分類は混同しやすいが、別々のものである。大きな違いは、クラスタリングは教師なし学習で、クラス分類は教師あり学習という点である。
    教師あり学習であるクラス分類は、どのグループに属するかという"ラベル"がついている既知データが手元にあり、それを用いてモデルを作って、"ラベル"がついていないデータの分類に用いるという手法であることに対し、
    教師なし学習であるクラスタリングは、ラベル付きデータがない状態で、あるデータを分類するような手法である。

    クラスタリングの手法の種類

     クラスタリングはデータ同士が「似ている」、「似ていない」かを基準に分類する。この「似ているかどうか」という尺度は人間の感覚的な部分があるため、これまで多くの研究者が様々な手法や考え方を提唱してきた。それらは未だ一本化されておらず、ここではその種類を紹介する。

    1. 「階層的クラスタリング」と「非階層的クラスタリング」
    2. 「ハードクラスタリング」と「ソフトクラスタリング」

    image

    階層的クラスタリング

     階層的クラスタリングとは、 各データを1つのクラスタとして、最も似ている2つのクラスタを合併すること(近いものから順番にくくる)を繰り返していく手法。最終的にクラスタが1つになるまで合併を繰り返す。(※1)

    image (※1)

     クラスタの合併をしていくと、樹形図のようなデータの階層構造が得られ、デンドログラムで表現することができる。(※2)

    image (※2)

    非階層的クラスタリング

     非階層的クラスタリングとは、事前にいくつのクラスタに分けるかを決め、サンプルを決めたクラスタ数に分割していく手法。階層的でないクラスタリングである。そのため、木構造のデンドログラムでは表現されない。階層的クラスタリングでは分類するデータが多いと、計算量が多くなってしまったり、階層構造が複雑になってしまったりする。それに対して非階層的クラスタリングは、分類するデータが多くなってしまう場合でも対応することができる。

     また、非階層的クラスタリングの代表的な手法はk-meansという手法である。

    image

    ハードクラスタリング

     ハードクラスタリングとは、各データが1つのクラスのみに所属するようなクラスタリング。

     一般的にクラスタリングといえばハードクラスタリングをさす。

    image

    ソフトクラスタリング

     ソフトクラスタリングとは、各データが複数のクラスタに所属することを許すようなクラスタリング。   image

    あとがき

     今回は、クラスタリングとはどんなものなのかについて広く浅く扱ってきた。

     次回は、今回詳しく説明することができなかったk-means、ウォード法、メディアン法など、クラスタリングの手法の種類の一つ一つをより具体的に説明していく。

    (2019/11/28 追記)
    k-means法について

    ニューラルネットワークとは

     ニューラルネットワークとはAI (人工知能)のうちの一つ。また、AIの一つである機械学習のうちの一つでもある。(図1)また、人間の脳内にある神経細胞(ニューロン)とそのつながり、つまり神経回路網を数理モデル化したもの。(図2)

    image(図1)

     ニューラルネットワークを構成している最小単位は、パーセプトロン(単純パーセプトロン)という。パーセプトロンとは、複数の入力に対して1つの値を出力する関数のこと。パーセプトロンへの入力値を(X1~Xn)とすると、それぞれの入力に対して重み(W1~Wn)が存在する。また、バイアスW0が存在する。

     f(x)(それぞれの入力値(X1~Xn)に対して重み(W1~Wn)を掛け合わせ、それにW0を足したもの)の値が0より大きい場合は1が出力され、0より小さい場合は0が出力される。(図2)f(x)が0より大きくなり1が出力されることをニューロンの発火という。発火のしやすさはバイアス(W0)によって決まり、バイアス(W0)は発火のしやすさを調整する役割をすると言える。

     図のように1つのパーセプトロンは単純パーセプトロンといい、単純パーセプトロンを複数組み合わせたものを多層パーセプトロンという。単純パーセプトロンを複数組み合わせて多層パーセプトロンにすることで、より複雑な関数近似を行うことができ、出力の精度を高めることができる。   image(図2)

     (図2)において

    f(x) < 0 → 1

    f(x) = 0 → 0 or 1

    f(x) > 0 → 0

    のような数式は活性化関数といい、ニューラルネットワークやパーセプトロンで用いられている、モデルを表現するための関数である。活性化関数を用いて変換を行うと様々な値の出力が行え、モデルの表現力を高めることができる。​

     パーセプトロンにおいてはステップ関数、ニューラルネットワークではシグモイド関数が主に使われている。

    image(図3)

    (シグモイド関数はステップ関数を連続的に表現したもの)

     ここで1つ指摘しておきたいのは、単純パーセプトロンを複数組み合わせてできた多層パーセプトロンはほぼニューラルネットワークと言うが、等しいわけではないということである。多層パーセプトロンはステップ関数を用いているが、ニューラルネットワークはシグモイド関数を用いているという点で違いがある。

    ニューラルネットワークの構造

    image(図4)

    (画像や音声などの情報も数値として入力する)

     ニューラルネットワークは、入力層、中間層、出力層の3つから成り立っている。入力層は人間の脳で言う感覚層、出力層は判別層、中間層は情報の処理を行っている部分に置き換えることができる。

     ニューラルネットワークの入力層と中間層、中間層と出力層の間にはニューロン同士のつながりの強度を示す強度W(重み)というものが存在する。ニューラルネットワークでは、この重みを調節することによって、入力したものに対して望む出力(教師データ)に近づけることができる。

    ※中間層が2層以上のニューラルネットワークをディープラーニングという​

    ニューラルネットワークの種類

     ニューラルネットワークには様々な種類がある。その中でも特によく使われているのが次の3種類である。

    1. RNN(再帰型ニューラルネットワーク)
    2. CNN(畳み込みニューラルネットワーク)
    3. LSTM(Long Short Term Memory)

    RNNとLSTMの違い

     (今回は一つ一つを説明することができないため、詳しい内容は別の記事で扱っていく)

     1. RNN(再帰型ニューラルネットワーク)

     再帰型ニューラルネットワーク(Recurrent Neural Network)は主に自然言語処理の分野で使われている。

     それまでのニューラルネットワークでは、入力値は互いに独立したものである必要があった。この場合、画像処理などでは問題ないが言語のように入力値に連続性がある場合は適さない。そこで、RNNでは中間層にループを組み込むことによって前のデータの入力を記憶できるようにした。そのことによって前後のデータが関連付けられるようになり、自然言語処理などの時系列データにも対応できるようになった。RNNは主に、機械翻訳、文章生成、音声認識などに使われている。

    image(図5)

     2. CNN(畳み込みニューラルネットワーク)

     畳み込みニューラルネットワーク(Convolutional Neural Network)は一般的なニューラルネットワークと違い、畳み込み層とプーリング層でできている。

     ここでいう畳み込みとは、簡単に言うと画像の特徴を際立たせることである。画像全体から様々な特徴を取り出していき、画像全体をそのまま分析するのではなく、画像より小さなフィルターを画像全体にスライドさせながら、部分部分で分析していく。フィルターを複数枚使って様々な特徴を抽出していく。そして、畳み込み層で抽出した特徴をもとに特徴マップを作成する。

     プーリング層では、特徴マップの要約を行う。特徴マップを小さなウィンドウに区切り、区切ったウィンドウ内の最大値をとっていく。プーリングを行うことによって、特徴の厳密な位置の変化を気にすることなく画像内での特徴を検出することが可能になる。これは、移動普遍性と呼ばれ、画像認識にCNNが向いている大きな理由の一つである。実際のCNNは畳み込み層とプーリング層が何層にも重なってできている。

     プーリング層の後に、多次元のデータを1次元のデータにフラット化していき、ソフトマックス法を用いて分類し、出力していく。​

    image(図6)  

     3. LSTM(Long Short Term Memory)

     先ほどのRNNには複雑な構造が故に1つ問題があった。RNNでは入力したデータは全て記憶されてしまい、必要でないデータも記憶してしまうということがあった。そこで、LSTMでは情報を忘れる機能が追加された。それによって、「この情報は必要」と「この情報は必要じゃない」という判断ができるようになった。

     それまでRNNが苦手としていた予測情報と関係情報の距離が長いケースでもLSTMで対処できるようになった。これにより、機械翻訳の精度が飛躍的に向上した。

    image(図7)

    ニューラルネットワークによって可能になること

     ニューラルネットワークでは、主に以下のことが可能になる。

    1. 画像認識...主にCNNを用いる
    2. 音声認識...主にRNNを用いる
    3. 自然言語処理...主にRNNを用いる
    4. 異常検知...主にCNNを用いる

    回帰分析とは

    先ず回帰分析とは、あるp個の変数Alt 最小二乗法が与えられた時、それと相関関係のあるyの値を説明、予測することである。ここで変数xを 説明変数 、変数yを 目的変数と呼ぶ。p=1、つまり説明変数が1つの時を単回帰、またp>=2、つまり説明変数が2つ以上の時を重回帰と呼ぶ。

    単回帰分析

    今回はp=1と置いた 単回帰分析 について説明する。

    このとき、回帰式は y=ax+b(a,bは 回帰係数 と呼ばれる)となり直線の形でyの値を近似(予測)できる。

    単回帰分析のデメリットとして知りたいデータを直線で近似してしまうため、精度が良くないと得られるデータに大きな誤差が生じてしまう。

    しかしデータのおおよその値が視覚的に分かるため、データの大概を掴むことができ非常に便利な分析手法の1つである。

    例として、ある店舗での来店者数(来場者数)について興味を持ったとしよう。ここで広告費(宣伝費)と来場者数について以下のような散布図が得られたとする。

    Alt text

    この散布図を見ると、グラフに弱い人でも「宣伝費が高ければ来場者数が増える」と読み取れるだろう。

    そこでパラメータa,bをうまく決定し( 最小二乗法 による)、下図のように直線を引けたとしよう。

    Alt text

    グラフからも分かるようにデータは正しい値を取るわけではない、つまり厳密に最小二乗法とはならないことに留意せよ。

    そこで後で説明する最小二乗法によって、パラメータa,bをうまく決定するのである。

    最小二乗法

    最小二乗法とは、誤差を伴う測定値の処理において、その誤差(残差)の二乗の和を最小にすることで最も確からしい関係式を求めることである。

    Alt text

    プロットされた各点(xi, yi)における回帰式( y=ax+b)との残差の和が最小となるようにパラメータa,bを決定したい。

    回帰式 y=ax+b にi番目のxの値を代入して得られるy(予測値)を、

    最小二乗法

    とする。

    そこでi番目のデータについての残差(実測値と予測値との差)をε_iと置くと、

    最小二乗法

    となる。このままだと残差の符号にばらつきが出るため扱いづらい。そこで残差の2乗和について考える。(サンプルサイズはnとしている)

    最小二乗法

    この式はパラメータ(a,b)の関数であり、最小二乗法によりこの残差の二乗和が最小となるようなパラメータ(a,b)を求める。

    最小化の一階条件として上式をa,bでそれぞれ偏微分した値が0となる性質がある。先ず偏微分すると、

    最小二乗法

    最小二乗法

    これより一階条件は、

    最小二乗法

    最小二乗法

    となる。一般的にこの二本の方程式は 回帰の 正規方程式 と呼ばれている。

    二本目の式より、最小二乗法を得るので、

    最小二乗法

    となる。これより、

    最小二乗法

    を得るが、これより y=ax+b が定点最小二乗法を通ることがわかる。

    改めて、中心化した変数及びデータ、

    最小二乗法

    を用いると、

    最小二乗法

    最小二乗法

    然るに、残差平方和をbを含まない式に書き換えることができる。

    最小二乗法

    よってaで偏微分して、残差平方和を最小にするaを求める。これをAlt textと書くことにする。

    最小二乗法

    最小二乗法

    が得られたことになる。

    決定係数

    次に、求めたパラメータa,bに対して、目的変数yが説明変数xによってどれだけ説明されているかを検証してみる。

    モデルの当てはまりが悪ければ、説明変数を追加するなどして、モデルを改良するための一つのインデックスとなる。

    今回は、モデルの当てはまりの良さを表す指標の一つとして、 決定係数 を導出する。

    決定係数とは、上で導出したパラメータa,bを持つ回帰式の精度を表す値である。

    一般に決定係数は、

    最小二乗法

    で定義される。第二項の分母は全変動と呼ばれ、データそのもののばらつき具合を表しており、分子は残差変動と呼ばれ、回帰モデルと実測値とのズレを表している。

    即ち、決定係数が1に近いほど残差変動が小さいということであり、良い予測が出来ていると判断される。

    関連するTheoremとして、「最小二乗法による直線フィッティングの場合、相関係数の二乗と決定係数は一致する」というものがある。

    今回はこの証明は割愛するが、 こちらのサイト から是非確認してほしい。

    参考文献

    最小二乗法の意味と計算方法 - 回帰直線の求め方

    線形回帰分析入門〜最小二乗法から決定係数まで

    LSTM(Long Short Term Memory)は音声認識など、様々な場面で使われるモデルなのですが、意外と歴史のあるモデルでもあります。今はattention等に押されている感はありますが、通常のRNNを大きく改善したと呼ばれる、学ぶ価値のあるモデルです。ここでは、RNNとの違い、実際の仕組みを解説していきたいと思います。

    1 RNN

    LSTMはRNNの一種ですが、通常のRNNが情報をそのまま次に引き継ぐのに対し、LSTMでは中間層を噛ませて次に渡しています。

    Alt text

    従来のRNNは、一度データを通して得た情報を、次のインプットと一緒に後続に渡す仕組みでした。

    Alt text

    Long Short-Term Memoryより引用。

    しかしこのモデルでは、長期依存性の問題があります。昔の情報を現在まで保持するのが難しいため、文章などのデータを適切に処理できないのです。関連する情報とそれが必要になる場面が離れていれば離れているほど、RNNはこれらを上手く繋げることができないのです。

    Alt text

    Long Short-Term Memoryより引用。

    LSTMはこの問題を解決するために開発されました。

    2 LSTMの仕組み

    では、LSTMの具体的な仕組みについて解説していきます。以下に二種類の図がありますが、この二つの図が同じものを表していることがわかるでしょうか。これがわかれば、今回の目標は半分達成です。

    Alt text

    Long Short-Term Memoryより引用。

    Alt text

    これらの図は、1999年に開発されたバージョンで、chainerのLSTMに実装されているものです。

    ではステップごとに見ていきましょう。この順番は便宜上のものであり、計算が前後しても大丈夫な部分もありますが、例えばOutput Gateに必要なインプットはForget GateとInput Gateで計算されるので、そういった部分は順番に注意する必要があります。

    2-1 Forget Gate

    一つ目の部品は、Forget Gateと呼ばれる、文字どおり「忘れる」ためのゲートです。これは実は1997年のオリジナルのLSTMモデルにはない部分で、インプットが大きく変わる際、一度メモリセルで記憶した内容を一気に「忘れる」ことを学習します。

    一つ目の図で言うと、下図のようになります。

    Alt text

    Long Short-Term Memoryより引用。

    二つ目の図では、

    Alt text

    Long Short-Term Memoryより引用。

    という式によって表現されています。(とりあえずp_forの項は無視してください)

    2-2 Input Gate

    二つ目のステップは、その段階の新しいインプット(xt)を処理するゲートです。古いリカーリングインプット(y{t-1})と新しいインプット(xt)をそれぞれシグモイド関数とtanh関数にかけ、XORすることで、新たな候補値のベクトル(C^~t)を計算します。そして、この新たな候補値を、forget gateに古い候補値(C_{t-1})をかけたものに足します。

    一つ目の図で言うと、

    Alt text

    Alt text

    Long Short-Term Memoryより引用。

    二つ目の図で言うと、

    Alt text

    Alt text

    Alt text

    になります。

    少しややこしくなりますが、最後の式を見ると、インプットを処理して得たCに、古いCの中でforget gateが残すべきと判断したものを足し合わせる、という仕組みになっていることがわかります。

    2-3 Output Gate

    最後のデートは、出力を処理するためのゲートです。他のゲートと同様にインプットをシグモイド処理した後で、セル状態(C_t)をtanh関数で処理したものと掛け合わせる構造になっています。

    一つ目の図でいうと、

    Alt text

    Long Short-Term Memoryより引用。

    二つ目の図で言うと、

    Alt text

    Alt text

    になります。

    LSTMは、主にこの3種類のゲートで成り立っています。一つ一つのゲートにおける仕組みは、図や式で表現されている通りですが、今一度まとめると、

    LSTMの特徴は

    ・y_{t-1}という古いアウトプットを次の段階でインプットとして使用する、というRNNの構造を保ちつつ

    ・C_{t-1}という長期記憶を少しずつ変えていく

    という2点で、それを

    ・Forget Gate(古いC_{t-1}のうちどの部分を忘れるか)

    ・Input Gate(新しいインプットと一つ前のアウトプットを組み込む)

    ・Output Gate(更新された長期記憶を再度処理してアウトプットを作る)

    の3つのゲートで管理しています。

    ここで疑問となるのが、

    なんで入力と出力にややこしいゲートがあるの?

    という点です。必要以上にややこしいというのは、その通りです。しかし、これには理由があります。

    2-4 入力ゲートと出力ゲートの意味

    実は、このややこしいゲートは重みを上手く調節するために存在しています。一般的なRNNでは、ユニットiからの出力が重みw_{ij}をつけてユニットjに入力されます。しかし、時系列データを使うと従来の方法ではこの重みが相反する2つの作用によって上手く更新されない、そのような事態が起きていました。具体的には

    ・ユニットを活性化されることによる入力/出力信号の伝達

    ・ユニットからの無関係な入力/出力によってユニットが消去されることを防ぐを入力/出力信号の保護

    の二つの更新が同時に行われる場合があるのです。これを防ぐために、一見ややこしく不必要な入力ゲート・出力ゲートがLSTMに付けられているのです。

    2-5 様々なLSTM

    LSTMにも様々なバージョンがあり、実際には仕様によって少しづつ違います。その中でも比較的重要なものを一つご紹介したいと思います。

    上でも記したように、LSTMは「忘却する・入力する・出力する」という3つのゲートで成り立っています。しかし、制御対象であるメモリセルの内部状態(C_t)それ自体は制御に使用されていませんでした。そこで、peephole connectionと呼ばれる接続を各ゲートに流し込むことで解決を図りました。

    Alt text

    上の図の青い線がpeephole connectionにあたります。ご覧の通り、各ゲートに青い線でメモリセルの内部状態(C_t)が流れ込んでいるのがわかると思います。上の式で説明されていなかった項の正体は実はこのpeephole connectionです。

    (もっと知りたい人向け)

    ・LSTMのBack Propagation (逆伝播)

    ・Gradient Clipping

    ・Constant Error Carousel (CEC)

    参考文献:

    LSTMネットワークの概要

    わかるLSTM ~ 最近の動向と共に

    Long Short-Term Memory


    ここでは今は去りしデータマイニングブームで頻繁に活用されていた決定木について説明する。理論的な側面もするが、概念は理解しやすい部類であるので参考にしていただければと思う。

    1 決定木(Decision Tree)

    決定木とは木構造を用いて分類や回帰を行う機械学習の手法の一つで段階的にある事項のデータを分析、分離することで、目標値に関する推定結果を返すという方式である。データが木構造のように分岐している出力結果の様子から「決定木」との由来である。用途としては「意思決定のためのデータモデリング」「機械学習としての予測への活用」が挙げられる。

    Decision_tree_model_ja.png

    また、決定木の構成方法には、ボトムアップ的な方法とトップダウン的な方法の2種類がある。前者はある学習データを正しく判別するための識別ルール(条件式)を作成してその制約を緩めながら他の学習データも正しく判別するためのルールを汎化していく方法である。一方で後者は根ノードでできるだけ誤りの少ないように分割するルールを求めて、その後のノードでも同様に2分割するルールを次々と求めていき成長させる方法であり、分割統治法と呼ばれる。ここでは主流となっているトップダウン的な方法について記載していく。

    トップダウン的な方法で決定木を構成するためには、次の要素について考える必要がある

    1. 各ノードにおける特徴軸と閾値の選択
    2. 終端ノードの決定(学習データがすべて分割されるかその前に止めるのか、また木の選定を行う)
    3. 終端ノードに対する多数決でのクラスの割り当て

    ここでトップダウン的な方法で学習する代表的な方式は3つあり(CART、ID3、C4.5)、中でも今回説明するCARTは以下の2つに大別される。

    • 分類木(Classification Tree)→対象を分類する問題を解く(分類カテゴリーは2つ)(例:性別(男/女)、試合の結果(勝ち/負け)の判別)
    • 回帰木(Regression Tree)→対象の数値を推定する問題を解く(例: 住宅の価格の見積り、患者の入院期間の見積りなど)

    分類木(Classification Tree)

    分類木は1つまたは複数の測定値から、あるデータがどのクラスに属しているのかを予測するために使用される。主にデータマイニングに利用されている技術である。データをパーティションに分割してから、各ブランチに更に分割するというプロセスを反復する。最終的にどのクラスに分類されたのかの判別は、終端ノードで行う。

    ○具体例

    今回は購入者(Puchaser)と非購入者(Non-Puchaser)を分類する分類木を例に挙げる。先ず、各データについて分類ラベル(Puchaser/Non-Puchaser)が事前に分類されているデータセットを用意する。次に2つのノードに対してある条件式を元に各データを割り当てる。(図ではincome<=$75,000かincome>$75,000で判定)その後、次のノードに割り当てる際にも別の条件を元に分割を適用していく。この分割の操作はこれ以上有用な分割ができなくなるまで行われる。(木の成長は以下の説明「木の剪定」、分割方法は「不順度」にて説明)

    Classification Tree.png

    回帰木(Regression tree)

    矩形内で一定の推定量をとる回帰関数である。 矩形は,(標準的な) ヒストグラム の場合とは異なり,その大きさが同じである必要はない。 回帰木は,ルールを2 分木として表現できるという独特の特徴がある。この特徴により,多くの説明変数がある場合にも推定値のグラフ表現を可能にする.

    1.1 決定木の各種定義

    tree.png

    上図のノード全てに対して幅優先順(breadth first)で1からナンバリングして(これをノード番号とする)0でない整数の集合をTとする。またleft()、right()をそれぞれ2分岐したときの左側、右側のノード番号を与える関数とすると次の2つの性質を満たす。

    1. 木Tに属する各ノードtについて、left(t)=right(t)=0(終端ノード)か、left(t)>t,right(t)>t(非終端ノード)のどちらかを満たす
    2. 木Tに属する各ノードtについて、根ノードを除いてt=left(s)もしくはt=right(s)のどちらかを満たすsが一つ存在する。ここでsを親ノード、tを子ノードといい、s=parent(t)で表す。

    ざっくりと説明すると木を構成するノードはどのクラスに割り当てるかを決める終端ノードとそれ以外の非終端ノードによって構成され、非終端ノードの分割先は多くても左側と右側に一つしか作成されず他のノードと合流することはないという意味である。

    上記でも説明したようにノードのナンバリングは幅優先で行うため、right(t)=left(t)+1が成り立つ。またtからsへの一意のパスの長さをl(s,t)=mで定義する。

    木Tの終端ノードの集合をmath-20190705.pngとすると、差集合math-20190705 (1).pngが非終端ノードの集合となる。

    またTの部分集合をmath-20190705 (13).pngとし、以下の式との組み合わせが木となる場合に部分木となる。

    math-20190705 (2).png

    わかりやすいように上の図を使って説明をすると、math-20190705 (13).png={2,4,5}は上記式を満たすので、Tの部分木となる。一方でmath-20190705 (13).png={2,4,5,3,6,7}は親がいないため、部分木とはならない。また、部分木の根ノードがTの根ノードと等しい場合はmath-20190705 (13).png剪定された部分木と呼ぶ。また任意のtとその子孫全てで構成される部分木を分枝と呼ぶ。

    各終端ノードはそれぞれ一つの分割領域u(t)に属する。決定木では、各領域u(t)に特定のクラスを割り当てることで、入力データのクラス分類を行う。ここでクラスをmath-20190705 (14).pngとしたときに、終端ノードが表すクラスの事後確率を以下のように計算する。

    クラスラベルのついた学習データ集合をmath-20190705 (3).pngとする。(木のノードと混ざりやすいが添字がついている方を学習データとする)クラスjに属する学習データ数をmath-20190705 (4).pngとすると、クラスjの事前確率

    math-20190705 (5).png

    となる。特徴空間はノードで分割ルールを経るごとに分割されていく。あるノードtに属する学習データの数をN(t)とし、j番目のクラスに属するデータをmath-20190705 (6).pngとする。必ず一つのクラスに属するのでmath-20190705 (7).png

    となる。j番目のクラスの学習データがノードtに属する確率が

    math-20190705 (8).png

    であることからそれらすべての同時確率

    math-20190705 (11).png

    となる。上記式より周辺確率は、

    math-20190705 (9).png

    となるので、tにおけるj番目のクラスの事後確率は、

    math-20190705 (10).png

    となる。よってノードtにおけるクラスの識別は上記式の事後確率が最大となるクラスを選択すれば良いので

    math-20190705 (12).png

    となる。

    1.2 ノードの分割ルール(不順度)

    各ノードにおいて最も推定精度を向上させるための分割方法は、不順度と呼ばれる評価関数で評価することで選択する。学習データがN個であれば、N-1個の分割候補点がある。また、となり合った2点間の中間を候補点の一つとすれば、それはカテゴリー数だけ存在する。これらの中で選択される候補点は以下の式で計算される不順度に基づいて決定する。

    ○計算方法

    ここであるノードtにおける不順度をI(t)とすると

    math-20190723 (7).png

    ただし、math-201907011.png

    math-201907012.png:クラスiに属するトレーニングサンプルの総数

    N:トレーニングサンプルの総数

    ここで、上記関数math-201907014.pngmath-201907015.pngに対して次の3つの性質を満たす。

    • math-201907016.pngは、すべてのiに対してmath-201907017.pngのとき(どのクラスの事後確率も一様に等しい)最大になる。
    • math-201907016.pngは、あるiについてmath-201907018.pngのみを満たすとき、(ただ一つのクラスに定まる)最小になる。
    • math-201907016.pngは、math-201907019.pngに関して対象である。

    代表的な不順度

    ノードtにおける誤り率(error rate)

    math-20190723 (6).png

    交差エントロピー、逸脱度(deviance)

    math-20190723 (5).png

    ジニ係数(Gini index)

    math-20190723 (4).png

    以上の①〜③のいづれかの方法を用いて不順度を計算し、不順度の減り方(勾配)が最も大きな分割を選択する。

    特に③のジニ係数はCARTで用いられることが推奨されている(参考文献[4]より)。ノードtでi番目のクラスのデータが選ばれる確率とそれ以外のクラスに間違われる確率の積をすべて足し合わせる式となっているため、ノードtにおける誤り率となっている。この誤り率の減り方(勾配の計算で求める)が最大となる分割点を分割可能なすべての候補点の中から選択すれば良い。

    1.3 木の剪定

    剪定とは作成された木構造の一部分を削ることで木構造を簡易化して汎用性を保つ方法である。決定木は訓練データに基づいており、学習と分割が進みすぎると木が成長しすぎてしまい汎用性が低下してしまう。(学習データを判定する際に全く通用しなくなってしまう可能性が高くなる)そのため、決定木を作成する際には、推定精度が高く、かつ汎化性を保った木を作成するためには、ある程度の深さで木の成長を止めることが必要である。

    ○計算方法

    木を構成した学習アルゴリズムに対して再代入誤り率を計算する。

    終端ノードmath-20190708 (4).pngにおける誤り率は

    math-20190708 (2).png

    M(t):終端ノードtにおける誤り数

    N:総学習データ数

    となる。(この誤り率は前節のジニ係数や逸脱度の値を用いても良い)

    したがって木全体(終端ノードすべて)の再代入誤り率の推定値は、

    math-2019070116.png

    となる。

    木構造の複雑さを終端ノードの数と再代入誤り率で評価する。

    ある終端ノードにおける誤り率と複雑さのコストの和

    math-2019070117.png

    math-2019070118.png:一つの終端ノードがあることによる複雑さのコスト(正規化パラメータ)

    したがって木全体のコストは、

    math-20190708 (3).png

    となる。この値が最小となるよう終端ノード数を調整する。しかしながら終端ノードが多くなるほど誤り率R(T)が高くなり逆に終端ノード数が減るほど誤り率が低くなる。そこでこの複雑さのコストが2つの要素の間のバランスを取る正規化パラメータ(調整パラメータでもある) の役割を果たしている。例えばこの値が小さくなると終端ノードを増やす方向に向かうため、大きな木が好まれる。

    ノードtにおける再代入誤り率は、最大事後確率で決まるため、前節のノードtにおける誤り率と同じになる。つまり、

    math-20190708 (5).png

    である。またノードtに学習データが属する確率をp(t)とすれば、

    math-20190708 (6).png

    と書くことができる。

    あるノードtを根ノードとする分枝(tのすべての子孫で構成される部分木のこと)をmath-20190708 (7).pngとする。もし、math-20190708 (8).pngならばtを終端ノードとしたときの木のコストより分枝を持っている方が小さいということになるので、分枝を残したほうが全体のコストは小さくなる。しかし、正規化パラメータの値を大きくするにつれて誤り率と複雑さのコストの値が等しくなり、その値は

    math-20190708 (9).png

    で与えられる。つまり、ノードtを残そうが剪定しようがコストは変わらないので、木が小さくなる方を優先するとして選定してしまって良いことになる。そこで、この正規化パラメータをtの関数とみなして

    math-20190708 (10).png

    と定義する。木の剪定はすべてのノードに対してこの値を計算し、

    math-20190708 (11).png

    とする。最小値をとるすべてのノードを終端ノードとし、その子孫を削除して木を剪定する。この操作を根ノードのみになるまで行う。

    以上が剪定アルゴリズムであるが、再代入誤り率は剪定を進めるほど大きくなるため、どこで止めるべきかの情報が与えられていない。そのための基準を設ける必要があるがその方法としてホールドアウト法や交差確認法がある。しかしながらこれらは明確な基準値が設けられているわけではなく経験的にルールを設定することで基準作りを行っている。

    2 応用

    2.1 バギング(bagging)

    bagging.png

    複数の決定木を組み合わせる方法の一つとしてバギングがある。Bootstrap AGGregatINGから派生しており、学習データのブートストラップサンプルを用いて複数の木で学習させ、それらの木で求めた結果に基づいて多数決で決定するという方法である。ブートストラップサンプルは学習データから重複を許したサンプリング(普通は学習データの数と同じだけ)を行い、新たな学習データを作製する、といった作業を木の数だけ繰り返す手法である。それぞれの木の判別性能はランダム識別より少し良ければ良いので弱識別器と呼ばれる。一つの決定木だけだと学習データに識別性能が大きく依存してしまうが、複数の結果の多数決を取ることでより安定で性能の良い判別器を構成することができる。一方でそれぞれの弱識別器はブートストラップサンプルに依存した性能であり、相関が高い性能になってしまうと、並列させるメリットが薄まってしまう。このような欠点を補うのが次節で説明するブースティングランダムフォレストである。

    2.2 ブースティング(boosting)

    adaptive_boosting.png

    バギングは複数の弱識別器を並列に学習させていくが、ブースティングは直列的にし、前の弱識別器の学習結果を参考にしながら一つずつ弱識別器を学習する方法である。学習データは次の弱識別器にとって最も有益なものが選択される。代表的なブースティングアルゴリズムにアダブースト(adaptive boositng)がある。アダブーストは弱識別器の学習結果に従って学習データに重み付けが行われ、誤った学習データに対する重みを大きくして、正しく判別された学習データに対する重みを小さくすることで、後に学習識別器ほど、誤りの多い学習データに集中して学習するようにする方法である。

    学習アルゴリズム

    学習データ、教師データ、重み、弱識別器をそれぞれmath-201907080.png,math-201907081.png,math-201907082.png,math-201907083.png,math-201907084.pngとする。このときアダブーストのアルゴリズムは以下のようになる。

    (1)重みをmath-201907085.pngに初期化する。

    (2)math-201907086.pngについて以下を繰り返す

      (a)識別器math-201907087.pngを重み付け誤差関数

         math-201907088.png

         が最小となるように学習する。math-201907089.pngは識別関数の出力が一致した場合0、一致しなかった場合1となる指示関数である。

      (b)識別器math-201907087.pngに対する重みmath-2019070810.pngを計算する。

        math-2019070811.png

      (c)重みを次のように更新する。

         math-2019070812.png

    (3)入力xに対する識別結果を、

       math-2019070813.png

       に従って出力する。ただし、sign(a)は符号関数でありa>0なら+1、a=0なら0、a<0なら-1を出力する。(多数決)

    (2)(a)は誤った学習データの正規化された重みの和である。これは誤差が小さいほど大きな値を取る。したがって誤りの小さなmath-201907087.pngに大きな重みを与える。また重みの更新では、誤った学習データの重みがexpmath-2019070810.png倍される。正しく判別されると重み付けはされないが、先程の(2)(a)の式で正規化されるため、相対的に小さくなっていく。また、弱識別器の数Mは多すぎると過学習が生じてしまうので、木の選定と同様に交差検証法などで選ぶ必要がある。

    2.3 ランダムフォレスト(random forests)

    randomforest.png

    バギングは前節で説明したように、決定木のような分散が大きな識別器に適した方法であるが、ブートストラップサンプリングによるため生成された決定木の相関が高くなってしまう。一般的に、分散math-2019070814.pngを持つM個の独立な確率変数math-2019070815.pngの平均

    math-2019070816.png

    の分散は

    math-2019070817.png

    であるが、2つの間に正の相関がある確率変数の場合には、平均の分散は、

    math-2019070819.png

    サンプル数Mを多くすれば上記式の第一項は無視できるが第2項は変化しない。ランダムフォレストはこの第2項のmath-2019070818.pngを減少させる仕組みを取り入れたバギング手法の一種である。決定木の各非終端ノードにて判別に用いる特徴をランダムの個数選択することで、相関の低い多様な決定木が生成されるようになっている。

    学習アルゴリズム

    (1)について以下を繰り返す

       (a)N個のd次元学習データ(入力データx)からブートストラップサンプルmath-2019070820.pngを生成する。

       (b)math-2019070820.pngを学習データとして、以下(ⅰ) 〜(ⅲ)の手順によって各非終端ノードtを分割して決定木math-2019070821.pngを成長させる。

          (ⅰ)d個の特徴からランダム個数d'を選択する。(一般的には平方根を四捨五入した個数が望ましいが問題によって最適は異なるので都度調整したほうが良い)

          (ⅱ)d'個の中から、最適な分割を与える特徴(ランダム)と分割点を求める(不順度より判断)。

          (ⅲ)ノードtを分割点でleft(t)、right(t)に分割する。

    (2)ランダムフォレストmath-2019070822.pngを出力する。

    (3)入力データに対する識別結果math-201907087.pngを出力する。2クラス分類なら01で判断し、多数決でランダムフォレストの識別結果を選択する。

    SVMやアダブーストが2クラス分類の識別器であるのに対して、ランダムフォレストは多数決によって多クラスの分類に容易に拡張が可能である。一方でデメリットとして各決定木で学習を進める際に、データが少ないと過学習になりやすくなってしまうという点がある。

    3 シミュレーション

    決定木アルゴリズムCARTを用いた性能評価をAzure MLで行う。評価は以下の2点である。

    • 森のサイズと推定精度

    各アルゴリズムで使用する決定木の数を調整し、推定精度にどのような影響が生じるのか評価した。それぞれで作成したモデルは次節で説明する。

    • 学習曲線

    学習データの数を調整し、推定精度にどのような影響が生じるのか評価

    3.1 シミュレーション1(森のサイズと推定精度)

    ブースティング、ランダムフォレストを用いると、森のサイズ(決定木の数)による推定精度の変化を評価することができる。一般的に森のサイズが大きいほど分散が小さくなるので推定精度は良くなることが予想される。以下でモデルの作成に関する説明を述べる。

    モデルの作成

    下図のフレームワークを用いてそれぞれのシミュレーションを行う。各フェーズについて説明する。

    framework1.png

    フェーズ1 データセットの整形

    データセットはAzure MLに標準で用意されている「2Adult Census Income Binary Classification dataset.csv」を使用している。属性として年齢、学歴、収入などの特徴軸があり判定対象は「性別」とし、サンプル数を10000用意している。

    class.png

    「Select Columns in Dataset」ではage,education,occupation,race,sex,hours-per-week,income,workclassをcolumnとして選択し、「Clean Missing Data」で"Null"のサンプルを取り除き以下の図のようにつなぐ。

    phase1.png

    フェーズ2 データの学習とテスト

    フェーズ2では各アルゴリズムの学習とテストを行うモジュールで構成される。はじめに「split data」でデータセットを学習データ100個とテストデータ9900個に分割する。次にブースティング「Two-Class Boosted Decision Tree」及びランダムフォレスト「Two-Class Decision Forest」と「train model」を用いて「性別」の判定に関する学習を行う。ここで、それぞれのモジュールにて木のサイズを1〜100まで(計16種類)を設定する。学習させたモデルに対して「split data」からテストデータを「score model」に読み込ませ、以下の図のようにそれぞれつなぐ。

    ○ブースティング

    phase2-1.png

    setting2-1.png

    ○ランダムフォレスト

    phase2-2.png

    setting2-2.png

    フェーズ3 評価と結果の統合、csvファイルへの出力

    フェーズ2で行った学習とテストに基づいて「evaluation model」で予測精度の評価を行う。評価を行った後はそれぞれの森のサイズで行った値を集計するため「add rows」でデータの統合を行う。

    phase3.png

    すべてのデータの統合が完了したら、エクセルにてグラフの作成を行うため、「convert to csv」によりcsvファイルへのエンコーディングを行う。

    phase33.png

    シミュレーション結果

    決定木の数に応じた推定精度評価.png

    シミュレーション結果は上記のようになった。学習したデータセットによってそれぞれのアルゴリズムの予測精度は大きく変化するが、今回の結果としては森のサイズが小さいときにはブースティング、森のサイズが大きくなるほどランダムフォレストの予測精度が高いことがわかる。特にブースティングは森のサイズが大きくなることによる予測精度の向上が見受けられなかった。これは誤りやすいデータと誤りにくいデータの相関が大きくアルゴリズムの特性を活かすことができなかった点が考えられる。一方でランダムフォレストは森のサイズが大きくなるほど予測精度は良くなっているが、68%付近にて飽和している。これ以上の予測精度の向上には属性を増やすことが挙げられる。

    3.2 シミュレーション2(学習曲線)

    決定木に限らず、学習量によってどの程度正確な学習モデルが作成されるかが変わってくる。極端に学習データが少ないと分散が非常に大きく、一つのデータに対する依存度が高くなってしまうことが予想できる。ここでは学習量が各アルゴリズムにて推定精度にどのような影響を及ぼすか評価を行う。

    フェーズ1 データセットの整形

    前節と同様のため割愛

    フェーズ2 データの学習とテスト

    各アルゴリズムでの設定を以下の図のように行う。

    「split data」

    setting4.png

    ○ブースティング

    phase4-1.png

    ○ランダムフォレスト

    phase4-2.png

    フェーズ3 評価と結果の統合、csvファイルへの出力

    前節と同様のため割愛

    シミュレーション結果

    学習曲線.png

    シミュレーション結果は上記のようになった。ランダムフォレスト(森のサイズ100)が最も精度がよくなっていることがわかる。また、全体的に学習量が増えるほど推定精度がよくなっており、それぞれのアルゴリズムごとにある値で飽和している。また、森のサイズが小さいもしくは決定木1つのみの場合は分散が大きいため、推定精度の安定性が低い。前節でも説明したようにブースティングに関しては森のサイズが大きくなることによって推定精度の劣化が見受けられる。

    終わりに

    この記事では非線形分類や回帰を行うことができる決定木全般に関する理論とシミュレーションを行った。今は過ぎしマイニングブームでもC4.5やCARTなどは推定精度が高いことから頻繁に活用されていたアルゴリズムである。個人的にはNNやSVMよりも理解しやすいため、是非ロジスティック回帰と併せて学習することをおすすめしたい。

    その他、Microsoft Azure Machine Learningでやってみた記事も参考にしてください!

    ・ロジスティクス回帰も用いたIris Two Class Dateの分類

    ・分位点回帰を用いた飛行機遅延予測

    ・パラメーターチューニングを行う

    ・ランダムフォレスト回帰を用いた人気ブログタイトル予測

    参考文献

    ○決定木について

    [1]https://ja.wikipedia.org/wiki/%E6%B1%BA%E5%AE%9A%E6%9C%A8 

    [2]https://dev.classmethod.jp/machine-learning/2017ad_20171211_dt-2/ 

    [3]https://qiita.com/3000manJPY/items/ef7495960f472ec14377

    [4]https://www.researchgate.net/publication/265031802_Chapter_10_CART_Classification_and_Regression_Trees

    ○分類木について

    [5]https://www.solver.com/classification-tree 

    ○回帰木について

    [6]https://www.solver.com/regression-trees 

    ○不順度について

    [7]http://darden.hatenablog.com/entry/2016/12/09/221630 

    ○ランダムフォレストについて

    [8]https://link.springer.com/article/10.1023/A:1010933404324 

    ○ブースティングについて

    [9]https://www.frontiersin.org/articles/10.3389/fnbot.2013.00021/full 

    はじめに

     今回はロジスティック回帰についてやっていこうと思います。まずはロジスティック回帰の概要を説明して、最後には実際にAzureでiris(アヤメ)のデータでロジスティック回帰を使っていこうと思います。

    勾配降下法

     ロジスティック回帰でパラメータの値を決めるときに勾配降下法を用いるので、簡単に説明をしておきます。

     勾配降下法は、ある関数J(w)が最小となるwを求める際に、あるwでの傾き(勾配)を求めて、降下の方向(傾きが小さくなる方)にwを更新し、その更新をwが収束する(勾配≒0)まで繰り返して収束したところでのwでJ(w)が最小であると決めます。その更新の式は次のようになります。

    Microsoft Azure Machine Learningでロジスティクス回帰

    ここでのαは学習率といい、降下の方向にどのくらいwを移動させるかを表します。ここでαが大きすぎると最小となる点を更新の際に飛び越えて振動してしまいます。逆に小さすぎるといつまでも収束しないので、適当な値をαに決めなければいけません。またwがn次元ベクトルの場合は、そのn個について同時に更新するということにも注意が必要です(詳しくはロジスティック回帰の説明中)。

    Microsoft Azure Machine Learningでロジスティクス回帰

    Microsoft Azure Machine Learningでロジスティクス回帰

    ロジスティック回帰とは

     ロジスティック回帰とは、ある事象が発生するかどうかを、その確率を出すことにより判定することに使われる手法で、目的変数が2値のときに使われるアルゴリズムです。具体的に言うと、アヤメの花の種類A,B(目的変数)があったとき、その花の花弁の大きさなど(説明変数)から種類を判定したいときにロジスティック回帰を使うことで判定することができます。それではロジスティック回帰の流れを見ていきましょう。

     線形回帰では目的変数yを、パラメータwによって決められる説明変数xの関数h(x)で予測しました。

    Microsoft Azure Machine Learningでロジスティクス回帰

     ロジスティック回帰では、このh(x)を下図のシグモイド関数に入れた形にして、その値を0以上1以下にすることで2値(目的変数y=0,1)の分類を可能にします。

    Microsoft Azure Machine Learningでロジスティクス回帰

    Microsoft Azure Machine Learningでロジスティクス回帰

    このh(x)はy=1である確率として解釈できるので、

    Microsoft Azure Machine Learningでロジスティクス回帰

    のように分類する規則を決めて判定することができます。

     では、パラメータwを決め方について見ていきましょう。結論から言うと次のような目的関数J(w)を最小にするようなwを決めます。

    Microsoft Azure Machine Learningでロジスティクス回帰

    目的関数はy=0,1を正しく判定したときに最小(→0)、全然一致しないとき最大(→∞)になるように設定します。そこで、h(x)≧0.5(より1に近い)のときy=1と予測し、h(x)<0.5(より0に近い)のときにy=0と予測することから、logの性質を利用して目的関数を決めました。考え方は次のようになります。

    Microsoft Azure Machine Learningでロジスティクス回帰

    Microsoft Azure Machine Learningでロジスティクス回帰

    これで目的関数の設定はできたので、これが最小となるパラメータwを決めていきましょう。ここで使われるのは勾配降下法です。

    Microsoft Azure Machine Learningでロジスティクス回帰

    ここでの勾配降下法は上の式において、j=0,1,...,nそれぞれについて同時に更新して、wの値が収束するまで更新を続けてwを決定します。

    目的関数を最小とするパラメータwを決めることができたので、ロジスティック回帰による予測モデルが完成しました。これで未知のデータに対して予測することができます。

    これで流れは掴めたと思いまので、実際にAzureを使ってロジスティック回帰を実行してみましょう。

    Azureでロジスティック回帰

     今回はAzureのサンプルデータのIris Two Class Dataを使います。はじめにデータを見てみると(画像はデータの一部)、目的変数に2種類のiris(アヤメ)のクラスを0,1で与え、説明変数にsepal-length(がく片の縦幅)、sepal-width( がく片の横幅)、petal-length(花びらの縦幅)、petal-width(花びらの横幅)の4つを与えています。

    Microsoft Azure Machine Learningでロジスティクス回帰

    このデータに対してロジスティック回帰を行います。

    Microsoft Azure Machine Learningでロジスティクス回帰

    Azureでは上のようにするとロジスティック回帰ができますが、流れを整理すると次のようになります。

    Microsoft Azure Machine Learningでロジスティクス回帰

    Alt text

    結果を見ると、一番右の列のScored Probabilitiesはクラス1である確率(h(x))を表していて、0.5以上でクラス1とScored Labelsで判定しています。ROC曲線で評価してみると、

    Alt text

    完全に予測することができています。今回はサンプルデータなのでこんなにうまく予測できていますが本来はこんなにうまくいきません。

    次に縦軸にそれぞれの説明変数ごとにとり、横軸にScored Probabilitiesを取った散布図を見て、どの説明変数が判定に影響を与えているかを視覚的に考えてみます。

    Microsoft Azure Machine Learningでロジスティクス回帰

    Microsoft Azure Machine Learningでロジスティクス回帰

    Microsoft Azure Machine Learningでロジスティクス回帰

    Microsoft Azure Machine Learningでロジスティクス回帰

    これを見ると、petal-lengthとpetal-widthは明確にその値が大きければクラス1に属する確率が高く、小さければクラス1に属する確率が低いことがわかります。sepal-lengthもpetalよりは弱くなりますが同様の傾向があることがわかります。それに対してsepal-widthは同じくらいの値を取っていても、クラス1である確率が大きかったり小さかったりと明確には言えません。更にどちらかと言うと、値が小さい方がクラス1の確率が高くなっています。その関係がパラメータに現れていることを確認すると、

    Microsoft Azure Machine Learningでロジスティクス回帰

    petal-length、petal-widthのweight(係数、重み)が大きくなっていて、sepal-lengthのweightがそれに比べ小さく、sepal-widthのweightは負でかつその絶対値は小さくなっていますので、散布図の傾向はしっかりとあたっています。今回はサンプルデータでやったので、かなりうまくいってわかりやすかったですが、本来はここまできれいにはならないでしょう。

    まとめ

     今回はロジスティック回帰についてやりました。非常に有名で基本的な手法ですのでしっかりと理解しておくと良いでしょう。


    その他のMicrosoft Azure Machine Learning Studioでやってみた記事も参考にしてください!
    決定木アルゴリズムCARTを用いた性能評価
    分位点回帰を用いた飛行機遅延予測
    パラメーターチューニングを行う
    ランダムフォレスト回帰を用いた人気ブログタイトル予測

    参考文献

    Coursera 機械学習 Andrew Ng

    はじめに

     今回は2分類SVMについて見ていきますが、数学や機械学習の知識があまりない方も全体のイメージを掴めるよう数式を使うことを極力避けました。ですので厳密には間違っている表記もイメージしやすいよう、わざと入れていることを始めに断っておきます。

    SVMを数式を追ってしっかりと理解したいという方には物足りない内容になっていると思いますがご了承ください。

    SVMとは

     SVMとは、教師あり学習を用いるパターン認識モデルの一つで、回帰、分類両方につかうことができます。ここでは2分類SVMを考えていきます。

    SVMは、「マージン最大化」という考え方を用いて分類する境界(決定境界)を決めます。この考え方によって他の分類モデルよりも高い識別性能を実現していますが、その理由とともにマージン最大化を用いて、次の赤と青のクラスの分類について見ていきます。

    Alt text

    ここでは簡単のために二次元で直線で分類することを考えますが、三次元以上になったときは下のように平面で切っていると考えてください。なので直線と出できたら基本的には平面に言い換えられると思ってください。

    Alt text

    ・マージン最大化

     マージンとは、分類する境界とデータとの距離のことで、いくつも考えられる境界の中から、サポートベクトルという「分類する境界に一番近いデータ点(境界を決めるのに使うデータ)」との距離が最大となるような境界を見つけようというのがマージン最大化という考え方です。このとき、それぞれのクラスのサポートベクトルに対するマージンは同じであるとします。ただし、2クラスそれぞれのサポートベクトル間の距離をマージンということもありますが、結局その距離のちょうど半分にしたところに境界を設定しているということです。つまり、どちらでマージンを設定するにしろ、2つのクラスからなるべく離れたところに境界を引きたいということです。

    マージン最大化の考え方を用いて赤と青の2つのクラスを分類してみると次のようになります。

    Alt text

    では、なぜマージン最大化を用いて分類することで高い識別性能が得られるのでしょうか。

     上の図のような分類を考えると、その分類する境界というのは無数に考えることができます。まず考えてほしいのは分類する目的の大前提として、今ある値を分類することにより、まだどちらのクラスの属するか分からない未知の値に対してどちらのクラスに属するかを正しく予測することがあります。つまり、分かっているデータに対して正しく分類できたところで、未知のデータに対しての正しく予測できている割合が極端に低くなるような境界では全くの無意味だということです。

    Alt text

    Alt text

    例えば、図のように片方もしくは両方のクラスの値ギリギリにあるような境界を設定してしまうと、そこからほんの少しだけずれたようなデータに対して誤分類を起こしてしまう可能性が高くなります。そこで、マージン最大化を考えることにより、データが少しずれただけでは誤分類を起こさなくなります。これによりマージンを考えて決めた境界で分類することにより、それを考えずに境界を決めたモデルより「汎化能力(新しいデータに対して正しく予測する能力)」が高くなっています。このことから、SVMはマージン最大化を考えることにより、汎化性能が最も高い境界により分類を行うことを可能にしています。

    ・ソフトマージン

     ここまでは、2クラスに対して直線で分類可能(線形分離可能)なデータに対して考えてきましたが、データが次のようになっていたらどうでしょう。

    Alt text

     データがこの様になっていた場合、直線で2クラスを完全に分類するのは不可能です。このようなデータに対して完全に分類しようとすると、もし誤分類をしてしまったデータに分類に大きく影響するような情報が含まれていた場合、汎化能力が下がってしまいます。ここで出てくるのがソフトマージンです。

    実は先程までの、線形分離可能なデータに対して考えたマージンをハードマージンといい、これは完全に2つのクラスを分類できることを前提にしたマージンです。それに対してソフトマージンは、あらかじめ誤分類を許すことで汎化性能を高めることを考えたマージンです。もちろん、誤分類が多すぎては汎化性能を高めるどころか低くしてしまう一方なので、「境界線とデータがなるべく離れていること」・「誤分類数をなるべく少なくすること」の2つを達成するようにします。

    そこで次のような値を最小にすることを考えて、境界を決めます。

    Alt text

    ここでCは、「どの程度まで誤分類を許すか」を表すパラメータです。Cが小さい場合、多少誤分類数が多くても値は大きくならないので、ある程度誤分類を許すことになります。それに対して、Cが大きい場合、誤分類数がより0に近くなければ値が大きくなってしまうので、あまり誤分類を許さないことになります。Cが無限に大きければ誤分類を許さなくなるので、上でのハードマージンと一致します。つまりCの大きさを調整すればハードマージン・ソフトマージンの両方を実現することができるので、C-SVMで両方の問題に対応できます。

     C-SVMで分類した様子は次のようになります。

    Alt text

    ここで、なんでマージン境界内に点が入ってくるのか、なんでサポートベクトルが色々増えているのかと思ったと思います。実は上で書いた式に少しだけ嘘が含まれていて、そこは誤分類数のところです。ここの値はダイレクトに誤分類数を表しているのではなく、誤分類したデータやマージン境界内にあるデータによって決まる値なんです。詳しく言うと、マージン境界より外で正しく分類できている点に対しては0、マージン境界内で正しく分類できるデータに対しては0から1の間の値、誤分類している値に対しては1より大きな値を与えます。なので、境界を決める際に誤分類のデータとマージン境界内のデータにより決めていることになります。そこでサポートベクトルの定義に戻ると、境界を決めるのに使う(影響のある)データなので、今までは境界から一番近いデータ(紫)がそれになっていましたが、ここではそれ以外にもマージン境界内のデータ(緑)と誤分類をしたデータ(黄色)が使われるのでそのデータもサポートベクトルになっているのです。そのそれぞれにも名前がついていて、マージン境界上のデータ(紫)が自由サポートベクトル、それ以外のサポートベクトル(黄・緑)を上限サポートベクトルといいます。実際にはこんな値が入りますが、結局一番影響を与える誤分類数をCでどの程度にするのかが一番重要ですので、そこをまずは抑えて、境界を決める要素が増えたんだなーと思っていいただければいいと思います。

    Alt text

     ソフトマージンにより非線形分離不可能なデータに対してSVMを適用できましたが、ここでのCは自分で決めなければならず、まず最適なパラメータを見つける必要があります(これがSVMの欠点につながる)。ここでは詳しいことは述べませんが、その方法としてグリッドリサーチ(色々なパラメータを試して精度の良いものを採用する)などがあります。

    ・カーネルトリック

     ソフトマージンにより、直線で分離が不可能な場合でも誤分類により境界を決定することができましたが、直線で分離をしているので、ある程度の性能しか望むことができません。そこで登場するのがカーネルトリックです。この手法によりSVMは強力な威力を発揮します。

     この手法を考えるときに次のような2クラスを分類することを考えます。

    Alt text

     これを分類しようとしたときに、今まで出てきたSVMを使ってやろうとしてもうまくいかないだろうと思うはずです。そこで、直線だけでなく曲線を使えるとしたら、下のような境界を使って分類することができれば良いですよね。

    Alt text

     この境界を引くことをできるようにしたのがカーネルトリックです。

     では、どのようにこれを可能にしているのかを数式は使わず考え方を中心に説明します。参考書なんかを見ると特徴空間に変換して分類するみたいなことが書いてあると思います。これは、今ある特徴量(上の赤と青の位置を決めているもの)では分類できないものを、新しい特徴量を作って分類できるようにしようということです。

    ※特徴量のイメージをしやすいように、予測の流れを出しときます。

    Alt text

    ここでのカーネルのイメージとしては、直線で分類できないものを、マージン最大化の最初で出てきたようなデータがある程度分かれた状態にして、直線で分類できるようにするというものです。これを簡単な例で見ていきましょう。

     次のようなデータが数直線上にあったらどう頑張っても直線では赤と青のクラスに分けるごとができません。

    Alt text

    そこで二乗した値を作るとどうでしょう。

    Alt text

    すると、このように直線で分類することができるようになります。厳密に言うと違うのですが、イメージ的にはこのような変換をカーネルで行います。実はカーネルにも種類があって代表的なのはガウスカーネルと多項式カーネルですが、ここでは主にガウスカーネルについて考えていこうと思います。

     ガウスカーネルは簡単に言うと値と値の近さを表しているものです。例を見るとイメージが掴めると思うので、円の境界を引きたいと思った例で考えてみましょう。

     この例では感覚として、真ん中らへんとその周りに分けることを考えたと思います。その感覚で真ん中らへんとそれ以外をはっきり分けられるような特徴量を今あるデータ(特徴量)から作れないかなーと考えるわけです。そこでガウスカーネルによって特徴量を考えていきますが、近くにあるデータは似た特徴量を持っていてほしいじゃないですか。例えば真ん中らへんにあるデータに対しては小さいけど、周りにあるデータに対しては大きい特徴量があれば、下のようになって分類しやすくなります。

    Alt text

    ガウスカーネルはデータとデータの近さを基準としてこの変換を行います。まずある一点を基準として、他のすべてのデータとの近さに関する値を出します。これを、基準を変えてすべてのデータ間の近さを調べて、それを使った値を特徴量として変換を行います。ここでどのくらいの近さまでを同じクラス、似た特徴量を持ったとするのかという問題が起きます。これを決めるのにはカーネルの中にあるパラメータを決めて調整しなければいけません。ただ、基本的には近さでデータの特徴を決めたいんだということだけまずは理解してほしいです。

     分かりやすいように、3つのデータだけで考えてみましょう。それぞれの点からの距離を取って、ある点からAまでの距離を特徴量a、Bまでの特徴量をb、Cまでの特徴量をcとします。実際は今あるデータの特徴量を使ってガウスカーネルで変換しますが、ここでは簡単のため距離をそれぞれ設定しました。

    Alt text

    ここで、特徴量a、b、cをそれぞれの点でみると、CだけA、Bとは逆(A,Bからの距離が近いときはCは遠い)になっていることが分かると思います。つまり、クラスの違うCだけが仲間はずれとなっています。こういったことを、もっとデータ数が多くて、直線で分類できない問題に対してカーネルを使って変換することでやっているのがカーネルトリックです。多項式カーネルは、意味としては最初に二乗した例に近いことがあるかもしれませんが、やりたいことは同じです。

     では、元の例に戻ってカーネルで変換する様子の一部分見ると次のようになります。

    Alt text

    このように特徴量を変換するとイメージとしては次のようになり、分類が明らかにしやすい配置になっているのが分かると思います。

    Alt text

     まとめると、直線で分類できないものをカーネルを使ってデータの特徴量を、クラスの違う特徴量に変えて直線で分類しているということです。特徴量を変換したあとは、マージン最大化で分類をするので、上のカーネルを使わなかった分類と同じです。では、どのようにしてカーネルのある無しを使い分けたらいいのかを見ていきましょう。

    ・カーネルのある無しの使い分けとSVMの欠点

     上のカーネルを使わないSVMと使うSVMを比べたとき、一見カーネルを使ったほうがそのままだと直線で分類できてものも分類できるからそっちを使えばいいと思うかもしれません。しかし、カーネルを使うのにも欠点があります。カーネルはより良い特徴量を取るために変換を行いましたが、もうすでに十分多くの特徴量が得ることができていたらどうでしょう。色んな特徴量があればそれだけ問題は複雑になるので、更にそこから変換を行うと今あるデータに厳密に従いすぎてしまいます(過学習という)。つまり新たなデータに対して無意味な境界になってしまうので、この場合はカーネルを用いないSVMを使ったほうがいいです。

     逆に、特徴量が少ない場合、つまり十分な特徴量は得られない場合はどうでしょう。この場合はデータが非常に単純な場合を除いて、上で見てきたようなような直線で分類できないような問題になっている可能性が高いので、カーネルを用いたSVMを使うといいです。

     ただ、データがかなり多い場合はカーネルを使うと、変換をするときに計算量が多くなってしまうので、この場合は変換をするのではなく特徴量を自分で増やして、十分にとってからカーネルを用いないSVMを使うといいです。

     また、SVMの欠点としてはパラメータを設定しなければならなかったり、カーネルを選ばなければならないことや。データが多いときはあまり効率的ではありません。この問題をクリアしている手法として「ランダムフォレスト」があります。これを使えばSVMより効率よく良い結果が得られるかもしれませんが、これは実際に使ってみないとどちらの手法が良いのかは判断できませんし(どちらにも長所・短所がある)、それぞれの特徴をしっかり理解することが重要です。

    まとめ

     今回は2分類SVMについてやりました。数式をほとんど使わなかったので、逆に分かりづらいところもあったかもしれませんが、SVM全体のイメージは掴めたでしょうか。SVMは他にも1クラスに対して外れ値を検出するものや、回帰にも使えますし、ロジスティック回帰との関係を見ても面白いと思います。また、最後に出てきたランダムフォレストについては、他の記事を見てもらうと良いと思います。

    参考文献

    Logics of Blue サポートベクトルマシンの考え方

    はじめてのパターン認識 平井有三(著) 森北出版

    分位点回帰は、普通の直線回帰とは少し変わった、特殊な回帰ですが、正規分布に従わないデータを処理する際、柔軟な予測をすることができる便利なモデルです。今回は、理論編・実践編に分けて、分位点回帰を解説していきたいと思います。

    理論編

    1.回帰

    回帰とはデータ処理の方法の一つで、簡単に言うとデータを予測するモデルを作る際に、「モデル化=簡略化」に伴う損失を最小限にすることです。そしてこの「損失」を定量化するためにモデルごとに様々な「損失関数」を定義します。「損失関数」の値を最小化するようなパラメーターを探すことが、いわゆる「学習」と呼ばれる作業になります。数多くある回帰ですが、その一つが今回紹介する「分位点回帰」です。

    2.分位点

    分位点回帰はその名の通り、「分位点」に注目した回帰です。「分位」とはデータを順番に並べた時に、上位何%に入るかを表現するときに使います。例えばquartileとは四分位のことで、データを四等分にできます。

    0th quartile = 上位0%

    1st quartile = 上位25%

    2nd quartile = 上位50%

    3rd quartile = 上位75%

    4th quartile = 上位100%

    他にもquintile=五分位など、何等分にデータを切るかは自由に設定することができます。

    こういうふうにデータを区切ると、例えば身長が上位25%の人と身長が上位75%の人で変数の影響が違う場合、それらを具体的に見ることができます。これは分位点回帰が一般的な直線回帰や重回帰とは違う点です。

    3.損失関数

    分位点回帰の損失関数と、一般的な最小二乗法の損失関数とでは決定的な違いがあります。最小二乗法では全てのデータポイントにおける損失が均等に評価されるため、平均に対して回帰していくことになります。しかし、事故率や年収など、偏りがあるデータでは、平均における情報よりも中央値における情報の方が重要だったりします。そのため、分位点回帰などは「上位何%における変数の影響」という平均とは全く違う観点でデータを見ることができます。

    「上位何%における変数の影響」を見るからといって、その上位何%のデータのみを使うわけではありません。データは常に全て使うのですが、データによって損失関数に対する影響が違う、というふうに捉えるとわかりやすいでしょうか。この損失関数を使うと、損失関数の微分が0<=損失関数が最小の時、上位τ%の値について予測できるような変数の係数が計算されているのです。

    (もっと知りたい人向け)

    具体的には損失関数は

    Alt text

    で定義されます。 ここで

    Alt text

    がquantileにあたる数字になります。

    Alt text

    は累積分布です。

    この損失関数が何故うまくいくかというと、左辺を微分したものの値が0となるような u = q_τに対して、

    Alt text

    となり、整理すると

    Alt text

    なので、確かにq_τが上位t%の値だとわかります。

    4.長所と短所

    上でも説明したように、分位点回帰は偏りのあるデータを処理したり、特定の分位における変数の影響を予測するのに適しています。逆に、分布が正規分布に近い場合は、平均で回帰した方が正確な結果が出ることになります。

    実践編

    では実際のデータを使ってQuantile Regressionを試してみましょう。今回はMicrosoft Azure MLに実装されているものを使って、飛行機の遅延について予測するモデルを訓練していきましょう。

    0.データ

    今回のデータは飛行機の離着陸の遅延時間、空港、日時などをまとめたデータセットです。

    Alt text

    DerDelay, ArrDelayを見てみると、かなり左側に偏っていることがわかります。またCarrier(飛行機会社)も正規分布よりかなり偏っているので、Quantile Regressionを活かせそうだ、ということがわかります。通常は空白のセルの処理やデータの取捨選択が必要になりますが、今回はMicrosoft Azureに内装されたデータセットを使うので、その必要はなさそうです。

    1.データの分割

    学習をするにあたって、機械を学習させるための学習データ(training data)と、その学習を評価するデータ(evaluation data)の2種類が必要になってきます。そこで、元のデータをランダムに分割する"Split Data"を使います。今回は元データの60%を学習データに使用することにしました。もちろん、この値は調節可能です。

    Alt text

    Alt text

    2 モデルの選択

    今回はQuantile Modelを使ってみたいので、その一つであるFast Forest Quantile Regressionを使います。

    Alt text

    Fast Forest Quantile Regressionのパラメータは初期設定のままにしました。一部TreeやLeavesのような見慣れない単語が出てきますが、興味のある方はRandom Forest Regressionについての記事をご覧ください。

    理論編で紹介した部分に当たるのは、下から2番目の"Quantiles to be estimated"になります。入力されている値を見ると、四分位なことがわかります。

    Alt text

    3.学習

    実際の学習モジュールを追加していきます。ここでは、"Train Model"モジュールに対して、どの変数を予測したいか、を指定しなければなりません。今回は出発の遅延を調べたいので、DepDelayを選びます。

    また、分割したデータのうち、学習用のデータ(左側)を入力として指定します。

    Alt text

    Alt text

    4.評価と結果

    学習が終わったら、モデルの精度を「見たこともないデータをどれだけ正確に予測できたか」という基準で測ります。ここで最初に分割しておいた評価データを使うことになります。

    Alt text

    学習結果を見てみましょう。

    Alt text

    一番左端が今回予測したDepDelayで、右側3列がQuantile Regressionで予測した結果になります。

    例えば一番上のDepDelay=-4のデータでは、全体の中で第1四分位に属しているため、"Score for quantile 0.250"の値が一番正確です。

    逆に、中ほどにあるDepdelay=65のデータは、全体の中で第4四分位に属しているため、"Score for quantile 0.750"の値が一番正確です。

    この結果からわかることの一つは、全体の中でどの四分位に属しているかによって、変数の影響が違う、ということです。でなければ、どの予想も同じような数字を出力するはずです。このような柔軟性のある分析ができるところが、分位点回帰の利点になります。

    以上、分位点回帰の理論と実践でした。
    その他のMicrosoft Azure Machine Learning Studioでやってみた記事も参考にしてください!
    決定木アルゴリズムCARTを用いた性能評価
    ロジスティクス回帰を用いた Iris Two Class Dataの分類
    パラメーターチューニングを行う
    ランダムフォレスト回帰を用いた人気ブログタイトル予測

    参考文献: 分位点回帰を使って、「その回帰予測どれくらい外れるの?」を説明する

    様々な場面で使われるランダムフォレストですが、大きく分けると「ランダム」の部分と「フォレスト=森」の部分の2つに分けることができます。そこで今回は理論編でそれぞれの部分がどういう仕組みになっているのか、解説していきたいと思います。後半では、実践編と題して、実際のデータセットとMicrosoft Azureを用いてRandom Forest Regressionを一般的なLinear Regression (直線回帰) と比べてみたいと思います。

    理論編

    0.前提知識

    ここではRandom Forest Regressionの中身を主に説明していくので、一部省略している部分があります。具体的には、

    「回帰」って何?

    「学習」って何?

    のような問いには答えていないので、その場合は他の記事をご参考ください。ここでは、Random Forestの仕組みについて説明していきます。

    1.「フォレスト=森」

    フォレストモデルはその名の通りで、複数の「木」から成り立つ「森」のような学習モデルです。下の図のように、一つ一つの木は「decision tree(決定木)」のような条件分岐でデータを分類しています。それぞれの分岐において使われる変数を説明変数と言い、最適な説明変数を学習していくのが決定木における学習です。

    例えば、下の図の場合、まずは「男性かどうか」、次に男性のうち、「10歳位以上かどうか」、最後に、10歳未満の男性のうち、「兄弟が3人以上いるか」、このような分岐条件でデータを4つに分類しています。

    実際には、この3つの説明変数以外に、「身長が170cm以上か」「海外旅行に行ったことがあるか」など、様々な説明変数があり、どの変数を使うとデータを一番適切に分類できるか、決定木が学習していきます。

    Alt text

    木が深いほど細かく分類ができますが、計算負荷が増えるので、回帰に使用する場合は深さをn=5にするのが良いとされています。

    このような木を複数集めて、結果を平均したものを最終結果として決定するのが、フォレストモデルです。計算負荷の少ない小さな木を複数使って最終的な判断を総合的に行う、このような学習モデルをアンサンブル学習と言います。

    Alt text

    (もっと知りたい人向け)

    各ツリーにおける分岐の分割条件の計算方法も様々あり、回帰モデルか分類モデルかによって変わります。

    ここで扱う回帰モデルの場合、最小二乗法が使われますが、分類モデルの場合、

    • エントロピー
    • ジニ不純度
    • 分類誤差

    の3つがよく使用されます。詳しい内容は次の記事をご参照ください。

    決定木の2つの種類とランダムフォレストによる機械学習アルゴリズム入門

    2.二つのランダム

    計算処理が早いツリーを組み合わせるフォレストモデルですが、一つ大きな問題があります。もし個々の木が全く同じようにデータを処理するのであれば、データ全体の特徴を反映することができません。一つの小さな木を使ってるのと同じになってしまいます。つまり、木によって分岐条件が違わなければ分類制度が低くなってしまいます。そこで、

    • 学習データ
    • 初期説明変数

    をランダムで設定することで学習制度を向上させています。学習データの選定はブートストラップ法と呼ばれ、それぞれの決定木に関して毎回母体データからランダムに一部を選び取ります。初期説明変数も同様に、全体の説明変数から毎回ランダムにいくつか選び、決定木の説明変数として使用します。

    3.長所と短所

    最後に、ランダムフォレストはどのような利点・欠点があるのでしょうか。

    長所としては、

    • 説明変数が多数であってもうまく働く
    • 学習・評価が高速
    • 決定木の学習は完全に独立しており、並列に処理可能
    • 説明変数の重要度(寄与度)を算出可能

    などがあります。

    短所は、

    • 説明変数のうち意味のある変数がノイズ変数よりも極端に少ない場合にはうまく働かない

    というものです。つまりデータの分類・予測に有用な変数が少なければ、学習がうまくいかないことになります。

    実践編

    では、実際Random Forest Regressionを使って学習をしていきましょう。今回はMicrosoft Azure MLを使って説明します。

    今回使うデータセットはブログに関するデータで、タイトル、お気に入り登録者数などの情報が入っています。今回はこのデータセットから、

    「どのような名前が人気のブログになりやすいのか」

    を回帰してみたいと思います。

    0.データ処理

    まず初めに、使うデータを綺麗にします。通常、空白になっている部分があったりして、処理がすぐにはできないようになっています。

    そこで、データを前処理する必要があります。今回は、

    • 必要な列を選ぶ
    • 空白の値があるデータを取り除く

    の二つの処理を行いました。

    Alt text

    今回の目的はどういう名前が読者を集めやすいのか、というのを知りたいので、

    メインの変数:BLOG_COUNT (読者数)

    説明変数:

    • DAYSSINCELAST_POST (最後に更新されてから何日経っているか)
    • VOWELS (アルファベットの母音がいくつあるか)
    • NON_ALPHABET (日本語の文字がいくつあるか)
    • LENGTH (タイトルが何文字か)

    を選びたいと思います。

    Alt text

    1.データの分割

    学習をするにあたって、機械を学習させるための学習データ(training data)と、その学習を評価するデータ(evaluation data)の2種類が必要になってきます。そこで、元のデータをランダムに分割する"Split Data"を使います。今回は元データの60%を学習データに使用することにしました。もちろん、この値は調節可能です。

    Alt text Alt text

    2.モデルの選択

    今回はRandom First Modelを使ってみたいので、標準的なLinear Regressionと比べてみることにします。

    Alt text

    モデルのパラメーターは初期設定のままにしました。下の画像からもわかるように、決定木が8本あり、最高でn=32の深さまで木を作ることができます。

    Alt text

    3.学習

    実際の学習モジュールを追加していきます。ここでは、それぞれの"Train Model"モジュールに対して、どの変数を予測したいか、を指定しなければなりません。人気のブログを予測したいので、BLOG_COUNTを選びます。

    また、分割したデータのうち、学習用のデータ(左側)を入力として指定します。

    Alt text

    4.評価と比較

    今回はRandom Forest ModelとLinear Regressionの精度を比べますが、2種類の比べ方をしたいと思います。

    一つ目は、「与えられた学習データをどれだけ正確に学習できたか」という基準です。理想的には、入力に使ったデータなので100%予測してほしいものなのですが、現実的にはそうもいきません。そこで、2種類のモデルがどの程度精度をあげられたのかをまず比較します。

    Alt text

    二つ目は、「見たこともないデータをどれだけ正確に予測できたか」という基準です。ここで最初に分割しておいた評価データを使うことになります。

    Alt text

    5.結果

    以上を全て組み合わせると、以下のような図になります。

    Alt text

    そして学習データの結果を比べると、下の図のように、

    Alt text

    誤差がRandom Forest Regression (2列目)の方が小さいことがわかります。 同様に評価データについても、Random Forest Regressionの方が精度が良いことがわかります。

    Alt text

    今回は説明変数も少なかったのですが、説明変数が非常に多い場合、比較的速く学習できるモデルとしてRandom Forest Regressionは有用です。

    以上、Random First Regressionの理論と実践でした。


    その他のMicrosoft Azure Machine Learning Studioでやってみた記事も参考にしてください!
    決定木アルゴリズムCARTを用いた性能評価
    ロジスティクス回帰を用いた Iris Two Class Dataの分類
    分位点回帰を用いた飛行機遅延予測
    パラメーターチューニングを行う

    参考文献:

    決定木の2つの種類とランダムフォレストによる機械学習アルゴリズム入門

    だれでも分かる機械学習(入門)第3回 Azure Machine Learning 回帰分析

    パッケージユーザーのための機械学習(5):ランダムフォレスト

    1,ベイズ統計学とは

    ベイズ統計学とは、ベイズの定理を基礎とした統計学の体系である。

    2,他の統計学との相違

    1. ベイズ統計学は標本を必ずしも必要とせず、母数が確率的に動くとみなす学問
    2. 記述統計学はデータを集計する手法を学ぶ学問
    3. 推計統計学は限られた標本のうち全体となる母集団の性質を推測する学問

    3,ベイズ統計学の歴史

    1700年頃、トーマス・ベイズによりベイズの定理が発表された。 後に、1800年代後半にベイズ統計の基礎ができた。 しかし、推計統計学論者のフィッシャーらによって主観確率を 取り扱う統計は科学的ではないとしてベイズ統計は闇に葬りさられた。 1950年代に入り、ベイズ統計の利便性の高さから注目されて、 近年は機械学習やビッグデータの分野で利用されることから多用されるようになった。

    4,ベイズ統計の特徴

    ベイズ統計では、主観確率を取り扱う。主観確率とは、 人により対象の確率が変動する主観に基づく確率の事である。 この確率を使用して事前確率と事後確率を用いて数式化する。

    5,事前確率と事後確率

    事前確率とは、データを手に入れる前に想定していた確率のことである。 事後確率とは、データを用いて事前確率を修正した結果の確率のことである。

    6,ベイズ変更

    事前確率を変更してより正確と考えられる事前確率に変更することをベイズ変更という。 ベイズ変更により事前確率が変更するため、その結果事後確率が変わる。

    7,ベイズ統計の公式

    ベイズの定理 P(A|X)=P(X)分のP(X|A)P(A)=P(A)✕P(X)分のP(X|A)

    • P(A|X):事象Xが起こった状況下で事象Aが起こる確率(事後確率)
    • P(A):事象Aが起こる確率(事前確率)
    • P(X):事象Xが起こる確率
    • P(X|A):事象Aが起こった状況下で事象Xが起こる確率

    ベイズの定理を文字として表現すると、 事後確率=事前確率✕修正項 になる。 この数式に数を代入すれば事後確率が求まる。

    8,ベイズ統計の使用例

    1.迷惑メール判別

    ユーザーがスパムとしたメールとスパムではないとしたメールから、タイトル、 本文に含まれる語句ごとの出現確率を抽出して点数をつける。 スパムと正常なメールを判別するための閾値を導き出す。 新規メールを受信したら、そのタイトルや本文を自然言語処理し、閾値と照らし合わせてスパムメールである 確率が高ければスパムメールとして振り分ける。

    2.検索エンジン

    Googleやマイクロソフトの検索エンジンはベイジアンフィルタを採用している。 1990年頃まで一般的だったif,and,or, butを使い判別する検索エンジンの検索精度や速度を凌駕した。

    3.アプリケーション開発

    インテル、マイクロソフトなどで活用されている他、LINEスタンプのレコメンドエンジンにも応用されている。

    1.判別分析の定義

    判別分析とは、統計学上のデータ解析手法の一つである。
    特定のグループに分かれているデータを元にどのような基準で判別されているか解析する。
    そして、どちらのグループがA群に属され、B群に属されるかを予測する分析のことである。

    2.判別分析の成り立ち

    1936年にロナルドフィシャーによって線形判別分析が発表され、これを元に分析手法が発達した。

    3.判別分析の例

    1.医療診断 
    ・喫煙の有無により癌の発病を予測
    ・検査結果から病気の有無の判別
    2.選挙予測
    ・世論調査による法案の通過の有無予測
    ・立候補政党から立候補者の当落の判別
    3.受験合格の予想
    ・模擬試験の採点から志望校の合格を予測
    ・勉強時間等から合否の判別
    4.マーケティングの予測
    ・企業の倒産の判別
    ・画像の色や形から異常の判別
    ・顧客の発注の有無判別

    4.判別分析の種類

    A 群とB群を線で仕切りA群に属するかBに属するかを分ける方法には、以下の2種類がある。
    1.線形判別関数で仕切る
    線形判別関数とは、2つのクラスを最もよく判別できる直線を求める手法の事である。

    image

    2.マハラノビス距離で仕切る
    マハラノビス距離とは、データの分布の広がりを加味した距離のことで2点間の直線距離を 標準偏差で割った値を2乗して求められる距離のことである。

    image

    5.判別分析の手順

    1.事例
    例)A塾では、生徒をなるべくいい学校に合格させたい。
    そこで生徒の能力で一番上の志望校をお勧めするために模試を作った。
    2.分析の目的
    模試によって生徒の志望校の合否判定を行うこと。
    3.データ準備
    今回の目的のために、様々なデータを集めた。
    例)合格点数、志望者数、偏差値等のデータ
    採用するデータを集める際には、人間が集めるためアナログな部分がある。
    4.判別分析ツール
    統計ソフトを使いそれらのデータを入れて計算する。
    データは相関性の強いもののみを使用して、線形判別係数により判別式を作る。
    5.分析結果の活用
    判別式で出た数値を元に合否を判断する。
    今回の場合、判別式でyが1以上であれば、合格になる可能性が高いと判断できる。 そして、A塾はこの模試の結果に基づいて生徒にもっとも良いと思われる学校をお勧めする。

    6.まとめ

    判別分析は、様々な場面で利用することができる。
    しかし、データの選択をする際には、人間が選ぶため相関性が高いのか判別して式に落とし込む必要がある。

    1.クラスタリングの定義

    クラスタリングとは、機械学習の目的物を分類する一つである。
    与えられたデータを外的基準なしに自動的に分類する手法の事である。
    簡単に言えば、データの集合体をカテゴリに分けることである。

    2.クラスタリングの特徴

    機械学習には教師あり学習と教師なし学習に大別される。
    1.教師あり学習
    人が正解を提示してそれを元に観測したデータから予測する事である。
    2.教師なし学習
    観測データのみを分析する。
    クラスタリングは教師なし学習に分類される。
    そのため、分類の基準が明確ではない。
    分類の外的な基準が与えられていない場合にはどうしてそのように機械が分類したか分析する必要がある。

    3.クラスタリングの目的

    クラスタリングの目的は、まとまりのないデータを分類してマーケティング等で応用することである。

    4.クラスタリングのアルゴリズム

    クラスタリングを行うためには以下の2つのアルゴリズムを利用する。
    1.断層クラスター分析
    グラフ(例)

    image 2.非断層クラスター分析
    グラフ(例)

    image

    5.断層クラスター分析

    断層クラスターとは、集合体のデータのうち最も類似している組み合わせにまとめて分類する手法である。
    この手法は、結果を出すのに繰り返しデータを計算して断層的に併合するので樹形図のような形に見える。

    6.断層クラスターのメリット・デメリット

    断層クラスターは予めクラスターの数を決める必要がないので便利である。
    しかし、断層が増えるたびに計算量が増加していき実行に時間がかかるので、膨大なデータを扱うのには向いていない。

    7.非断層クラスター分析

    非断層クラスターとは、異なるデータの集合体の中から対象のものを集めて分類する手法である。
    ビッグデータを解析して大量のデータを分類する際に行う。

    8.非断層クラスター分析のメリット・デメリット

    非断層クラスターはデータの数が多いものでも取り扱う事ができる。
    しかし、予めクラスターの数を決めておかなければならない。

    9.クラスタリングの注意点

    クラスタリングを行う際には、何らかの主観的視点に基づいているため客観的な証拠とする事ができない。
    そのため、クラスタリングの結果を使う際は、その結果が妥当なのか検証しなければならない。

    10.まとめ

    クラスタリングは教師なし学習であり、似ているデータを分類する手法である。
    クラスタリングは、断層クラスター分析と非断層クラスター分析のアルゴリズムを使用して分類を行う。

    1.単回帰分析とは

    回帰とは、統計学においてYが連続値の時にY=f(x)というモデルをあてはめる事である。
    これにより二つの事項に関する相関関係などをを分析することができる。


    2.単回帰分析の成り立ち

    19世紀にフランシス・ゴルトンによって「回帰」という言葉が誕生した。
    ゴルトンは、遺伝子学の研究において分析を行い、その際に身長と遺伝子の関係を回帰モデルを用いた事で後の統計学で使われる回帰モデルが発展した。


    3.単回帰分析の例

    例えば、都道府県の人口密度と人口100万人あたりのコンビニの数を示したグラフがあるとする。
    薬局の数yを目的変数、人口密度xを説明変数とするとき、y=ax+bのa,bは回帰係数である。またy=ax+bのような式は単回帰式と呼ばれる。


    4.単回帰分析の特徴

    単回帰式は説明変数xが一つのみの状態の式である。
    例えば、アパートの賃料を予想する際には、 単回帰分析の場合は、目的変数を賃料とおき, 説明変数を部屋の広さのみで求めるのに対して、重回帰分析ではその説明変数が複数あるものである。


    5.y=ax+bの式には誤差が生じるがどう対処する。

    データにはy=ax+bの線から離れた点も存在する。 これらの誤差が大きければ大きいほど予測が不正確になる
    。 そのため、誤差を小さくしなければ正確な予想ができない。 そこで誤差をuとおきy=ax+bに挿入してu=y-ax-bと表す。 その後、誤差uを最小とするために最適なa、bを最小二乗法で求めれば誤差の小さい単回帰分析ができる。 image


    6.回帰分析を用いるメリット

    1. 散布図から当てはまる直線を引くことで分かりやすく理解できる。
    2. データが無いところも推論できる。


    7.総評

    以上のことから単回帰分析は散布図から求められ、y=ax+bというわかりやすい線によって求めたい数を把握できるためメリットは大きい。しかしながら、使われる場面は重回帰分析の方が多い。

    1.ニューラルネットワークの定義

    ニューラルネットワークとは、人間の脳内にある神経細胞(ニューロン)とそのつながり、 つまり神経回路網を人工ニューロンという数式的なモデルで表現したものである。

    2.ニューラルネットワークの歴史

    コンピューター科学の父であるアラン・チューリング氏によって様々な論文が出された。 その中の特に「チューリングテスト」によって第一次AIブームが到来し、 ニューラルネットワークの黄金時代を築くようになった。

    3.ニューラルネットワークを直感的に理解するための数式

    image 生物の脳内にはニューロンという細胞があります。 この細胞には電気物質が通り別の細胞に電気が流れることで脳が活性化します。 以下でこれを数式化したい。脳内では、シナプスという細胞があり、これをxとおく。 シナプスを経由した細胞体(ソマ)に集合する。これをbとおく。細胞体(ソマ)を流れるものがアクソンであり、 これをyに伝達します。これらを通る電気をwとおきます。 これらを数式に置き換えるとf(x1、x2)=b+w1x1+w2x2というわかりやすいものになります。 この数式を重ねれば重ねるほど脳の伝達が複雑化し多様化する。 つまり、ニューラルネットワークの構築には、シナプスに電気物質が流れ他の細胞に行くことが 繰り返されるように情報データを別のデータと集合し重ねる事で、 正確なデータを出すことができるネットワークを作ることができます。

    4.ニューラルネットワークの種類

    1.ディープニューラルネットワーク
    十分なデータがあることで、人間の力なしで機械が自動でデータから特徴を抽出してくれる。
    2.畳み込みニューラルネットワーク
    人工知能により画像分析を行う手法である。画像認識処理を行うのに使われる。
    3.再帰型ネットワーク
    時系列データを使用するネットワークである。翻訳機や音声認識に使われている。

    5.ニューラルネットワークの目的

    1.量を予測するため。
    例えば、売上金額を予想したいときに使用する。
    2.どこに何が分類されるか予想するため。
    例えば、受注か失注かを区別したい時に使用する。 
    3.異常なデータの抽出するため。
    例えば、機械の故障検知やクレジットカードの不正利用の検知に使用する。
    4.構造を発見するため。
    例えば、文書検索のためにキーワードを決める目的に使用します。

    6.ニューラルネットワークのモデル例

    主なモデルを分類すると以下の4つに分ける事ができる。

    1. 回帰モデル
    2. 分類モデル
    3. 異常検知モデル
    4. クラスタリングモデル

    これらのモデルを使用して物事を予測したり、分類したりします。

    7.私見

    現在、ニューラルネットワークは急成長している。私見では、 今後このネットワークは労働不足問題の解決に役立つものである。 ただし、現在のニューラルネットワークを用いて物事を判断する際に 倫理的な判断能力に欠落があり、これは機械学習の大きな課題である。

    8.総評

    以上のように、ニューラルネットワークは課題はあるものの、 今後の私達の生活の向上に必要不可欠なものである。

    1.ランダムフォレストの定義

    アルゴリズムで複数の決定木を使用して、「分類」または「回帰」をする、 機械学習の代表的なアルゴリズムのことである。

    2.決定木とは

    決定木とは、決定理論の分野において決定を行うためのグラフであり計画を 立案して目標を達成するために用いられる。 このグラフ(質問に対してyes or noと答える分岐グラフ)を見ると木のような 形をしていることから木構造であるといえる。 これが、決定木の名前の由来である。

    3.決定木の種類

    決定木は大別すると、分類と回帰に分ける事ができる。 分類木は性別を分けるように分類可能な変数で分類を目的にして決定木のアルゴリズムを使用する場合に使う。 回帰木は株価の変動のように分類がなく、過去からのデータを使い、未来の数値を予想する場合に使う。 これらの決定木のベースにアルゴリズムを形成することをランダムフォレストと呼ぶ。

    4.アンサンブル学習

    アンサンブル学習は決定木をランダムに構築してそれらの結果を合わせて分類と回帰をする方法である。

    5.バギング

    バギングは、アンサンブル学習を行う際に決定木を適用するアルゴリズムのことである。 これは、データのランダムサンプリングを繰り返すことで無作為に決定木のサンプリングを行います。

    6.ランダムフォレストのメリット、デメリット

    ランダムフォレストのメリット

    1. ノイズに強い
    2. 表現力が高い
    3. データ量が多くても高速に動く

    ランダムフォレストのデメリット

    1. 説明変数が膨大
    2. 説明変数をランダムに抽出するためデータと変数が少ないとうまく機能しない

    7.私見

    ランダムフォレストは説明変数がある程度ないといけない面はあるが、機械学習における分類、 回帰、クラスタリングに用いられるほど汎用性の高い便利なモデルであると考える。

    1.重回帰分析の定義

    重回帰分析とは、統計上のデータ解析手法の1つであり、 単回帰分析とは異なりある結果(目的変数)を説明する際に、 関連する複数の要因(説明変数)のうち、どの変数がどの程度、 結果を左右しているのかを関数の形で数値化し両者の関係を表し、 それを元にして将来の予測を行う統計手法のことです。

    2.重回帰分析の使用用途例

    1. ビジネスで売上を予想する
    2. 身体検査で体重の予測を行う
    3. イベントの参加人数を予想する

    3.重回帰式の表し方

    重回帰分析は目的変数をyとおき、複数個の説明変数をxi(i=1,2,3...)とする際に、 以下の式で表す事ができます。( 説明変数は3つとした場合)

    y=β0+β1x1+β2x2+β3x3

    4.重回帰分析の手順

    例として、カフェをこれから経営する予定のjさんがいると仮定します。
    1.これからjさんはどのくらい売上が成り立つのか知りたいと考えました。
    この際まずは、目的変数を決定します。この例では、目的変数は売上高です。

    2.jさんはカフェを経営するために売上高に関連しそうなデータを収集する必要があります。
    売上高を予想するには、都市人口、競合店舗、店舗面積、座席数、従業員数、メニュー数、利益率、広告費 などのデータが必要です。これらのデータは説明変数と呼び、目的変数が決まった後に説明変数を決定します。

    3.これらのデータが目的変数を出すのに必要なのか否か検討する必要があります。
    説明変数のデータの精度を上げるにはステップワイズ法で最適なデータを探します。 ステップワイズ法は、はじめに最も有効な説明変数を1個採用します。 その後まだ採用されていない説明変数の内で最も有用な説明変数を1個採用します。 これを繰り返し行うが最初の方で採用された説明変数も不要になる場合があるので採用された変数を 取り除くかどうかを確認する方法です。

    4.これによって決めた説明変数をエクセルのツールを利用します。
    エクセル以外にもネットにある計算ソフトも使うことができます。

    5.以上のものを使い方程式に落とし込むと
    Y=0.35✕店舗面積+0.33✕座席数+0.55✕従業員数.....+0.77

    売上高  回帰係数  回帰係数  回帰係数     定数項

    (数字は例です) 定数項は説明変数の影響を受けないベースの売上高の事です。

    6.この数式をを元にjさんは売上高を高める方法として説明変数の寄与率の高いものに予算を多めに配分して寄与率の低いものは予算の配分を少なくするなどの調整を行います。
    以上のような手順で分析を行います。

    5.私見

    私見では、単回帰分析に比べて重回帰分析は複雑さがあるため、 単回帰分析のように直線を引いて直感的に理解しにくい面がありますが、 いくつかの説明変数を用いて目的変数を割り出す事ができるという大きなメリットがあります。 特に重回帰分析はマーケティングで応用されることが多く、売上高の予想などに向いていることから ビジネスマンに最適かつ多様な面で使う事ができると考えられます。

    1.SVMの定義

    SVMとは、パターン認識の手法を用いて物事を分類することである。 パターン認識は事前に学習したデータを用いて、 新たなデータがどこに属すものかをあてはまる手法である。

    2.分類する線を引くイメージ

    集めたデータを元に最も適した線を引く。 クラス1に分類するものとクラス2に分類するものの間に 識別境界線を引くことで2つのクラスを分けることができます。 

    3.識別境界線を引く方法

    では、どのような基準で識別境界線を引くことができるのであろうか。 ハードマージンと呼ばれる関数が最大値になるベクトルが識別境界線となる。 つまり、マージンは、2クラスのデータの中で最も他クラスと近い位置にいるもの (これをサポートベクトルと呼ぶ)と識別境界f(x)=0との間のユークリッド距離のことです。 ただマージンを最大化して境界線を引くだけでは、境界線が平行移動すれば片方のクラスが 大きくなり、もう片方のクラスが小さくなる問題が生じる。 そのため下のグラフの赤いサポートクラスをd1と置き、青いサポートクラスをd2と置く。 そしてd1とd2を2で割れば最適点oが導かれる。この最適点oを通る識別境界線が クラス1とクラス2を分類するための最も適当な線となる。 image

    4.識別境界線を用いて分類することができる例

    1. 迷惑メールと通常のメールの区別
    2. 郵便番号を認識して分類する
    3. 顔認識ができる。事前に画像ピクセルから出された値から顔を否かを識別できる。

    5.私見

    私見では、SVMを応用することであらゆる画像を認識して対象のものか否かを区別できる 便利なツールとして用いることができる。 近年のアマゾン問題における過度な労働から機械化を進める大きな要因になると考える。 例えば、画像認識を用いれば、ダンボールの位置や向きやサイズの状態を画像が判別して振り分け作業が可能となる。 この技術が発展すれば人手が多く必要な工場では機械が導入され労働状況の改善や企業の生産力の工場に寄与することとなる。

    今回は特定のモデルではなく、パラメーターチューニングというテクニックについて解説したいと思います。

    パラメーターチューニングとは、特定のモデルにおけるパラメーター(例:Decision Forest Model における決定木の数)を調節することで、モデルの精度を上げていく作業です。実際にモデルを実装する際は、与えたれたデフォルト値ではなく、そのデータで一番精度が出るようなパラメーターを設定していくことが重要になります。その際、一回づつ手動で調節するのではなく、チューニングモジュールを使うことで最適なパラメーターが比較的楽に特定できます。

    具体例

    具体的な例を見ていきましょう。

    今回は他の場所でも触れたFast Forest Quantile Regressionを使います。

    通常、Microsoft Azure ML で初めに使う場合、デフォルトのパラメーターが設定してあります。

    下の図からわかるように、このモデルのデフォルトは決定木が100, それぞれの木における葉が20, 回帰をする分位が四分位であることがわかります。

    Microsoft Azure Machine Learning

    ここで、一番上の"Create Trainer Mode" を"Single Parameter"から"Parameter Range"に変えると、以下のように切り替わります。

    Microsoft Azure Machine Learning

    ここでは、パラメーターを調節するにあたって、決定木の数を16から64、葉の数を16から64と調節していきますよ、ということがわかります。ここに好きな値を自分で追加することも可能です。

    次に、"Tune Model Parameters"のモジュールを使って、実際にチューニングを行なっていきます。このモジュールも、以下の何種類かの設定からチューニング方法を選択することができます。

    ・Entire Grid - パラメーターの全ての組み合わせを順番に試していく。網羅的にチューニングができるが、その分時間がかかる。

    ・Random Grid - ランダムに候補を決め、その中で網羅的に行う。計算量を減らせるが、効果はEntire Gridとほぼ同等であることが証明されている。

    ・Random Sweep - ランダムにパラメーターを使用していく。計算量を減らせるが、必ずしも最適なパラメーターの組み合わせを探せるとは限らない。

    理想的にはRandom Gridを使うのですが、時間節約のため今はRandom Sweepを使い、組み合わせを10種類試すように設定します。それでも、実質的にモデルを10回学習させ直しているのと一緒なので、非常に時間がかかります。僕の場合1時間弱かかりました。

    Microsoft Azure Machine Learning

    では、パラメーターチューニングを行なったモデルとデフォルト値のモデルを比べていきましょう。下の図のようにモジュールを繋ぎます。左側のデフォルト値を使ったモデルと、右側のチューニングを行なったモデルを、最後に比較しています。

    Microsoft Azure Machine Learning

    結果を見てみましょう。

    上の列がデフォルト値のモデルで、下の列がチューニングされたモデルになります。比べてみると、チューニングされたモデルの方が誤差が約1/2になっていることがわかります。一度チューニングすると、その後同じデータに同じモデルを使うときに、より良いパラメーターを用いることができます。

    Microsoft Azure Machine Learning

    実際にどのパラメーターが一番精度が高いのでしょうか。今回は10種類試すように設定したので、結果が10列分表示されるはずです。

    一番右側の誤差を比べてみると、決定機の数=24, 葉の数=46などが一番誤差が小さいことがわかります。このパラメーターが上の図の比較で使われています。今回はRandom Gridを使ったので、この組み合わせが最適なパラメーターとは限りませんが、デフォルト値より誤差が半分になったといことで、大幅な改善と言えるでしょう。

    Microsoft Azure Machine Learning

    以上、パラメーターチューニングについてでした。時間がかかる作業ではありますが、精度を高めるためには是非活用したいテクニックです。


    その他のMicrosoft Azure Machine Learning Studioでやってみた記事も参考にしてください!
    決定木アルゴリズムCARTを用いた性能評価
    ロジスティクス回帰を用いた Iris Two Class Dataの分類
    分位点回帰を用いた飛行機遅延予測
    ランダムフォレスト回帰を用いた人気ブログタイトル予測

    概要

     はじめまして。アクセルユニバースのインターンに参加してる宇田川と申します。機械学習において必須の知識である数理モデルについて、その中でも特に基本的な回帰モデルに関して書いていこうと思います。

     このブログは機械学習を始めたばかり、または興味を持ち始めたばかりの方にわかっていただくようにわかりやすく書きました。事前知識としては機械学習の知識はもちろん必要なく高校数学における数学Bの確率の範囲程度の知識があれば十分です。よって細かい数式を書くことは避けました。回帰モデルのイメージを掴んでいただけたら幸いです。

    その他のMicrosoft Azure Machine Learning Studioでやってみた記事も参考にしてください!
    決定木アルゴリズムCARTを用いた性能評価
    ロジスティクス回帰を用いた Iris Two Class Dataの分類
    分位点回帰を用いた飛行機遅延予測
    ランダムフォレスト回帰を用いた人気ブログタイトル予測

    回帰モデルとは

     回帰モデルの説明をする前に回帰の語源について簡単に説明します。
    回帰という言葉は英語でregressionと書きます。この言葉は遺伝学者であり統計学者でもある19世紀のフランシス・ゴルトンによって造られました。ゴルトンは、背の高い祖先の子孫の身長が必ずしも遺伝せず、平均値に戻っていく、すなわち「後退(=regression)」する傾向があることを発見しました。これを「平均への回帰」といいいます。ゴルトンはこの事象を分析するために回帰モデルを発明しました。この発明が後に統計学の基礎となり回帰という言葉が誕生しました。

     では、回帰モデルについて書きましょう。回帰モデルとは関数をデータに適用することよって、ある(未知の、予測したい)変数yの変動を別の(既知の、予測するための)変数xの変動により説明・予測するための手法です。ここで登場した、説明したい変数yのことを目的変数、説明するために用いる変数xを説明変数と呼びます。説明変数xの数によって、1つであれば単回帰、2つ以上あれば重回帰という名前がついています。例として目的変数「頭の良さ」に対して、説明変数「大学の偏差値」のみで行うのが単回帰となり、目的変数「頭の良さ」に対して説明変数「コミュニケーション力」、「判断力」、「年齢」、「大学の偏差値」...と複数の説明変数を用いる場合が重回帰になります。

    Alt text

    1. 単回帰

     単回帰は先ほど説明したように説明変数xが一つになるので式で表すとy=ax+b(aは係数、bは定数項です。a,bをパラメータや回帰係数と言ったりします。a,bを上手に決めると目的変数yの予測がうまくできます。後ほど少し詳しく書きます。)の形になり直線によって目的変数yを予測するモデルとなります。もちろん直線によってyを予測することになってしまうので単回帰のみで分析することはほぼありません。単回帰によって大まかな予測することで大まかな推測ができその後、他のモデルによって精度よく分析をします。単回帰は式がとてもシンプルなので簡単に大まかな予測ができます。

    Alt text

    上の図からわかるように真の値と予測をしたyの値では誤差(上の図の緑線)が生じてしまいます。この誤差をεで表すと、先程のy=ax+bという式はy=ax+b+εと表せます。つまり、ε=y-ax-bとなり、この誤差は小さくしなければ良い予測ができたとは言えません。この誤差εを最小にするためのパラメータa,bを決めるのに有名な方法として最小2乗誤差法があります。最小2乗誤差法を説明をすると数学的になり数式が増えてしまうのでここではやめておきます。詳しく知りたい方は こちらのスライド21枚目を参考にしてみて下さい。ここではすでにわかっているn個の(x,y)の組(訓練データといいます。)を用いて最小2乗誤差法により最適なパラメータβ1,β0を求めています。

    2. 重回帰

     重回帰は説明変数xが2つ以上になるので式で表すと、説明変数xがn個(x₁,x₂,...,xn. nは2以上)ある時、y=a₀+a₁x₁+a₂x₂+...+an*xn(a₀,a₁,...,anはパラメータ)の形になるのでn種類のxの変数によって目的変数yを予測することができます。説明変数が増えるので単回帰よりも予測の精度が高いのは明らかですね。

    Alt text

    また重回帰の場合もパラメータa₀,a₁,...,anを誤差が小さくなるように考える必要があり、この場合も最小2乗誤差法が使われています。ここでも詳しく知りたい方は こちらを参考にしてみて下さい。パラメータα,β1,β2,...,βkを求めるために訓練データ(x,y)を用いて計算をしています。

     重回帰の実用例を挙げましょう。

    カフェをこれから経営する予定のjさんがいると仮定します。

    (1)これからjさんはどのくらい売上が成り立つのか知りたいと考えました。まずは、目的変数を決定します。この例では、目的変数は売上高です。

    (2)jさんはカフェを経営するために売上高に関連しそうなデータを収集する必要があります。売上高を予想するには、都市人口、競合店舗、店舗面積、座席数、従業員数、メニュー数、利益率、広告費(説明変数です。)などのデータが必要です。目的変数が決まった後に説明変数を決定します。

    (3)これらのデータが目的変数を出すのに必要なのか否か検討する必要があります。説明変数のデータの精度を上げるにはステップワイズ法で最適なデータを探します。ステップワイズ法は、はじめに最も有効な説明変数を1個採用する。その後まだ採用されていない説明変数の内で最も有用な説明変数を1個採用します。これを繰り返し行うが最初の方で採用された説明変数も不要になる場合があるので採用された変数を取り除くかどうかを確認する方法です。

    (4)以上のものを使い方程式に落とし込むと

    Y=0.35✕店舗面積+0.33✕座席数+0.55✕従業員数.....+0.77

    売上高  回帰係数  回帰係数  回帰係数     定数項

    (数字は例です)

    定数項は説明変数の影響を受けないベースの売上高の事です。

    (5)この数式をを元にjさんは売上高を高める方法として説明変数の寄与率の高いものに予算を多めに配分して寄与率の低いものは予算の配分を少なくするなどの調整を行います。

    このようにして重回帰は利用されます。

    3. ベイズ回帰

     単回帰、重回帰(まとめて線形回帰と呼びましょう。)では最小2乗誤差を求めてパラメータを決めていました(パラメータを推定するとも言います)。ベイズ回帰は線形回帰を確率の問題に読み替えることにしました。つまり、最適なパラメータを求めるということは一番高い確率になるパラメータを求めるということになります。ではどのようにして一番高い確率になるパラメータを求めればよいでしょうか。答えはたくさんあるのですが一番シンプルな例として尤度を最大にすることを扱いましょう(これを最尤推定法と呼びます)。

     尤度(ゆうど)の説明からします。パラメータθの確率モデルP(X=x;θ)と、D={x₁,x₂,...,xn}というそれぞれ独立な実現値(実現値は統計的な用語でデータ x を変量 X の値と考えています。)の集合を考えます。尤度はモデルのもとでDが得られる確率のことという意味です。尤度を数式で表すとP(D;θ)=P(X=x₁;θ)×P(X=x₂; θ)×...×P(X=xn;θ)と書けます。

     少し余談ですが、この式は確率を表す式的には何も変わりません。では尤度と確率は何が違うでしょうか。それは、式で表している意味合いが異なります。確率はこれから起きる可能性のあること(事象といいます。)それぞれがどれくらいの割合で起きるのかを表します。一方、尤度とはすでに観測されている(訓練データと呼んでいましたね。)起きてしまったデータの確率を考えています。

     余談はこれくらいにして最尤推定の説明をしましょう。最尤推定は尤度P(D;θ)を最大にするパラメータθを求めることです。このθを求めるときにP(D;θ)が積の形になると扱いづらいので両辺に対数をとって和の形にしたものlogP(D;θ)=logP(X=x₁;θ)+logP(X=x₂; θ)+...+logP(X=xn;θ)を対数尤度と言い、最尤推定を求めるときは対数尤度から求めるのが一般的です。

     ではこれを線形回帰において考えるとどうなるでしょうか。ここでは数式をたくさん書くのは避けて結果だけ書きます。先程のパラメータθに当たるところを単回帰ではa,b、重回帰ではa₀,a₁,...,anと考えて、訓練データ(x,y)においてある組(x,y)に対する誤差εがε~N(0,σ²)(これはどの組(x,y)に対しても誤差εが平均E(ε)=0、分散Var(ε)=σ²となり、またある2つの組(x,y)の誤差をε、ε'とするとその共分散Cov(ε,ε')=0と仮定しています。すると誤差εは平均0、分散σ²の正規分布に従うという意味です。このような分布を事前分布と呼んでいます。)として、最尤推定法により計算をしていくと最小2乗誤差法と同様の式が出て最適なパラメータの値は等しく推定することができます。

     ではベイズ回帰ではなぜ確率で考えるという手間を踏んでいるのでしょう。色々なメリットがありますが、簡単なメリットを挙げると、事前分布を考えて推定することができる点です。事前分布は私達がすでにわかっている知識などを考慮し分布を決め打ちするのが通常です。このように私達の知識を推定の中に取り入れられることです。

    最後に

     今回は回帰モデル、特に基本的な3つの回帰モデルを書きました。単回帰では式がシンプルである一方、誤差が大きく良い推定ができませんでした。それを克服したのが重回帰でした。重回帰は誤差が小さく良い推定ができる一方、式が複雑になってしまいました。またベイズ回帰では事前分布を考えることにより私達の事前知識を数式に取り入れることができました。このように基本的な3つの回帰モデルにはメリット・デメリットがありました。今後、新たなモデルを学ぶ上でも3つの回帰モデルは重要になるので必ず理解しましょう。次回は、今回の基本的な回帰モデルと同じくらい重要なニューラルネットワークについて書きます。

    参考文献

    機械学習をはじめよう 第12回 ベイズ線形回帰[前編]

    Pythonでベイズ線形回帰を実装してみた

    回帰分析(単回帰分析)をわかりやすく徹底解説!

    尤度とは何者なのか?

    概要

    ML.NETは、Microsoftが開発したクロスプラットフォーム対応の機械学習フレームワークである。 ML.NETで提供されているAutoMLを使うと、アルゴリズムの選択やオプションの設定などが自動で行われ、最も良い結果を出したモデルを得ることができる。 今回は、AutoMLによる文章の二項分類を行った。

    環境

    • macOS Sierra 10.12.6
    • .NET SDK 2.2.107
    • ML.NET 0.3.27703.4

    手順

    .NET SDKのインストール

    次のURLからインストーラをダウンロードし、インストールする。

    Download .NET Core

    ML.NET CLIのインストール

    .NET SDKに含まれる dotnet コマンドを使用し、ML.NET CLIをインストールする。

    $ dotnet tool install -g mlnet
    

    AutoMLを用いたテキスト分類

    1. 新規ディレクトリを作成する

    $ mkdir myMLApp
    $ cd myMLApp
    

    2. Wikipedia detoxデータセットをダウンロードする

    以下のようにしてデータセットをダウンロードする。

    $ curl -O 'https://raw.githubusercontent.com/dotnet/machinelearning/master/test/data/wikipedia-detox-250-line-data.tsv'
    

    wikipedia-detox-250-line-data.tsv は、文章が否定的(Sentiment=1)か肯定的(Sentiment=0)かがラベル付けされている。 データは以下のような形式になっている。

    Sentiment   SentimentText
    1           ==RUDE== Dude, you are rude upload that carl picture back, or else.
    1           == OK! ==  IM GOING TO VANDALIZE WILD ONES WIKI THEN!!! 
    0 I hope this helps.

    3. 学習をする

    与えられた文章に対して、Sentimentで二項分類するように学習する。 下記の mlnet auto-train コマンドを実行すると、様々なデータ変換、アルゴリズム、アルゴリズムのオプションが組み合わせて試された後、最も結果の良いものが出力される。

    $ mlnet auto-train --task binary-classification --dataset "wikipedia-detox-250-line-data.tsv" --label-column-name "Sentiment" --max-exploration-time 10
    

    オプションの意味は以下の通り。

    • --task: 機械学習の種類
    • --dataset: 使用するデータセット
    • --label-column-name: データセットの中で推論したいラベル
    • --max-exploration-time: ML.NETがモデルを探索する最大の秒数

    実行すると以下のようなログが出力される。

    Best Accuracy: 88.24%, Best Algorithm: LinearSvmBinary, Last Algorith...00:00:10
    
    ===============================================Experiment Results=================================================
    ------------------------------------------------------------------------------------------------------------------
    |                                                     Summary                                                    |
    ------------------------------------------------------------------------------------------------------------------
    |ML Task: binary-classification                                                                                  |
    |Dataset: wikipedia-detox-250-line-data.tsv                                                                      |
    |Label : Sentiment                                                                                               |
    |Total experiment time : 10.42 Secs                                                                              |
    |Total number of models explored: 33                                                                             |
    ------------------------------------------------------------------------------------------------------------------
    |                                              Top 5 models explored                                             |
    ------------------------------------------------------------------------------------------------------------------
    |     Trainer                              Accuracy      AUC    AUPRC  F1-score  Duration #Iteration             |
    |1    LinearSvmBinary                        0.8824   0.7273   0.7848    0.9167       0.2         17             |
    |2    SgdCalibratedBinary                    0.8235   0.7576   0.7857    0.8696       0.2          7             |
    |3    SgdCalibratedBinary                    0.8235   0.7576   0.7857    0.8696       0.2         10             |
    |4    SgdCalibratedBinary                    0.8235   0.7576   0.7857    0.8696       0.2         19             |
    |5    SgdCalibratedBinary                    0.8235   0.7576   0.7857    0.8696       0.2         22             |
    ------------------------------------------------------------------------------------------------------------------
    

    表の見出しの意味は次の通り。

    • Trainer: 学習に使われたアルゴリズム
    • Duration: 学習時間
    • #Iteration: 学習の反復回数

    評価指標(Accuracy、AUC、AUPRC、F1-score)については以下を参照。

    学習後、ディレクトリ構成は以下のようになる。

    .
    ├── SampleBinaryClassification
    │   ├── SampleBinaryClassification.ConsoleApp
    │   │   ├── ModelBuilder.cs
    │   │   ├── Program.cs
    │   │   └── SampleBinaryClassification.ConsoleApp.csproj
    │   ├── SampleBinaryClassification.Model
    │   │   ├── DataModels
    │   │   │   ├── ModelInput.cs
    │   │   │   └── ModelOutput.cs
    │   │   ├── MLModel.zip
    │   │   └── SampleBinaryClassification.Model.csproj
    │   ├── SampleBinaryClassification.sln
    │   └── logs
    │       └── debug_log.txt
    └── wikipedia-detox-250-line-data.tsv
    

    4. 学習したモデルを使用する

    自動生成されるサンプルプロジェクトは、データファイルから一つの文章を取り出して推論をする内容となっている。 サンプルプロジェクトを実行するには以下のようにする。

    $ cd SampleBinaryClassification/SampleBinaryClassification.ConsoleApp
    $ dotnet run
    

    出力結果

    Single Prediction --> Actual value: True | Predicted value: True
    =============== End of process, hit any key to finish ===============
    

    参考

    こんにちは、システム部の大瀧です。

    今回は初歩ということでGoogle Colaboratoryを使ってみようと思います。
    せっかくなので実際に動くものとして、scikit-learnが用意しているbostonのデータセットを使って初歩的な単回帰分析を行ってみます。

    1. Google Colaboratoryとは

    Colaboratoryは、完全にクラウドで実行されるJupyterノートブック環境です。設定不要で、無料でご利用になれます。
    Colaboratoryを使用すると、コードの記述と実行、解析の保存や共有、強力なコンピューティングリソースへのアクセスなどをブラウザからすべて無料で行えます。

    Google Codelaboratoryへようこそ より

    つまりGoogle Colaboratory(以下Colab, コラボと読むようです)は、端的にいうとクラウド版のjupyter notebookということです。
    誰でも無料で簡単に利用することができるという敷居の低さや、GPU環境を無料で利用可能であることなどがColabのメリットです。

    補足. jupyter notebookとは

    「jupyter notebookが何か」を簡潔にいうとプログラムの実行環境のことなのですが、優れているのはnotebookというだけあってコードだけでなくメモやファイル、コードの実行結果などをノートのように残すことができる点です。
    特にデータの処理を行ったグラフなどを残しておけるのは非常に見やすく、データを分析する助けになります。

    2. 実際に動かしてみる

    Colabの準備は簡単です。
    Googleアカウントを用意しましょう。それだけです。

    https://colab.research.google.com/にアクセスします。
    以下のような画面が表示されるはずです。

    blog_colab_01.png

    次に新しいノートブックを作成します。
    メニューの「ファイル」から「Python3の新しいノートブック」を選択すると真っさらなノートブックが作成されます。

    blog_colab_02.png


    画像の赤枠が「セル」と呼ばれ、コードはセル単位で実行することが可能です。
    せっかくなので簡単にコードを記載してみます。
    今回はscikit-learnというライブラリのBostonデータセットを使ってなんちゃって線形回帰を試してみたいと思います。

    blog_colab_03.png

    import pandas as pd
    import matplotlib.pyplot as plt
    from sklearn.datasets import load_boston
    
    # データセットの取得
    # 米国ボストン市郊外における地域別の住宅価格のデータセット
    boston = load_boston()
    
    # 取得したデータをpandasのdataframeへ
    boston_df = pd.DataFrame(boston.data, columns=boston.feature_names)
    price = boston.target.reshape(-1,1)
    lstat = boston_df['LSTAT'].values
    plt.scatter(price, lstat)
    plt.xlabel('house price') # x軸のラベル
    plt.ylabel('% lower status of the population') # y軸のラベル
    plt.grid() # グリッド線を表示
    plt.show() # 図の表示
    

    実行するコードをセルに書き込んだらセルの左上にある再生ボタン?を押しましょう。これでコードが実行されます。
    もし複数のセルを実行したい場合は、メニューにある「ランタイム」の項目の「すべてのセルを実行」を選択してください。他にも一部のセルのみを実行することなどが可能です。

    blog_colab_04.png

    実行するとグラフが描画されます。
    今回は「地域別住宅価格(X軸)」と「給与の低い職業に従事する人口の割合 (%)(Y軸)」のグラフです。プロットされたドットをみるとどうやら相関関係がありそうです。
    当たり前かもしれませんが、住宅の価格が高い地域には給与の低い職業に従事する人が少ないようです。

    ではこれらを線形回帰(今回は手抜き単回帰分析)します。
    描画されたグラフはそのままに新たに分析結果を追加したグラフを描画します。
    メニュー下の「+コード」を押します。

    新たに作成されたセルに新たにコードを書き込み、今回書き込んだセルの左上にある再生ボタンをクリックすると、このセルのみが実行されます。
    画像のように線形直線が描画された新たなグラフが表示されたでしょうか。

    blog_colab_05.png

    # 線形回帰モデルのクラスを読み込み
    from sklearn.linear_model import LinearRegression
    # 線形回帰のインスタンスを生成
    lr = LinearRegression()
    
    # 単回帰モデルの学習を実行
    lr.fit(price, lstat)
    plt.scatter(price, lstat)
    plt.xlabel('house price') # x軸のラベル
    plt.ylabel('% lower status of the population') # y軸のラベル
    plt.grid()
    plt.plot(price, lr.predict(price), color = 'red')
    plt.show()
    

    作成したファイルなのですが、アカウントのGoogle Drive内にColab Notebooksというフォルダができており、そこに保存されています。ここで察しがつくのですが、Google Driveに保存されているファイル(例えば集計データなど)をロードして、コードの中で使うことも容易になっており、そういう点もColabの魅了ですね。

    今回のサンプルを公開しておきます[リンク]
    このように簡単に公開できることも大きな魅力ですが、これらを自身のワークスペースに複製して編集することなどもできます。

    今回のサンプルはグラフの描画などを行いましたが、単純にPythonを初めて触る際にも使い勝手が良いかと思いますので是非使ってみましょう。

    概要

    ビルド済みのTensorFlowをpipでインストールすると、CPUの命令セットのAVX2やFMAが有効にならない。 AVX2やFMAを用いると、演算速度や精度の向上が期待できる。

    参考 MMX, SSE, AVX, FMA命令とは何かを明らかにしたい会

    そこで今回は、ソースコードからビルドしてAVX2とFMAを有効にしたTensorFlowを用意し、ビルド済みのパッケージをインストールしたものと、速度や精度の比較を行った。

    環境

    • プロセッサ Intel Core i7-5557U 3.1 GHz
    • メモリ 16GB 1867 MHz DDR3
    • macOS Sierra 10.12.6
    • Python 3.6.8
    • TensorFlow 1.13.1

    方法

    学習は以下のようなCNNで行った。 データセットはMNIST、Fashion MNIST、CIFAR-10を用いた。

    import tensorflow as tf
    
    # データセットの選択
    dataset = tf.keras.datasets.mnist
    # dataset = tf.keras.datasets.fashion_mnist
    # dataset = tf.keras.datasets.cifar10
    
    (x_train, y_train), (x_test, y_test) = dataset.load_data()
    x_train, x_test = x_train / 255.0, x_test / 255.0
    
    # shapeをモデルの入力に合わせる
    if len(x_train.shape) == 3:
        x_train = x_train.reshape(x_train.shape + (1,));
        x_test = x_test.reshape(x_test.shape + (1,));
    
    # CNNモデルの作成
    model = tf.keras.models.Sequential([
        tf.keras.layers.Conv2D(32,
            kernel_size=(3, 3),
            activation=tf.nn.relu,
            input_shape=x_train.shape[1:]),
        tf.keras.layers.Conv2D(64, (3, 3), activation=tf.nn.relu),
        tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
        tf.keras.layers.Dropout(0.25),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(128, activation=tf.nn.relu),
        tf.keras.layers.Dropout(0.5),
        tf.keras.layers.Dense(10, activation=tf.nn.softmax)
    ])
    model.compile(optimizer='adam',
        loss='sparse_categorical_crossentropy',
        metrics=['accuracy'])
    
    # 訓練
    model.fit(x_train, y_train, epochs=12)
    # 評価
    model.evaluate(x_test, y_test)
    

    計測は以下のコマンドで行った。

    $ time python cnn.py
    

    結果

    MNIST

    AVX2, FMA 有 AVX2, FMA 無
    学習時間 26m37s 28m32s 6.7%
    精度 0.9939 0.9928 +0.0011

    Fashion MNIST

    AVX2, FMA 有 AVX2, FMA 無
    学習時間 25m30s 27m59s 8.9%
    精度 0.9218 0.9241 -0.0023

    CIFAR-10

    AVX2, FMA 有 AVX2, FMA 無
    学習時間 32m00s 37m04s 13.7%
    精度 0.7049 0.7034 +0.0015

    まとめ

    AVX2, FMAが有効であると実行時間が短くなった。一方、精度はあまり変わらなかった。

    概要

    TensorFlowをpipでインストールして実行したところ、以下のようなログが表示され、AVX2FMAが有効でないことがわかった。

     2019-04-09 10:28:05.680156: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
     Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
    

    AVX2FMAは、SIMDの拡張命令セットで、これらを使用することで速度の向上が期待できる。 今回は、TensorFlowでAVX2FMAを有効にするため、ソースコードからビルドをした。

    環境

    • macOS Sierra 10.12.6
    • Python 3.6.8
    • Xcode 9.2
    • Bazel 0.21.0
    • TensorFlow 1.13.1

    手順

    1. Pythonの仮想環境の作成

    pyenv, pyenv-virtualenvを使用する。

     $ pyenv virtualenv 3.6.8 TensorFlow-build # python 3.6.8、「TensorFlow-build」という名前の仮想環境を作成する
     $ pyenv local TensorFlow-build # 現在のディレクトリでTensorFlow-buildを使用するよう設定する 
    

    2. TensorFlowの依存パッケージのインストール

     $ pip install -U pip six numpy wheel setuptools mock # 最新版をインストールする
     $ pip install -U keras_applications==1.0.6 --no-deps # keras_applications 1.0.6のみのインストール(依存パッケージはインストールしない)
     $ pip install -U keras_preprocessing==1.0.5 --no-deps # keras_preprocessing 1.0.5のみのインストール 
    

    3. Bazelのインストール

    Bazelとは、Googleが開発したビルドツールで、TensorFlowのビルドにも用いられている。

    参考 Googleが開発する最新ビルドツール「Bazel」を使ってみよう

    今回は、公式の推奨する、バイナリインストーラー方式でインストールする。

    3.1 Xcodeをインストールする

    Xcodeは、Bazel でobjc_*ios_*をサポートするのに用いられる。 インストールはApp Storeから行う。XcodeはiOS SDK 8.1、本体6.1以降のバージョンが必要となる。

    インストール後、下記のコマンドでライセンスに同意する。

     $ sudo xcodebuild -license accept 
    

    3.2 Bazelインストーラーをダウンロードする

    bazel-0.21.0-installer-darwin-x86_64.sh を下記URLからダウンロードする。 https://github.com/bazelbuild/bazel/releases

    0.21.0よりも新しいバージョンを使用すると、TensorFlowをビルドできない。

    3.3 インストーラーを実行する

    下記コマンドで実行する。--userフラグをつけると、Bazelが$HOME/binにインストールされ、.bazelrcのパスが $HOME/.bazelrcになる。

     $ chmod +x bazel-0.21.0-installer-darwin-x86_64.sh # 実行権限を付与
     $ ./bazel-0.21.0-installer-darwin-x86_64.sh --user # インストールを実行 
    

    3.4 環境変数を設定する

    ~/.bash_profileに下記コマンドを追記して、Bazelのバスを通す。

     $ export PATH="$PATH:$HOME/bin" 
    

    3.5 動作を確認する

     $ bazel version # バージョン情報を出力する 

    出力結果

     Starting local Bazel server and connecting to it... 
     INFO: Invocation ID: 06b87c44-ed30-4d0d-8211-cb25664ca345
     Build label: 0.21.0
     Build target: bazel-out/darwin-opt/bin/src/main/java/com/google/devtools/build/lib/bazel/BazelServer_deploy.jar
     Build time: Wed Dec 19 12:57:09 2018 (1545224229)
     Build timestamp: 1545224229
     Build timestamp as int: 1545224229 
    

    4. TensorFlowのソースコードのダウンロード

    gitでソースコードを取得する。

     $ git clone https://github.com/tensorflow/tensorflow.git # ソースを取得する
     $ cd tensorflow # ソースコードのディレクトリに移動する 
    

    ビルドするTensorFlowのバージョンのブランチをチェックアウトする。 利用可能なバージョンは、リリースページから確認できる。

     $ git checkout branch_name # r1.9, r1.10, etc. 

    5. オプションの設定

    下記コマンドでオプションを設定する。

     $ ./configure 

    今回はすべてデフォルトの設定にした。

    前述の通り、Bazelのバージョンが0.21.0よりも新しいと、ここでエラーとなる。

     You have bazel 0.24.1 installed.
     Please downgrade your bazel installation to version 0.21.0 or lower to build TensorFlow! 
    

    6. ビルド

    以下のコマンドでビルドする。筆者の環境では1.5時間かかった。

     $ bazel build --config=opt --copt=-mavx2 --copt=-mfma //tensorflow/tools/pip_package:build_pip_package 

    ビルドに成功すると、最後に以下のようなログが出力される。

     Target //tensorflow/tools/pip_package:build_pip_package up-to-date:
       bazel-bin/tensorflow/tools/pip_package/build_pip_package
     INFO: Elapsed time: 5396.832s, Critical Path: 348.37s
     INFO: 3499 processes: 3499 local.
     INFO: Build completed successfully, 3500 total actions 

    続いてpipパッケージをビルドする。

     $ ./bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg # /tmp/tensorflow_pkg に配置する 

    7. インストール

    以下のコマンドでビルドしたTensorFlowをインストールする。

     $ pip install /tmp/tensorflow_pkg/tensorflow-<version-tags>.whl 

    動作確認をする。

     $ cd .. # ソースコードのディレクトリから抜ける
     $ python -c "import tensorflow as tf; tf.enable_eager_execution(); print(tf.reduce_sum(tf.random_normal([1000, 1000])))" # TensorFlowを動かす 

    出力結果

     tf.Tensor(3945.0461, shape=(), dtype=float32) 

    AVX2FMAに関するログが出力されていないことが確認できる。

    なお、TensorFlowのソースコードがあるディレクトリでTensorFlowをインポートすると、以下のようにエラーになるので注意。

     ImportError: Could not import tensorflow. Do not import tensorflow from its source directory; change directory to outside the TensorFlow source tree, and relaunch your Python interpreter from there. 

    参考

    このアーカイブについて

    このページには、過去に書かれた記事のうち機械学習カテゴリに属しているものが含まれています。

    前のカテゴリは物体検知です。

    次のカテゴリはアプリ開発です。

    最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。