「具体的にはログの解析・集計のほか、検索動向の分析などにも利用しています。よく検索されているということは、そこが故障しやすい箇所ということ。さらに言えば、リコールの予兆とも言えます。『Maintenance.c』では AI 技術なども駆使して、これをシステム上でサジェストする仕組みを用意し、利用者(修理工場)が顧客(修理依頼者)に早めの問題解決を提案するなどできるようにしました。クラウド移行以前もこうした方法論はあったものの、リソースが不足しており実現できていませんでした。もちろん、大手自動車メーカーもすでにこうした取り組みを進めていると思いますが、ブロードリーフはそれをメーカーの壁を越えて横断的に行えるのが強みです。なお、AI 活用については、今後さらに推し進めていく予定。たとえば車の情報だけでなく、お客さまの特性も学習させ、入庫する前により適切なサジェストができるようにするなどといったことを考えています。また、Cloud Vision API でナンバープレートを自動認識させたり、Cloud Speech-to-Text API でお客さまとの電話内容などを自動的にテキスト化したりといったことも検討中です。」(祖慶さん)
進化型コンピューティング アルゴリズムをスケーリングする優れたインフラストラクチャを構築すれば、この領域はさらに進展するということは判明していましたが、大規模システム開発に明るい研究者は多くはいません。幸い、ここ数年間で Kubernetes などのテクノロジーが生み出され、専門のエンジニアでなくても簡単に分散環境によるソリューションを構築できるようになりました。そこで本稿では、Kubernetes を活用してスケーラブルな進化型アルゴリズムをデプロイする仕組みの実例を紹介します。コードと手順もこちらで公開していますので、ML 研究において GKE 上で ES を試す際の参考にお役立てください。
ちなみに、Google Cloud ではコンテナによる分散トレーニングが可能なプラットフォームとして AI Platform も提供しています。AI Platform では TensorFlow と同様の分散処理をサポートする ML フレームワークが利用可能です。しかしその目的は、おもにモデルを非同期でトレーニングすることであり、次のセクションで説明するような ES の分散コンピューティングの目的とは異なります。
進化戦略入門
ES は一種のブラックボックス最適化です。ベースとなるタスクや関数に勾配がない場合や、勾配の計算が非常に複雑な場合、または勾配推定にノイズが多く学習できない場合など、勾配ベースのアルゴリズムではうまく解決できない ML タスクに有効です。例として、下の図の左側に示す地形に立っていることを想像してみてください。あなたのタスクは、目隠しをして最も低い場所へ向かうことです。あなたは複数の魔法の玉を持っており、それを介してしか周囲の状況を知ることができません。
ES のアプローチはこれとはまったく異なります。最適化のステップごとに、複数回の試行を行います。そして、高い適応度(fitness)を示した設定に基づいて進み先を決めます(適応度とは、試行がどのくらい優れているかを測る指標です。上図の地形の例では地面の高さがそれに当たり、低いほど適応度が高いことになります。RL で言えば試行で得られる累積報酬に当たります)。この過程を通じて、適応度が低い試行は取り除かれ、適応度がもっとも高いものだけが生き残ります。これが進化の過程に似ているため、進化戦略という名前が付けられています。
先ほどのたとえに当てはめて ES の仕組みを説明するなら、各ステップで玉を落として転がす代わりにピストルに玉を込めて数発を発射し、いくつかの玉を周囲に散りばめる、ということになります。それぞれの玉が地面に打たれた時点で位置と高度がわかるので、ステップを繰り返すうちに高度が低いと推定される場所に徐々に移動していけます。この方法は、図の左右どちらの地形にもうまく働きます(高い山の向こうにも届く強力なピストルを使うことを想定します)。またこの方法なら、複数回の試行を同時に実行することで最適化を簡単に高速化できます。ますたとえるならピストルの代わりに散弾銃を使うようなものです。
message RolloutRequest {
// Index of rollout
int32 rollout_index = 1;
// Random seed from the master
int32 env_seed = 2;
// The weights of the neural network policy
Repeated double policy_weights = 3;
// Whether this request is evaluation
bool evaluate = 4;
}
message RolloutResponse {
// Index of rollout
int32 rollout_index = 1;
// The reward collected in the rollout
double rollout_rewards = 2;
}
service Rollout {
// The RPC service for policy evaluation
rpc RolloutWithParameter(RolloutRequest) returns (RolloutResponse) {}
}
このサンプルで利用する ES アルゴリズムは、estool に基づく Parameter-exploring Policy Gradients(PEPG)と 、pycma に基づく Covariance Matrix Adaptation(CMA)です。これらは解決がとりわけ難しい連続制御 RL 環境である Google Brain の Minitaur Locomotion や OpenAI の BipedalWalkerHardcore-v2 でも試せます。また、コードを拡張して ES アルゴリズムを追加したり、設定を変更して独自の環境でアルゴリズムを試したりすることも簡単です。具体的には、algorithm.solver.Solver で定義されたインターフェースに従った実装であれば他のコードと合わせて実行できるはずです。
クラスタができたら、次の 3 つのステップでサンプルの ES コードを GKE で実行できます。それぞれ簡単な bash コマンドです。
コントローラとワーカーのコンテナ イメージをビルドする
ワーカーをクラスタにデプロイする
コントローラをクラスタにデプロイする
# Step 1: Build a container image for the controller and the workers.
gcloud builds submit \
--tag gcr.io/${GCLOUD_PROJECT}/es-on-gke:1.0 . \
--timeout 3600 \
--project ${GCLOUD_PROJECT}
# Step 2: Replace the ${GCLOUD_PROJECT} in the YAML file and run the command.
kubectl apply -f deploy_workers.yaml
# Step 3: When all the workers are started and running,
# replace the ${GCLOUD_PROJECT} in the YAML file and run the command.
kubectl apply -f deploy_master.yaml
POD_NAME=$(kubectl get pod | grep es-master | awk '{print $1}')
# Download reward vs time plot.
kubectl cp $POD_NAME:/var/log/es/log/reward_vs_time.png $HOME/
# Download reward vs iteration plot.
kubectl cp $POD_NAME:/var/log/es/log/reward_vs_iteration.png $HOME/
# Download best model so far.
kubectl cp $POD_NAME:/var/log/es/log/best_model.npz $HOME/
# Download model at iteration 1000.
kubectl cp $POD_NAME:/var/log/es/log/model_1000.npz $HOME/
# Download all test scores.
kubectl cp $POD_NAME:/var/log/es/log/scores.csv $HOME/
ES は、勾配ベースのアルゴリズムでよい結果が得られない ML タスクに対して強力なソリューションとなります。ES には並列処理との親和性が高い性質があるので、Kubernetes で ES を実行することで大幅な高速化を実現できます。これにより、ML リサーチャやエンジニアが新しいアイデアを試すイテレーションのスピードが上がります。
簡単にスケールできるという ES の力をもっとも活かせる応用は、難しい問題を解くためのシミュレーション環境をローコストに用意できるケースです。最近の研究(1、2)では、コントローラを実環境にデプロイする前に、まずシミュレーションで仮想ロボット コントローラをトレーニングする方法が効果的であることが実証されています。また、手作業のプログラミングではなく、収集した観測結果から学習で得られたディープラーニング モデルでもシミュレーション環境を実現できます(1、2、3)。こうした応用であれば、ES のスケーリングを活かした数 1000 ノード規模の並列シミュレーション環境での学習が可能でしょう。
進化の手法を用いると最適化する対象の選択肢がぐんと広がるため、従来の RL ポリシー最適化では対応できなかったさまざまな応用が可能です。たとえば、この最新の研究では RL 環境で ES を使い、ポリシーのトレーニングだけでなくより優れたロボットの設計まで学習しています。進化の手法を使うジェネラティブ デザインの領域では、ずっと多くのクリエイティブな応用が生まれるはずです。また、この最新の研究成果では、複数の RL タスクを実行できる最小のニューラル ネットワーク アーキテクチャが、進化型アルゴリズムを使うことでパラメータのトレーニングなしで得られることを実証しています。この結果は多くの ML リサーチャを驚かせ、進化の手法が切り拓くまったく新しい研究分野の存在を示しています。
ディープ ラーニングの革命は、大規模なディープ ニューラル ネットワークのトレーニングを実現する GPU が触媒となり生じました。同様に、ローコストな CPU で構成された大規模クラスタへ簡単にスケールできる進化の手法は、これからのコンピューティング革命をリードするカギとなるでしょう。
Google Cloud Next ’19 in Tokyo の開催まで、3 週間を切りました。イベントへのお申し込みおよびセッション登録はお済みでしょうか? 本日は、7 月 31 日(水)の夜の時間帯に開催するセッションをピックアップしてご紹介します。18 時以降に開催するセッションでは、お弁当を提供させていただきますので、お仕事帰りにぜひお気軽にご参加ください。なお、ご来場の際には事前のイベント申し込み・希望セッションへの登録 をお願いいたします。
7 月 31 日(水)| 7:40–8:20 PM D1-7-S04 ゼロから始める Google Kubernetes Engine 〜Kubernetes の基本からクラウドネイティブ・アプリの運用まで
Google Kubernetes Engine は小規模アプリから大規模システムまで、本番環境に必要な様々な機能を備えています。本講演では Kubernetes の基本となる機能、簡単なアプリの展開に加え、自動スケールやモニタリングなど Google Kubernetes Engine を最大限に活用した、クラウドネイティブ・アプリの運用方針までご紹介します。
テーマ:セキュリティ
7 月 31 日(水)| 7:40–8:20 PM D1-7-S01 実例から学ぶ、VPC Service Control Deep Dive
Google Cloud では企業の中の機密データの価値を最大化するため、その前提となる機密データを企業内で安全に扱うための方法として VPC Service Control という機能を提供しております。このセッションではその詳細を、実際に実装されたお客様の実例とともに解説します。
Google Cloud Certified Lounge
Google Cloud 認定資格取得者専用のラウンジを東京プリンスホテル 11 階 Room H にご用意しております。ラウンジでリフレッシュしていただき、Google Cloud Next ’19 in Tokyo を 100% お楽しみください。
Google Cloud 認定資格取得者特典
Google Cloud 認定資格取得者の特典として、Google Cloud スペシャル バックパックをご用意しています。東京プリンスホテル 11 階 Room H、Google Cloud Certified Loung にお立ち寄りください。
データ分析のほか、BigQuery ML では SQL クエリを使って機械学習モデルを作成、評価できます。機械学習フレームワークやプログラミング言語に関する詳細な知識がなくても、データ サイエンティストであれば、わずかなクエリだけで回帰モデルの構築や評価を行えるのです。ここでは、エイムズにある不動産の最終販売価格を予想する線形モデルを作ってみましょう。このモデルでは、居住スペースの広さ、築年数、条件全般、品質全般を入力としてトレーニングを行います。モデルのコードは次のようになります。
model1 = """
CREATE OR REPLACE MODEL
`my-example-housing-dataset.ameshousing.linearmodel`
OPTIONS(model_type='linear_reg', ls_init_learn_rate=.15, l1_reg=1, max_iterations=5) AS
SELECT
IFNULL(SalePrice, 0) AS label,
IFNULL(GrLivArea, 0) AS LivingAreaSize,
YearBuilt,
OverallCond,
OverallQual
FROM
`my-example-housing-dataset.ameshousing.train`
"""
Google Cloud Speech-to-Text なら金融・証券業界独自の用語にもスムーズに対応
「私が所属している先端 IT 戦略部(現在は組織改編によって「システム企画部」に)は、先端テクノロジーを駆使して、業務の効率化を図る取り組みを企画する部署。今回お話しする Google Cloud Speech-to-Text(Speech-to-Text) は、従業員のテキスト入力をサポートするために導入を決定しました。」(武部さん)
なお、武部さん曰く、Speech-to-Text の導入には、これから拡大していくクラウド活用を見据えたテストケースという意味合いもあったそうです。情報セキュリティがとりわけ厳しい金融・証券業界では、外部にデータを置くことがタブーとされています。そこで、まずはデータを外部サーバーに保存することなく利用できる API でクラウド サービスを使い始めることにしたのです。
SELECT
w1mpro_ep,
mjd,
load_id,
frame_id
FROM
`bigquery-public-data.wise_all_sky_data_release.mep_wise`
WHERE
source_id_mf='3425p651_ac51-032187'
ORDER BY
mjd ASC
CREATE TEMP FUNCTION
ArcSecondDistance(p1 GEOGRAPHY, p2 GEOGRAPHY,
d FLOAT64) AS (ST_DISTANCE(p1,p2) < d * 30.8874796235);
SELECT
source_id_mf,
point
FROM
`bigquery-public-data.wise_all_sky_data_release.mep_wise`
WHERE
ArcSecondDistance(point,
ST_GEOGPOINT(201.5, -2.6),60)
AND ST_CONTAINS(
ST_GEOGFROMTEXT('Polygon((201.00 -3.10,201.00 -2.10,202.00 -2.10,202.00 -3.10, 201.00 -3.10))'),point)
各手順の詳細については、公式ドキュメントを参照してください。本稿では上記の手順の例として、 Go を用いて実装します。
package main
import (
"context"
"encoding/base64"
"fmt"
"log"
"net/http"
"os"
"time"
"cloud.google.com/go/storage"
"github.com/google/uuid"
"golang.org/x/oauth2/google"
iam "google.golang.org/api/iam/v1"
)
var (
// iamService is a client for calling the signBlob API.
iamService *iam.Service
// serviceAccountName represents Service Account Name.
// See more details: https://cloud.google.com/iam/docs/service-accounts
serviceAccountName string
// serviceAccountID follows the below format.
// "projects/%s/serviceAccounts/%s"
serviceAccountID string
// uploadableBucket is the destination bucket.
// All users will upload files directly to this bucket by using generated Signed URL.
uploadableBucket string
)
func signHandler(w http.ResponseWriter, r *http.Request) {
// Accepts only POST method.
// Otherwise, this handler returns 405.
if r.Method != "POST" {
w.Header().Set("Allow", "POST")
http.Error(w, "Only POST is supported", http.StatusMethodNotAllowed)
return
}
ct := r.FormValue("content_type")
if ct == "" {
http.Error(w, "content_type must be set", http.StatusBadRequest)
return
}
// Generates an object key for use in new Cloud Storage Object.
// It's not duplicate with any object keys because of UUID.
key := uuid.New().String()
if ext := r.FormValue("ext"); ext != "" {
key += fmt.Sprintf(".%s", ext)
}
// Generates a signed URL for use in the PUT request to GCS.
// Generated URL should be expired after 15 mins.
url, err := storage.SignedURL(uploadableBucket, key, &storage.SignedURLOptions{
GoogleAccessID: serviceAccountName,
Method: "PUT",
Expires: time.Now().Add(15 * time.Minute),
ContentType: ct,
// To avoid management for private key, use SignBytes instead of PrivateKey.
// In this example, we are using the `iam.serviceAccounts.signBlob` API for signing bytes.
// If you hope to avoid API call for signing bytes every time,
// you can use self hosted private key and pass it in Privatekey.
SignBytes: func(b []byte) ([]byte, error) {
resp, err := iamService.Projects.ServiceAccounts.SignBlob(
serviceAccountID,
&iam.SignBlobRequest{BytesToSign: base64.StdEncoding.EncodeToString(b)},
).Context(r.Context()).Do()
if err != nil {
return nil, err
}
return base64.StdEncoding.DecodeString(resp.Signature)
},
})
if err != nil {
log.Printf("sign: failed to sign, err = %v\n", err)
http.Error(w, "failed to sign by internal server error", http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprintln(w, url)
}
func main() {
cred, err := google.DefaultClient(context.Background(), iam.CloudPlatformScope)
if err != nil {
log.Fatal(err)
}
iamService, err = iam.New(cred)
if err != nil {
log.Fatal(err)
}
uploadableBucket = os.Getenv("UPLOADABLE_BUCKET")
serviceAccountName = os.Getenv("SERVICE_ACCOUNT")
serviceAccountID = fmt.Sprintf(
"projects/%s/serviceAccounts/%s",
os.Getenv("GOOGLE_CLOUD_PROJECT"),
serviceAccountName,
)
http.HandleFunc("/sign", signHandler)
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", os.Getenv("PORT")), nil))
}
二つ目の方法は、 Cloud Identity and Access Management が提供する Service Account API の中の一つである serviceAccounts.signBlob を用いる方法です。これを用いることによって、アプリケーションランタイムで秘密鍵を管理せずに署名をすることができます。本稿では、秘密鍵の管理を避けるために、この方法を採用しています。