2017年12月4日月曜日

【Googleクラウド・機械学習編】機能のご紹介

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

最近流行の機械学習について勉強中です。

今までは「人工知能調査」と銘打って記事のタイトルとしていましたが、調査対象をGoogleクラウドの機械学習APIに絞り込んだことから、記事のタイトルも合わせて絞り込んだものにしてみました。

では、早速機械学習APIの中に入っていきましょう。

何が出来るのか?

ご存じ無い方だと、「機械学習のAPI? 何のこっちゃ?」という印象かと思います。
以下の例を見ればすぐイメージが沸くでしょう。

CLOUD NATURAL LANGUAGE API


「非構造化テキストから分析情報を得る」とのこと。
「非構造化テキスト」とは、例えばこのブログの記事のようなフリー文章のことです。

フリー文章をこのAPIに食わせると、「機械学習」「人工知能」みたいな要点となる単語をピックアップしてきたり、そこに含まれている感情をピックアップしてきたりするものです。

例えば自社サービスのユーザからアンケートを収拾してきて、それを食わせると、


  • 「高い」
  • 「障害」
  • 「対応」
  • 「値段」


みたいな、特徴的な単語が抽出されてきます。
加えて、「怒り:20%」「不満:30%」「良好:50%」みたいな感情も数値化されて出てきます。

こういう情報を見て、

「ああ、利用者はウチのサービスに対して値段の高さ、障害発生率、ヘルプデスクの対応、この辺りを気にしているんだなぁ。値下げは出来ないけど、障害発生率、ヘルプデスクは気になる。これは新機能の追加より、現在のサービスの安定性向上にリソースを割いた方が良いってことなのかなぁ」

という判断材料に使えるわけですね。

このAPIは「ユーザからの声を数値化するサービス」と言えるでしょう。
上手く使えば経営者の目がキラキラするかもしれません。

補足ですが、「ビッグデータ解析と似たようなもんだな」という印象を抱く方もいると思います。
私は「似たような物ではなく、同じ物だ」と解釈しています。

機械学習とビッグデータ解析は技術領域が被っていますので、両者の境界線は曖昧です。

CLOUD SPEECH API



音声をテキスト変換するAPIです。日本語にも対応していることを確認済み。

最近のスマホは「近所の居酒屋まで道案内してや」と話し掛けるだけでGoogleマップが起動したりしますが、恐らくはこの技術を使っているものと推測されます。

私は業務系エンジニアであるため、このAPIの使い道は真っ先に以下を思いつきました。

  • 議事録のテキスト化

会議の内容を手持ちのスマホで録音して、戻ってからAPIに食わせてテキスト化出来るんじゃないか!?

これは期待大です。

CLOUD TRANSLATION API

言わずと知れたGoogle伝統の翻訳APIです。

最高に素晴らしい機能ではありますが、公式のGoogle翻訳以上のものを自分で作るのは難しいんじゃないかな?

自分のアプリの中にGoogle翻訳を組み込みたいようなケースがあれば、活躍するのかもしれません。

CLOUD VISION API


画像を解析するAPIです。
画像から様々な情報を抽出します。


  • ラベル検出
  • 不適切なコンテンツの検出
  • ロゴ検出
  • ランドマーク検出
  • 光学式文字認識(OCR)
  • 顔検出
  • 画像属性


「光学式文字認識(OCR)」とは、画像の中に書かれた文字をテキスト抽出することです。
名刺画像を食わせれば名前を抽出出来る、とかそういう機能ですね。

それ以外は何のこっちゃ???

これ、使ってみれば感覚が分かります。
以下、私の写真を食わせてみました。



JOY:■■■■■

とか出ていますね。

「これ、お前が遊びに出かけた時の写真だろ!!」と、断定してきているわけですね。
服装のポップな感じから見極めていると思われます。

人間の思考回路と同じ。
実に人工知能らしい機能じゃありませんか。

その他の機能

上記を見ると、「ああ、あのサービスのあの機能はコレだったんだ」と思う方も多いと思います。
何か、どこかで見たことがあるような機能です。

あの機能を自分で作るとなると途方も無い労力です。
しかしWebAPIを使えば簡単に実現出来ます。

それが機械学習APIなわけですね。

最後に、私が気になるAPIをご紹介。

CLOUD JOBS API





限定公開アルファ版。

「求職者がもっと簡単に職を探せるようにするという幅広い取り組みの一環」

とのことです。

要するに、「求職者のスキル」と「企業の求めている人材像」を分析してマッチングする機能ということでしょう。
リクルートとかが関心を寄せそうな話です。

これを弊社ジェニシスに置き換えた場合、弊社では「マッチング営業」という業務が存在します。
SEを派遣する時の仲介となる業務です。

この業務は「行う仕事と、派遣された人材のスキルが合わない」というスキルミスマッチが大問題に発展します。
もちろん、念入りに面談して技術力も見極めればそんなことは起きるはずは無いのですが、「忙しくて面談の時間が30分しか取れない」とか「技術力を見極める力量のある人が忙しいので動員出来ない」とか、大人の事情で万全な体制が取れないケースがあります。

しかし、機械学習を活用してSEの職務経歴書を読み込ませて判断材料にすることが出来れば、問題点のいくらかは補強されるんじゃないかと思います。

こんな風に「もしかしたらこんなことが出来るんじゃないかな?」と期待が膨らんでいく辺りが、機械学習の楽しいところですね。

終わりに

次回からは上記のAPIを実際に使っていきたいと思います。

2017年11月27日月曜日

【人工知能調査】機械学習のWebAPI

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

最近流行の機械学習について勉強中です。

前回の調査で、自分で機械学習アプリを作ってみたい場合はGoogleの機械学習ライブラリ「TensorFlow(テンソルフロー)」がオススメとなりました。




しかしながら、やっぱり結構難しいんですよね。。。
勉強期間を置かなければ厳しいです。

しかし、そこは天下のGoogle。そんな初心者でも機械学習が使えるようにWebAPIを用意してくれています。

ここから先は機械学習WebAPIについて調査してきます。

Google Cloud Platform


Googleが提供するWebAPI、それは「Google Cloud Platform」の中にあります。
通常、「Googleクラウド」。




AmazonのAWS、MicrosoftのAzureと並ぶクラウド三巨頭の一角です。

メニューの内容をいくつか見ていきましょう。


クラウド コンピューティング サービス


「Googleクラウド」という言葉は、暗黙的にこのクラウドコンピューティングサービスのイメージで使われている事が多いです。
アプリを載せるサーバをクラウド環境で提供するという、クラウド界の一般モデルですね。

以前、私はこの中の「GoogleAppEngine」を調査しました。
驚異的な速さと安さ、処理パワーを誇る一方、制約がキツい
通常の業務システムではこんなの使えませんが、特定局面ではブッチギリの最強を誇る。
キレ味の鋭いデンジャラスなサービスです。
当時の時期はこちらをご確認下さい。


ストレージとデータサービス、その他


Googleクラウド上で展開しているデータベースです。
普通のOracleとかMySQLとかと違い、クラウド上で効率的に処理をするためにチューニングが施されたDBが展開しています。

が、上記のサイトのデザインを見るとクラウドコンピューティングサービスは別の項目として置かれていますから、違うサービスであるかのように見えます。
課金体系も別れているので確かに違うサービスと言えばそうですが……。

私は「クラウドコンピューティングサービスの一部」としか思っていません。
だって、「言語は動かせるけどDBはありません」って、それじゃシステムが成り立たないじゃないですか。
この「クラウドDB」とは、要するに「GoogleAppEngineの接続先のDB」なんですよ。

DBだけ独立して使うものじゃない。

他の項目である「ネットワーキング」「ビッグデータ」「管理ツール」も同じ。
全部揃って「Googleクラウド」です。

  • Googleクラウドのうち、サーバ部分の詳細はコンピューティングを参照。
  • Googleクラウドのうち、DB部分はストレージの項目を参照。
  • Googleクラウドのうち、ネットワーク部分はネットワークの項目。
  • Googleクラウドでも、特にビッグデータ処理用の機能はビッグデータの項目を参照。
  • GoogleクラウドのAdminコンソールは管理ツール参照。


と、みんな繋がっているものです。

つまり、

  • 一つのサービスを実現する為に必要な技術領域毎にメニューを分けている。
  • 全部組み合わせて最終的に一つのWebサービスが出来上がる。


と考えるのが分かり易いです。

課金体系もサーバ処理、DB処理、ネットワークで個別に別れています。

  • 重い処理があるサービスはコンピュータ代が高くなる。
  • アクセスが殺到するサービスはネットワークが高くなる。
  • 月々の維持費は全部の合計。


こういう課金体系です。
こうして見ると「クラウドクラウドって言うけど、普通のサーバと似たようなもんじゃないか」というのは、その通りです。

クラウドはクラウドという新しい技術ではなく、昔ながらの技術の延長線上にある、ちょっと便利なテクニックのようなものなのです。

機械学習


さて、そんなGoogleクラウドの中にねじ込まれている項目があります。
以前は無かったのにいつのまにか増えました。


これが目当ての機械学習です。

例えば、Google検索でテキストボックスに文字を少し入力すると、その先が予測されて表示されるという機能は、この機械学習の機能を使った結果のはず。

我々が普段使っている機能の裏側がここに眠っているのでしょう。

終わりに


次回からは、この機械学習について、調査と検証に着手していきたいと思います。

2017年11月20日月曜日

【人工知能調査】機械学習を始めてみよう

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

最近流行の機械学習について勉強中です。

これまでの調査で「機械学習とはどういうものか?」というものを触り程度には理解出来たと思います。
しかし、「じゃあ早速業務で使いたいんだけど♪」となると、まだまだハードルが高そうです。

ここからは具体的にどう実現していけば良いか、について模索していきたいと思います。

二大プラン


機械学習は、元を辿るともの凄く高度な技術領域で、特別な研究者でなければ手も足も出ないようなものです。

しかしながら、最近機械学習がブームになっているのは、そういった偉大なる先人達が一般エンジニアでも使えるようにお膳立てを整えてくれたおかげで、以前よりもずっと身近なものになってきているからです。

機械学習を導入する手段としては、私は以下の2つに絞り込みたいと思います。

  • ライブラリ導入 
  • WebAPI 

まずはライブラリから調べてみます。

機械学習ライブラリ


機械学習を実現するライブラリを導入して実現するプランです。
「ライブラリ」とは、その名のとおり、普通にソースの集合体です。
オープンソースとして公開されているので誰でも取得可能。

自分でプロジェクトを作成し、公式サイトからダウンロードしたパッケージにパスを通し、起動。
後は自分で実装していく中でライブラリのメソッドを呼んだりするわけです。

つまり、普通のプラグラミングです。

昔ながらのイメージだと、こういうのは世界有数の先端企業の天才プログラマーが本人以外誰にも分からないような異次元開発を行っているような気がしますが、
実際はネットに転がっていて誰でも活用OKという状況です。

時代の潮流ですね。

注目のライブラリ:TensorFlow


では、世の中にはどのようなライブラリがあるか?

「機械学習 ライブラリ」で検索すると、結構沢山出てきます。
機械学習のライブラリは既に世界に溢れています。
とっくに群雄割拠の時代に突入していると言ってしまって良いでしょう。

その中で私がイチオシするのは、GoogleのTensorFlow(テンソルフロー)です。


機械学習のライブラリ開発は、古くは(と言うほど昔ではありませんが)「カルフォルニア大学バークレー校」「FaceBook」などが活躍してきました。

一方、技術領域の最高峰と目されていたGoogleはソースのオープン化を行っておらず、内部プロジェクトとして秘密裏に進行していました。
「Googleは一体どんなことをやっているんだろう???」とみんなが思っていた2015年、満を持して世界に公開された待望のライブラリ、それがこのTensorFlowです。

最大の特徴は、Googleが実際にこのライブラリを自社で使っているという「実績」でしょう。

Googleの迷惑メールフィルタリングとか、画像検索とか、表示される広告の選抜とか、Googleが実現している機能はこのライブラリを使っているわけです。

  • 現在、Googleがこういう機能を実現している。 
  • これを応用して、自分達の業務に活用したい。 

こういう発想で物事を考えていくことが出来るわけですね。

2017年の現時点において機械学習を始めたい人は、このTensorFlowを勉強するのが最善の道だと思います。

言語はPython


TensorFlowの言語はC言語、C++にも対応していますが、主力はPythonです。

Pythonは日本ではまだまだ普及しているとは言い難いですが、欧米ではかなり採用比率が高く、特に機械学習業界では「言語=Python」と言ってしまって良いくらい支配的な地位を占めています。

今一番ホットな言語だと思います。

機械学習界でPythonが人気を集めるのには理由がありますが、私は特に以下の点が重要だと思います。

インタプリタ言語である


インタプリタ言語とは、書いたソースを逐次解釈して実行するタイプの言語のことで、例えばPerl、Ruby、PHPがそれに該当します。

C言語みたいにコンパイルを経由しないので高い生産性を持つと評価されます。

ココ、「コンパイルせずに即実行」という特性がポイントです。

私のような業務系SEの場合、開発風景は基本的に「基本設計⇒詳細設計⇒実装」と進行します。
キチッと設計してから実装するので、実装は理論上は一撃必殺です。(実際はバグで手戻りしますが)
一撃必殺だからコンパイルも一回で終わりです。

対して、機械学習は「あーでもない」「こーでもない」と試行錯誤しながら開発が進行します。
試行錯誤の度に毎回コンパイルなんてやってられないのです。
だからインタプリタ言語が重宝されるわけです。

この発想は他の開発における言語選びでも一つの基準となりますね。

  • 詳細設計までビシッと書いて一発で実装を完了出来るなら、コンパイル言語 
  • 実装しながら考えるようなやり方なら、インタプリタ言語 

大規模ビジネスシステム開発のウォーターフォールモデルではJava等のコンパイル言語の採用が多く、
スパイラルモデルやアジャイル開発ではインタプリタ言語採用が多いのも、この辺りが背景にあるわけです。

人工知能業界は後者なのです。

速い


Pythonのもう一つの特徴。
それはインタプリタ言語にしては速いということです。

一般的にコンパイル言語の方が速く、インタプリタ言語の方が遅いです。
Pythonの場合も、流石にC言語よりは遅いのですが、インタプリタ言語の中では速い方だと言われています。
自分でベンチマークしたわけではありませんが、ザックリと

  • C言語:最速
  • Python:C言語の5~7倍の処理時間が必要 
  • Ruby:Pythonの 5~7倍の処理時間が必要

これくらいの違いが出ると思って良さそうです。
(C言語の速さはぶっちぎり)

なお、言語の処理速度とは難しいもので、処理内容によっても得意不得意があります。
例えば、「文字列の処理ならこっちの言語の方が速いが、計算処理ならそっちの言語の方が速い」なんてこともあるので、一口に速い遅いとは言えないのですが……。

ともかくPythonは大抵の場合は速いと言われており、特に機械学習がよく使う計算などの機能については定評があります。

普通に開発していると「言語なんてどれ使っても大して変わらんだろ」というのが正直なところですが、突き詰めていくと違いがあるんですね。

そんなこんなで、機械学習を習得する道筋は以下です。

  • Pythonを覚える。
  • TensorFlowを導入する。
  • そこからは普通に実装。

普通に開発です。
それなりに難しさはあるものの、手も足も出ないような特殊領域の世界ではありません。

続く


しかしながら、私はPythonが使えず、現在勉強中の段階です。

行く行くはTensorFlowを採用した自主開発が出来るようになりたいですが、まだ時間が必要です。
しかし、世の中には「HTTPリクエストを送るだけで結果を貰える」という機械学習のWebAPIサービスも普及しています。

取り急ぎ機能を使いたい人はWebAPIを利用することもオススメです。

Pythonの勉強は並行で進行しつつ、次回は機械学習WebAPIについて調査していきたいと思います。

2017年11月13日月曜日

【人工知能調査】機械学習とそうでないもの

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

前回にて、「人工知能とはつまるところ何か?」ということについて考察しました。
改めて纏めますと、私の考える人工知能とは以下です。

  • 人工知能とは、人間がロジックとして明示化出来ないマッチング条件を、機械に代行して作成して貰う為のツールである。

例えば、「犬と猫ってどう判別するの?」と写真を見せられた時、人間だったら、まあ大体分かりますよね。
顔つきとか、丸っこさとか……。

でもそれを「定義しろ」って言われても良く分からないし、ましてや「if文で書けるようにロジックとして定義しろ」なんて言われても無理無理。
こういう人間が感覚でやっていることは自分でも良く分からんのです。

こういう時に人工知能の出番というわけですね。

機械学習


さて、人間はどうやって「犬」と「猫」を見分けているのでしょう?
それはズバリ、経験です。

過去に犬と猫を何匹も見ているから、「犬っぽい顔をしているもの」「猫っぽい顔をしているもの」を見分けることが出来るわけです。

人工知能も同じ。

「コレは犬」「コレは猫」と決めて画像を大量投入すると、人工知能が経験を蓄積して「犬っぽいものは犬」「猫っぽいものは猫」というマッチングを行うようになるわけです。

この経験蓄積を「機械学習」「ディープラーニング」と言います。

「機械学習」と「ディープラーニング」の違いの定義は、ちょっと難しいです。

  • 機械学習を発展させたものがディープラーニング
  • 機械学習よりもオートマティックが進んだものがディープラーニング

という印象を受ける文献が多いですが、「ディープラーニングは機械学習の一部」と考えておくと良さそうです。
この連載では広義な「機械学習」で用語として統一させて頂きたいと思います。

機械学習の使いどころ


私の狙いとしては、「機械学習を業務やビジネスで生かすことが出来ないかな?」という所にあります。
そこで、もう少し「こういう時は機械学習の出番」「こういうのは機械学習不要」という判別について理解を深めていきたいと思います。

機械学習なもの:迷惑メールフィルタリング


人工知能への着目が世間に溢れてきたのは、将棋でAIがプロ棋士に勝ち始めた頃くらいではないでしょうか?
しかし実際のところ、私たちの身の回りにはもっとずっと前から機械学習の成果がありました。

例として、迷惑メールフィルタリングを挙げてみます。

迷惑メールフィルタリングの筆頭格は、やはりGMailでしょう。

そのメールが迷惑メールかどうかは、人間なら目視で判断出来ます。
大体、以下のような特徴があるイメージですね。

  • 内容が18禁である。
  • 金儲けの話が入っている。
  • 得体の知れないサイトへ誘導されている。

大体こういうイメージですが、特に「これ!!」って断定する条件は無いですよね。
こういう時こそ、機械学習の出番です。

昔は上司のメールが迷惑メールフィルタリング行きってことが頻発していましたが、最近は昔よりもそういうケースが減ってきたように思います。

長年の蓄積により、GMailの迷惑メールフィルタリングがどんどん成長しているのですね。
成長こそが機械学習の特徴です。

機械学習ではないもの:ウイルスメールフィルタリング


同じメールフィルタリングでも「ウイルスメールフィルタリング」は機械学習ではありません。

私はウイルスバスターを使っていますが、あれはトレンドマイクロ社員が「パターン定義ファイル」というものを毎日ガリガリ作っているんです。

「ウイルスと判定するための条件」がキチッと決まっています。
こういうものは機械学習ではありません。

  • 迷惑メールフィルタリングは、機械学習の成果である。
  • ウイルスメールフィルタリングは、機械学習ではない。

同じメールフィルタリングでも裏側の機能は別物です。
両者を「似たようなもの」と考えてしまう人がいるとしたら、言語道断です。


このように、


  • 人工知能と機械学習を投入するべきところ
  • 昔ながらの人間による定義で処理するべきところ


これらの違いが分からなければダメということですね。

「これからは人工知能の時代だ」という話は良く聞きますが、世の中の全てが人工知能に置き換え可能なわけではありません。
「どの辺りが人工知能の使い所なのか?」ということを理解した上で検討していきたいものです。

終わりに


こういう記事を書いていると、「そう言えば、アレって機械学習使えないのかな?」とか思う時があります。

例えばですね、最近「メルカリ」というフリマアプリが人気ですよね。
あれは不正出品が多発して治安が問題になっているとニュースになっています。

メルカリ社員が24時間体制で不正出品を監視しているそうですが、「機械学習で不正出品の自動検知したり出来ないのかな?」と思うところです。
迷惑メールフィルタリングが出来るのだから、不正出品フィルタリングも出来ると思うのです。

実際に機能を実現するとなったら大変でしょうし、もしかしたら既にメルカリ内部では動き出しているのかもしれません。

でも、こう考えるだけでも、色々と可能性がありそうな技術ですよね。

さて、機械学習についてイメージが沸いてきたところで、そろそろ「具体的にどう実現したら良いの?」という所に迫っていきたいと思います。

2017年11月4日土曜日

【人工知能調査】始めに

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

業務多忙によりしばらく連載を停止していましたが、そろそろ復活していきたいと思います。
時間も経ってしまっているので、新しいテーマで仕切り直しです。

テーマは人工知能(AI)


最近、人工知能がブームでよく話題を耳にしますよね。
人工知能という概念自体は私が生まれる前からありました。
それが最近ブームになりつつあるのは、もちろん鉄腕アトムのレベルには達しないものの、ある程度の成果、使い道が生じる程度にまで実現性が生まれてきたからでしょう。

その為か、私は人工知能という言葉はバズワード化してきていると思っています。

人工知能とそうでないもの


そもそも「人工知能」という言葉自体、特に明確な線引きがあるわけでは無いのでバズワード化するのも無理は無いと思いますが、
それでも世の中の人は「人工知能」と「そうでないもの」を分けて表現していると思います。

だって、
  • 人が近付くと自動ドアが開く。⇒人工知能ではない。
  • 写真に写っている人の顔を自動認証する。⇒人工知能だ!!
みたいな感覚、あると思います。
どっちも自動認証していることには変わらんと思うのですが、不思議ですよね。

他には、
  • 格闘ゲームでコンピュータが対戦相手を務める。⇒人工知能ではない。
  • コンピュータがプロ棋士に将棋で勝った!!⇒人工知能の時代だ!!
とか。

恐らく「何か知らんが凄いもの」と「そうでないもの」くらいの感覚かと……。

しかし、私はこの「何か知らんが」の部分に鍵があると思います。

人工知能とは


昔を思い出すと、私が最初に「人工知能って凄い!!」と思ったのは子供の頃、ドラゴンクエスト4でした。
ドラクエは3以前はプレイヤーがコマンド入力で戦っていましたが、4以降はコンピュータが自動戦闘してくれるのです。
しかもドラクエ4の場合、戦闘を重ねる毎に学習して頭が良くなっていくという機能まで付いていました。
これを「人工知能」と称して大々的に宣伝を打っていました。

後に知ったのですが、ドラクエ4のアレは、実は人工知能でも何でも無いんですよ。

「戦闘するとランダムでフラグが解禁される。だから何度も戦っているとフラグが全て解禁されて頭が良くなったように見える」

これだけ。単なるフラグ処理です。
ファミコンなんだからその程度が関の山なのは当然ですが、当時子供だった私は本気で人工知能と信じ込んでいました。

しかし、ここに一つの真理があります。

  • 中身がどうだろうと、人工知能っぽい挙動であれば、人はそれを人工知能と思う。

それが人工知能かどうかなんて、外から見ても分かりゃしない。

その人がそう思うかどうかの世界です。

では、何をもって人はそれを「人工知能っぽい」と思うか?
私の考えはコレです。

  • 学習機能を有している。

これが核心だと思います。

自動学習機能


この視点で冒頭に戻ってみましょう。

自動ドア、格闘ゲーム
これらは人が近付くと自動でドアが開いたり、パンチを打つと防御してきたりするわけですが、それは事前に開発者がプログラミングしたものです。
なので、能力はずっと固定。自動で能力が上がったりすることはありません。
「この自動ドア、昔は開かなかったけど、最近調子良くなったね」なんてことは起きません。

 ⇒人工知能ではない。

顔自動認証、将棋
将棋の方が分かり易いと思いますが、これらはサンプルとなる膨大な過去データを内部に持っていて、その膨大な過去データをサーチして経験則的に挙動を決めてきます。
だから内部データが増えるほど頭が良くなるという学習機能を有している、と言えます。

 ⇒人工知能である。


そうして学習機能して得た成果は「マッチング条件」の精度に反映されてきます。

  • 開発者が自分でマッチング条件をプログラミングしているものは、人工知能ではない。
  • 機械がマッチング条件を自動生成しているものは、人工知能である。

こう定義すると、人工知能というあやふやな言葉も、ビジネスの世界で要望されているものの本質に近付いてくるのではないでしょうか?

終わりに


そう考えると、人工知能の意義というものが見えてきましたね。
人工知能とは、結局はツールの一種、手段の一種でしか無くて、
開発者が人工知能に望んでいるのは、要するにこういうこと。


人間が自力でプログラミングし切れないマッチング条件を、コンピュータが代行して自動生成して欲しい!!


人工知能が「何か知らんが凄いもの」と見える理由はココ、人間でもよく分からんロジックを委託しているからなんですね。

そして、最終目的である「自動生成」に到達する為の過程として存在するものが「学習機能」なわけです。

となると、

どうやってコンピュータに学習機能を持たせるか?

ということが重要になってきます。
そういった時に登場するのが、こちらも最近話題の「機械学習(machine learning)」です。

「人工知能」と「機械学習」の関連性が見えてきたところで、次回に続きます。

2016年9月27日火曜日

【JavaでPlayFramwork2.4.6】routesファイル

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

ただ今、もうすぐ始まるプロジェクトの実装で使用するPlayFrameworkについて事前勉強を進めています。


今回はURLを制御するroutesファイルについてご紹介します。

伝説のXML地獄


JavaWebシステム業界では長年の間、Struts1が支配的な地位を占めてきました。
そこで常に大問題を起こしてきたのが「struts-config.xml」「web.xml」という巨大XMLです。

コイツラはWebシステムが受け付けるURLを制御したり、そのリクエストを行った際に取得するパラメータを格納するFormや、遷移先のjspなど、WebシステムのWeb部分を管轄する設定ファイル達です。

欠点は、もの凄く煩雑なんですよね!!

基本的にココで躓くのは新人レベルの人なのですが、XMLなんでちょっと壊れただけでも動かなくなりますし、設定が間違っていても動かないし、ログを追うのも難しいし、と不慣れな若手プログラマーの未来の芽を摘むのに多大な役割を果してきました。

更にORMappingにSpringとHibernateを導入すれば完璧。

今やJavaWebシステム業界の金字塔とも言える究極のXML地獄が完成します。

これね、慣れれば分かるんですよ。でも不慣れだと全然分からない。
だから自分が数年の月日を経て手慣れてきても、その頃には会社には後輩が入ってきているわけで、「何か動かないんですけど~」と単体環境で起動も出来ないような始末になっていることは日常茶飯事。

あのXML地獄は最悪だとみんな身に染みて分かっているんですね。
そうして出てきた概念が、あの有名なRubyOnRailsのキャッチフレーズ、

「設定より規約」

です。

一言で言いますと、「ファイル名、クラス名を合わせておけばXMLは省略出来るよ」というものです。

RubyOnRailsの命脈を引き継ぐPlayFramworkもこの思想がありまして、膨大な設定ファイルを多数記述しなくても、ある程度の命名規約に則してソースを作っておくだけでとりあえず動いてくれる。

もう「設定より規約」はRubyOnRailsがどうこうと言うより、Webシステム業界の基本概念と言って良いくらいになってきましたね。

今回はPlayFramworkでURL制御をする為のやり方を検証してみたいと思います。

コントローラ


まず最初にリクエストを叩いた直後に呼び出されるクラス「コントローラ」を作成します。

public class LoginController extends Controller {
 /**
  * @return Result
  */
 public Result index() {

  Form userForm = Form.form(LoginForm.class);

  return ok(views.html.layout.login.render(userForm));
 }

}


命名規約と言っておいてなんですが、実際には「Controllerクラスを継承する」という点だけ守っておけばOKです。

しかし、ここで特徴が一つ。
コントローラを格納するcontrollersパッケージはルート直下に置くのがオススメです。


普通はJavaのパッケージって言うと組織を表現する長~いフルパスを指定するものじゃないですか?
弊社ジェニシスで言えば「jp.co.net.genesis.controllers」というパッケージにするのがJava業界のお約束ですが、PlayFrameworkはいきなり「controllers」だけにするのが普通です。

理由は後述します。

routesファイル


クラスを作ったところで、次にURLの定義に移ります。

上記「LoginController」のメソッド「index」とURLリクエストを結びつけるには、confフォルダ配下のroutesファイルに以下のように記述すればOKです。


GET     /                           controllers.LoginController.index()
GET     /login/                           controllers.LoginController.index()


見た目そのままかと。簡単ですね。

RubyOnRailsと違い「LoginというURLを打ち込めば自動的にLoginクラス」という挙動はありません。
「設定より規約」の思想を受け継ぎつつも、この辺りは「規約より設定の方が便利」という崩しが入っているんですね。

ほら、上記の例だと「URLに何も入力しなかったら自動的にログインを表示」という挙動も簡単に表現できます。
このくらいが自動化するのに丁度良い塩梅だと考えたのでしょう。

また、従来のStruts1のAction方式が「1URL1アクションクラス」だったのに対し、PlayFrameworkのコントローラはメソッド分けにも対応しています。
なのでクラス数が膨大に増えていってしまう問題が解消されている一方、URL設計をちゃんとやらないと1クラスにメソッドが大量終結してしまう欠点があります。
この辺りは設計者の腕の見せ所ですね。

しかし、ここで注意事項。

  • controllers.LoginController.index()

「controllers」という文字がありますね。そう、このroutesファイルの記述はフルパスなんですよ。
これが上記でルート直下をオススメした理由です。

もし「jp.co.net.genesis.controllers」と書いてしまうと、記述がこうなります。

  • jp.co.net.genesis.controllers.LoginController.index()

長いんですよ。
もちろん1システムにURL数は数十~数百まで沢山ありますから、もし会社名まで含めたパッケージにしてしまうと、routesファイルは以下のようになってしまいます。


  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()

これは冗長でしょう!!

気にしなければ良いと言えばそれだけなのですが、PlayFrameworkは軽快にアプリケーションを作っていくという思想がありますから、「フルパスがどれだけ長かろうがコピペするだけなんだから作業効率は変わらん」ということは分かりつつも、
出来るだけ記述する文字数を減らすのがPlayFramework。

伝統的なJavaエンジニアにはちょっと気持ち悪いですが、ここはルートフォルダ直下にcontrollersパッケージを置くのがPlayFrameworkの標準かな、という所感です。

終わりに


これでURL制御は終わりです。
PlayFrameworkの簡単さがよく分かる一例だったと思います。

引き続きPlayFrameworkの検証を進めます。

2016年9月20日火曜日

【JavaでPlayFramwork2.4.6】ログ出力とフィルター

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

業務多忙により更新が停滞していましたが、再びPlayFrameworkの連載を復活します。

ログ出力

システムを構築する時に最初にどこから作っていくか、というところは個人の趣味があるところかと思いますが、私の場合はまずログ出力から固めていきます。
今回はログ出力についてご紹介します。

出力本体

PlayFrameworkのログ出力と銘打ってこんな記事を書いていますが、PlayFrameworkはJavaを内包していますから、早い話が単なるLog4jなんですよね。


PlayFrameworkの中には最初からLog4jが入っていますので、素直にコレを使えば良いかと。
log4jの標準に従ってlogback.xmlを設置すればその通りに動いてくれるようになります。

この辺りはPlayFrameworkの話ではなくlog4jそのままの話ですので、この記事でわざわざ記述するほどの話ではないかと。

今回はここから一歩踏み込みまして「リクエストの開始と終了のログ」を出力する方法に行ってみたいと思います。

ロギングフィルター


純粋なJavaのフレームワークであれば、リクエストの開始と終了は「doGet」とか「doPost」のメソッドの最初と終了にログを出力するようAbstractの親クラスを作るだけの話ですが、PlayFrameworkはそういう風に出来ていませんのでちょっとしたコツが必要になります。

そのテクニックを「フィルター」と言います。


フィルターとは、前回でご紹介したGrobal.javaに適応するものでして、
全てのリクエストの開始時に呼び出される共通処理を提供する機能です。

使い方はGrobal.javaのメソッド「filters()」にフィルタークラスをセットするだけでOKです。

 /**
  * Get the filters that should be used to handle each request.
  */
 @Override
 public  Class[] filters() {

  Class[] clazz = new Class[1];
  clazz[0] = RequestLogFilter.class;

  return clazz;
 }

これで全てのリクエストの開始時に「RequestLogFilter」が呼び出されますので、そこにログ出力の処理を書けば良いわけですね。
ただし、Filterはscalaで書かなければなりません。

PlayFrameworkでJavaを選択したプロジェクトであってもFilterクラスはscalaのみなのでご注意を。

しかしですので、Filterというのは開始時に呼び出されるものであって、終了時には呼び出されません。
よって「リクエストの終了ログはどうやって出すの?」という問題が発生します。

これにつきましてもPlayFrameworkとscalaならではの機能で実現してくれます。

traitとインターセプター


以下が私が使用しているログフィルターです。

class RequestLogFilter extends EssentialFilter {

  def apply(nextFilter: EssentialAction) = new EssentialAction {

    def apply(requestHeader: RequestHeader) = {

      def isTarget = RequestLogFilterUtils.isLonningTarget(requestHeader.uri);

      val startTime = System.currentTimeMillis

      if (isTarget) {
        Logger.info(RequestLogFilterUtils.getStartLog(requestHeader.method, requestHeader.uri))
      }

      nextFilter(requestHeader).map { result =>

        val requestTime = System.currentTimeMillis - startTime

        if (isTarget) {
          Logger.info(RequestLogFilterUtils.getEndLog(requestHeader.method, requestHeader.uri, result.header.status, requestTime))
        }

        result.withHeaders("Request-Time" -> requestTime.toString)

      }

    }

  }

}


RequestLogFilterUtilsというのは、私はscalaが不見識ですので文字列加工機能部分だけJavaに切り出しているだけなので気にする必要はありません。
今回のポイントはこちら。

nextFilter(requestHeader).map { result =>


nextFilterです。

resultという単語が出ていることから察せられるとおり、この中身がリクエストの終了時に呼び出されることになります。

?????

Javaエンジニアには意味不明な機構ですね。

これはscalaが搭載している「trait」という機能でして、Javaで言うところのインターフェースに近い性質を持つものです。
ただし、インターフェースほどカッチリとはしておらず、より柔軟性を持たせたものである模様。

ともかく、流れたとしては、

  1. リクエストが来る。
  2. リクエストをフィルターでインターセプト(傍受)する。
  3. リクエストにフィルターで定義した機能を挟み込む。

こういうちょっとメタっぽい形でリクエストにフィルター機能を持たせます。

そして開始ログを提供するメイン部分は普通にそのまま実行。
終了ログ部分は「trait」を使って定義しておいて、リクエスト終了時に後から呼び出す(chainするように)ようにフィルターの親クラスである「EssentialFilter」が作られている、とこういう構図なようです。

むむ。
これはPlayFrameworkの中でもかなりscala寄りの部分なようですね。
本格的に理解を深めるにはscalaの勉強を深めなければならなさそうですが、この連載は「JavaでPlayFramwork」なので掘り下げはこの辺り留めたいと思います。

終わりに


引き続きPlayFrameworkの勉強を進めます。