2018年1月22日月曜日

【Googleクラウド・機械学習編】Python3でJSONパラメータをpost送信する2

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

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

今回は前回の後編として、Googleクラウドの「CLOUD NATURAL LANGUAGE API」にPythonでリクエストを送りたいと思います。

ソース


結論から行きますと、このソースでリクエスト送信に成功しました。
import urllib.request
import urllib.parse
import json

#送信先URL
url="https://language.googleapis.com/v1/documents:analyzeEntities?key={My_API_KEY}"

#送信するJSONパラメータ
body = {
  'document': {
    'type': 'PLAIN_TEXT',
    'content': '株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。\n\n仕事はシステムエンジニア。\n特技は空手道初段です。\n\n家族は妻が一名ほどいます。\n\n好きなお酒はウイスキーです。\n\n仲良くして下さい。'
  },
  'encodingType': 'UTF8'
}
#JSONパラメータをバイト変換
body = json.dumps(body).encode("utf-8")

#リクエストヘッダー
header = {
    "content-type": "application/json"
}

try:
    #送信実行
    request = urllib.request.Request(url, data=body,  headers=header)
    with urllib.request.urlopen(request) as response:
        #結果を出力
        response_body = response.read().decode("utf-8")
        print(response_body)

except urllib.error.HTTPError as e:
    #エラーだった場合、エラー原因を出力
     print('ERROR!!')
     print(e.code)
     print(e.read())


解説


これが私の初めてのPythonでしたが、ふむ、確かに最近注目を集めるだけのパワーがあるものだと思います。

イチオシの点を上げていきます。

リクエスト送信の簡単さ


この処理の中でリクエスト送信を行っている箇所はここです。

    #送信実行
    request = urllib.request.Request(url, data=body,  headers=header)


headerやbodyの加工という前処理は別ですが、送信実行するだけなら僅か1行。

これをJavaで表現すると、大体こんな感じ。
   URL url = new URL(urlstr);

   HttpURLConnection connection = null;
   DataOutputStream dos = null;

   try {
    connection = (HttpURLConnection) url.openConnection();
    connection.setRequestMethod("POST");
    connection.setDoInput(true);
    connection.setDoOutput(true);

    dos = new DataOutputStream(connection.getOutputStream());

    Map postParamMap = getPostParamMap();

    StringBuilder buls = new StringBuilder();
    if (postParamMap != null) {
     for (String key : postParamMap.keySet()) {
      buls.append(key);
      buls.append("=");
      buls.append(postParamMap.get(key));
      buls.append("&");
     }
    }
    dos.writeBytes(buls.substring(0, buls.length() - 1));

    StringBuilder bul = new StringBuilder();
    try (InputStreamReader isr = new InputStreamReader(
      connection.getInputStream(), StandardCharsets.UTF_8);
      BufferedReader reader = new BufferedReader(isr)) {

     String line;
     while ((line = reader.readLine()) != null) {
      bul.append(line);
      bul.append(System.lineSeparator());
     }

     return bul.toString();

    }

   } finally {

    if (dos != null) {
     dos.close();
    }

    if (connection != null) {
     connection.disconnect();
    }

}

DataOutputStreamとかBufferedReaderとかConnectionとか、最後にclose?
ハッキリ言って「知らんわ!!」としか言いようが無い宣言の嵐。

比べて「request = urllib.request.Request(url, data=body, headers=header)」で済むこのPythonの簡潔さは特筆するべきものと言えるでしょう。

私はWebAPIこそがWebシステムの理想形だと考えています。

インターネット=パソコンだった昔と違い、今ではスマホやタブレットなど様々な端末から参照出来ることが求められている時代ですからね。

MVCモデル(モデル、ビュー、コントローラ)のうち、モデルとコントローラを完全に切り離してWebAPIに設置し、ビュー側は、「パソコン用」「スマホ用」「タブレット用」など、個別に開発する。

これが今の時代に求められるマルチ端末対応の最適解です。

つまり、WebAPIへのリクエスト送信に強い言語は、即ち時代の覇者であるのです。
Pythonはその点を良く分かっている言語と言えるでしょう。

JSON定義


Pythonが便利な点はまだあります。

body = {
  'document': {
    'type': 'PLAIN_TEXT',
    'content': '株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。\n\n仕事はシステムエンジニア。\n特技は空手道初段です。\n\n家族は妻が一名ほどいます。\n\n好きなお酒はウイスキーです。\n\n仲良くして下さい。'
  },
  'encodingType': 'UTF8'
}

JSONが直接定義出来る。

良いですか?
「JSON形式の文字列を読み込む」じゃないです。
JSONそのものを定義しているのです。

「JSON形式の文字列を読み込む」だったらこう書くことになります。

body = "{
  \'document\': {
    \'type\': \'PLAIN_TEXT\',
    \'content\': \'株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。\n\n仕事はシステムエンジニア。\n特技は空手道初段です。\n\n家族は妻が一名ほどいます。\n\n好きなお酒はウイスキーです。\n\n仲良くして下さい。\'
  },
  \'encodingType\': \'UTF8\'
}"

「エスケープ文字「\」が邪魔くせえ」という地味だけど面倒な問題点がPytonでは解消されているのです。

可読性が大変高くなっています。
データ定義にJSONを使うのは今や常識。

Pythonは良く分かっていますね。

JSONバイト変換


実装中にハマってしまったのがココです。
#JSONパラメータをバイト変換
body = json.dumps(body).encode("utf-8")

HTTPリクエストを送り込む前に、JSONをバイト変換しなければならない。
当然と言えば当然なのですが、ネット上に情報が錯綜していましてね、エラーの原因が分からず非常に苦労しました。

エラーハンドリングの奮闘記を記載させて頂きましょう。

まず、バイト変換しない場合です。
上記の「json.dumps(body).encode("utf-8")」を消すと、以下のようになエラーが出てしまいます。

Traceback (most recent call last):
  File "C:/Users/endo/PycharmProjects/Test/postjson.py", line 30, in 
    with urllib.request.urlopen(request) as response:
  File "C:\Python\Python36-32\Lib\urllib\request.py", line 223, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Python\Python36-32\Lib\urllib\request.py", line 526, in open
    response = self._open(req, data)
  File "C:\Python\Python36-32\Lib\urllib\request.py", line 544, in _open
    '_open', req)
  File "C:\Python\Python36-32\Lib\urllib\request.py", line 504, in _call_chain
    result = func(*args)
  File "C:\Python\Python36-32\Lib\urllib\request.py", line 1361, in https_open
    context=self._context, check_hostname=self._check_hostname)
  File "C:\Python\Python36-32\Lib\urllib\request.py", line 1318, in do_open
    encode_chunked=req.has_header('Transfer-encoding'))
  File "C:\Python\Python36-32\Lib\http\client.py", line 1239, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "C:\Python\Python36-32\Lib\http\client.py", line 1285, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "C:\Python\Python36-32\Lib\http\client.py", line 1234, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "C:\Python\Python36-32\Lib\http\client.py", line 1064, in _send_output
    + b'\r\n'
TypeError: can't concat str to bytes



  • can't concat str to bytes


「文字列をバイトに変換してからじゃないとHTTP送信出来ねえよ」というエラーログが出ます。
当たり前ですね。

次の罠がこちら。

#JSONパラメータの間違った変換
body = urllib.parse.urlencode(body).encode(encoding='utf-8')

これ。

  • urllib.parse.urlencode(body).encode(encoding='utf-8')

「urllib.parse.urlencode(body).encode(encoding='utf-8')」はNGです。

「urllib.parse.urlencode(body).encode(encoding='utf-8')」は、どうやらJSONをJSONではなく「普通の文字列」としてエンコードしてしまうみたいなんですよ。

urllib.parse.urlencode(body).encode(encoding='utf-8')した瞬間に、JSONはJSONではなく、単なる変な文字列になってしまう。

なのでWebサーバ側のバリデーションチェックでエラーになってしまう。

ERROR!!
400
b'{\n  "error": {\n    "code": 400,\n    "message": "Invalid JSON payload received. Unexpected token.\\ndocument=%7B%27type%\\n^",\n    "status": "INVALID_ARGUMENT"\n  }\n}\n'


だから、JSONのエンコードはこっち。


  • json.dumps(body).encode("utf-8")


JSONではない汎用エンコードはこっち。

  • urllib.parse.urlencode(body).encode(encoding='utf-8')

私が調べた限り、現在のネット情報だと「JSONのPOST送信とそれ以外のPOST送信は違いますよ」ってことがハッキリ書いている所が見つからなかったです。
理解した今となっては分かりますが、最初は両者の違いが分かりませんでした。

だから後者の汎用エンコードのサイトを見ていると「あれ? ちゃんとエンコードしているのにエラーになる。変だなぁ?」とハマッてしまう。
これは要注意です。

Pytonでは、JSONのPOST送信とそれ以外のPOST送信ではエンコードのやり方が違います。

要注意です。

終わりに


ともかく、これでWebAPIの一番の難関である「疎通確認」は成功しました。

ここから先は色々なデータを流し込んで「CLOUD NATURAL LANGUAGE API」の能力を見てみたいと思います。

2018年1月9日火曜日

【Googleクラウド・機械学習編】Python3でJSONパラメータをpostする

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

2018年になりました。本年も宜しくお願いします。 

さて、2017年から引き続き、最近流行の機械学習について勉強中です。

 リクエスト送信プログラム作成


さて、現在はGoogleクラウドの「CLOUD NATURAL LANGUAGE API」を検証中なわけですが、
その為には「リクエスト送信プログラム」を作らなければなりません。

ちょっと実行するだけならネット上に転がっているリクエスト送信支援ツールを使えば良いですが、
手元の大量データを送り込んだりとか、独自のカスタマイズを施す為には自前開発が必要不可欠です。

私はJavaエンジニアですので、プログラムもJavaで作るのが一番簡単な道です。
アンドロイドアプリでWebAPIのリクエストプログラムとか作ったこともありますし。
しかし、新年も始まったことですし、ここは志を高く持ってPythonで作ることにチャレンジしていきたいと思います。

 作成プログラム


目標


CLOUD NATURAL LANGUAGE APIに対する最も基本的な疎通確認レベルのPOST送信。

条件


言語はPythonとする。バージョンは3。

結論を言いますと、もの凄く苦労しました。
この記事はJavaだったら30分で作れたはずのプログラムを6時間も悪戦苦闘した奮闘記となります。

Python開発の困難点


1.Python2の情報が混ざっている


前の記事で書きましたが、Pythonは「Python2」と「Python3」で互換性がありません。

JavaだったらJava1.5で書いたソースは概ねJava8でも動作します。
(完全互換ではないのはミソ。以前に予約後の問題でJavaのバージョンを上げたら動かなくなったことがありました。とはいえ、殆どOKなので苦労はしません)

Pythonの場合は全然ダメです。
「バージョン間で互換性」は、まあハッキリ言って程度問題でして、「完全互換を保証するものではないが、大体は流用OK」くらいの言語が多いです。

でも、Python2とPython3は雰囲気が似ているだけの別物というくらい全然動きません。
そして、伝統的にはPython2が長く使われており、Python3は最新鋭です。

よって、「Python post送信」とかで検索すると、Python2とPython3の情報が混ざって出てくるんです。
私が必要としているのはPython3ですから、Python2の情報は罠でしか無い。
これが厄介です。

ちなみに調べている中で偶然知ったのですが、「Perlは互換性に強い」そうですね。

Perl...
相当古くから根付いている言語ですが、Perlは互換性が強い故に、何十年も前からサーバを引っ越ししつつ代々引き継がれているようなソースでも問題無く動くそうな。

「何十年も維持するプログラムだったらPerlが良い」

という記事を見ました。

なるほど。
こういうブログをやっていると最新情報ばかりに目が行ってしまいますが、業務系システムでは恒久的保守をどう行っていくかも重要な能力です。

「古い技術であっても侮ってはならない」という教訓になりました。

2.情報が少ない


やっぱりですね、少ないですよ、情報が。
無くは無いですが。

まず日本語の情報だけでは全然足りないので、英語情報に手を伸ばすことは当然
しかし、英語情報も踏まえても、イマイチ必要な情報が見つからない。

JavaとかPHPとか、長年の蓄積がある言語と比べると、ネット上における情報量の差というものを肌で感じます。
これは大きなリスクです。

仮に会社の案件としてPythonを採用したとすると、体制を構築するのは至難でしょう。

JavaとかPHPだともうネット上に情報が溢れているので誰でも何とかなるのですが、Pythonはそうは行きません。
強力な少数精鋭の体制以外では対応出来ないと思います。

これをチャンスと見るか、リスクと見るかは見解が分かれる所だと思います。

3.デタラメ


これが一番厄介!!

ネットに嘘が書いてある!!

嘘ではないにしても説明不足だったりとか、肝心な情報が抜けている記事が多い。
(もしくは、昔はそのソースで動いたのかもしれませんが、今では動かないとか)

情報源の少なさ故に淘汰されていないからなのでしょう。
ネットの技術情報は量が質を生むものです。
大量の情報が溢れかえって切磋琢磨し淘汰された結果、役に立つ情報が検索結果の上の方に来るのがネット界。

現在のPythonはまだ発展途上で、その段階に到っていません。
ノイズでしかない情報が溢れている。
これも大きなリスクです。

成果物ソース


そんなこんなで苦労しましたが、ひとまずリクエストの正常送信までは確認出来ております。

import urllib.request
import urllib.parse
import json

#送信先URL
url="https://language.googleapis.com/v1/documents:analyzeEntities?key={My_API_KEY}"

#送信するJSONパラメータ
body = {
  'document': {
    'type': 'PLAIN_TEXT',
    'content': '株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。\n\n仕事はシステムエンジニア。\n特技は空手道初段です。\n\n家族は妻が一名ほどいます。\n\n好きなお酒はウイスキーです。\n\n仲良くして下さい。'
  },
  'encodingType': 'UTF8'
}
#JSONパラメータをバイト変換
body = json.dumps(body).encode("utf-8")

#リクエストヘッダー
header = {
    "content-type": "application/json"
}

try:
    #送信実行
    request = urllib.request.Request(url, data=body,  headers=header)
    with urllib.request.urlopen(request) as response:
        #結果を出力
        response_body = response.read().decode("utf-8")
        print(response_body)

except urllib.error.HTTPError as e:
    #エラーだった場合、エラー原因を出力
     print('ERROR!!')
     print(e.code)
     print(e.read())


どうです?
私はこれを見ると「あっ、綺麗だな💛」と思います。

Javaだったらもっとゴチャゴチャですもん。
InputStreamだとか、OutputStreamだとか、close処理とか……。

比べて、要は


  • urllib.request.Request.urlopen(url, data=body,  headers=header)


で完結するPythonは如何に綺麗か。

確かによく洗練された言語だと思います。

私はまだ使い始めたばかりですが、慣れれば確かに他の言語より使い勝手が良いんじゃないかな、という感触は感じられましたね。

まとめますと、


  • 言語そのものが持つパフォーマンスは優れている。
  • 枯れておらず、情報がまだ少ないのがリスク。


というのが私の所感です。

なので、


  • プロジェクトのメイン言語として採用するのはハイリスク過ぎる。
  • 社内用のちょっとしたツール開発用なら、生産性も高くノウハウ蓄積にも適している。


こういう使い方でスキルアップしていきたいなぁ、と思うところです。

次回


次回は上記ソースの解説と、作成過程で蹴躓いた箇所の説明、デバック解説です。

同じ原因でハマっている人が検索から飛んできてくれたら嬉しいですね。

2017年12月25日月曜日

【AndroidStudio】日本語化再び【完全版】

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

今回は臨時投稿。
以前に連載していたAndroidStudioについて更新が発生したのでご連絡です。

【AndroidStudio】インストール&日本語化


2015年の記事「AndroidStudio】インストール&日本語化」で、
AndroidStudioの日本語化について試行錯誤しましたが、
結論はと言うとダメでした。

AndroidStudioの日本語化は不完全。。。
下手に日本語化するより英語でやった方がマシ。。。

と思っていましたが、いつの間にか日本語対応が完成していました。

日本の誇る日本語化アプリ「Pleiades」が対応して下さったようです。
対応時期はどうやら2017年6月末だったの模様。

かなりの大幅アップデートだったようで、私が知っていたPleadesから相当な進化を遂げております。

日本語化手順は公式サイトを見れば分かるかと思いますが、一応、当ブログでもご紹介させて頂きたいと思います。

【AndroidStudio】日本語化手順


1.AndroidStudioのインストール


事前のAndroidStudioのインストールは省略します。
普通にインストールして下さい。

2.Pleadesの取得


Pleadesの公式サイトよりプラグインをダウンロードします。


ここで注意ですが、ダウンロードするのは上にある「Pleiades All in One」ではなく、下にあるプラグインの方です。

ここがPleiadesの凄い所なのですが、Pleiadesは元々はEclipse用に作られた日本語化ツールですが、AndroidStudioなどのIntelliJ系にも適応出来るのです。

「AOP (横断的関心事を解決するテクノロジー)」 と言うそうです。
「Java クラスローダーをフックし、クラスをバイトコードレベルで動的に書き換え……」とのことですが、完全に黒魔術
私は性能測定ツールやモックツール等でメタ領域に突っ込んだ製品を見たことがあるので概念はある程度理解する所ですが、実装イメージが沸くほどには到底及びません。
特殊技術の領域です。

とは言え、使うだけなら単なるツールなので簡単です。

早速プラグインをダウンロードしてみましょう。



3.解凍


ダウンロードしたプラグインを解凍します。


昔は「features」と「plugins」しか無かったのですが、色々と増えました。
これは革命的なことです。
Eclipseのプラグインなんてどれもこれも「features」と「plugins」だけがチョロっと入っているだけのチープなものばかりなんです。
それ以外が含まれた豪華なパッケージなんて初めて見ました。

この中の「setup.exe」をダブルクリックして実行します。

4.セットアップ


セットアップ実行直後の画面は以下です。



「日本語化するアプリケーション」の選択ボタンを押下します。
実行ファイルの選択ダイアログが表示されますので、日本語化したいアプリの実行ファイルを選んで下さい。

私の場合はAndroidStudioの64bit版を日本語化したいので、「studio64.exe」を選びます。



後はもう、スルスルっと設定が行われ、以下の状態になります。



「日本語化する」のボタンを押下して下さい。

これで日本語化完了です。


5.起動


では、期待を込めてAndroidStudioを起動してみましょう。



バッチリです!!

終わりに


いやぁ、流石はレジェンドアプリのPleadesですね。

昔は「自分でパスを通せ」みたいな、実に技術者向けのそっけないツールだったのですが、今や完全GUI対応。
この進化は普通ではありません。

「AndroidStudioを普及させたい勢力が手伝った」とかあるんじゃないかな?
それくらい特別なアップデートが成されています。

日本Android界全体に影響を与える大改修と言って良いでしょう。

しかし、最近はIntelliJベース製品の攻勢が著しいですね。

Android開発はAndroidStudioが正式採用。
Python開発はPyCharmが世界最強と評価されています。

Javaは長年の間、Eclipseが支配的地位を占めてきましたが、

「AndroidはAndroidStudioなのにJavaはEclipseかよ?」

というのは誰もが思っていることでしょう。

私は伝統的JavaエンジニアなのでEclipseに最も慣れ親しんでいます。
しかし、IntelliJの活躍を見ると、慣れたEclipseを離れて新しい環境に挑戦していかなければならないと、最近強く思いますね。

今年度の更新はこれが最後です。
また来年も宜しくお願いします。

2017年12月18日月曜日

【Googleクラウド・機械学習編】CLOUD NATURAL LANGUAGE API その2

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

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

前回に引き続き、「CLOUD NATURAL LANGUAGE API」の実行を目指していきます。

前回まで

前回までで、ひとまずAPIの有効化と共に課金許可まで行いました。

認証ID取得

API管選択画面から「管理」のボタンを押して認証情報の取得画面に進みます。




選択肢が出てきました。

  • APIキー
  • OAuthクライアントID
  • サービスアカウントキー

このうち、単純に実行したい場合に必要なのはAPIキーです。
それ以外のキーは未調査。

APIキーを選択します。


無事に生成されました。

ここで注意事項ですが、APIキーは他人に漏らしてはいけません。

APIキーで個人を識別する仕様ですので、APIキーが漏れることは、ログインID/パスワードやクレジットカード番号が漏れることと同レベルの危機です。

ちなみに今は私が自分で検証しているだけなので考慮不要ですが、もし業務で本格的に使う事になったらAPIキー秘匿の為の策も練る必要があります。

外部への流出対策は言うまでもありませんが、内部に対する秘匿も課題になるでしょう。

例えば、

  • ログにHTTPリクエストのクエリが表示されている。
  • クエリの中にはAPIキーも含まれている。
  • ログは内部の人間ならば誰でも見れる。

なんてコンボをやらかしたら、もう完全にダダ漏れですよね。
こういうのを一つ一つ見落とさないように防いでいくことはなかなか難しいと思います。

クラウドにはクラウドのリスクがありますので、その辺りも理解する必要があります。

ともかくこれで無事に取得出来ました。




ちなみに今、「取得したけど一覧に何も出ない」という挙動しました。
F5を押したら表示されましたが。

ちょっとGoogleさん、画面リフレッシュの実装漏れみたいなバグがありませんか、これ?

Googleって、些細なバグは後回しにするような所がありますからね。
ユーザーも些細な事は気にしないのがお付き合いするコツです。

実行

さて、これで実行に必要な素材は全部揃ったはずなのですが。
ここからが難関。

API仕様書を読み込んで行かなければなりません。


また、HTTPリクエストを作るプログラムも実装しなきゃいけないなど、大変な作業が待っています。
しかし、親切な事にGoogleには「APIエクスプローラ」という動作確認用の機能があります。



これを使ってちょっと動作確認をしてみましょう。

文章

テキトーに考えた私の自己紹介を送り込んでみます。

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

仕事はシステムエンジニア。
特技は空手道初段です。

家族は妻が一名ほどいます。

好きなお酒はウイスキーです。

仲良くして下さい。
======================================

使用する機能

analyzeEntities。
エンティティ解析です。

エンティティとは、「特徴的な単語」と解釈すれば良いでしょう。

結果

以下のようなリクエストを送り込みます。
POST https://language.googleapis.com/v1/documents:analyzeEntities?key={YOUR_API_KEY}
 
{
 "document": {
  "content": "株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。\n\n仕事はシステムエンジニア。\n特技は空手道初段です。\n\n家族は妻が一名ほどいます。\n\n好きなお酒はウイスキーです。\n\n仲良くして下さい。",
  "type": "PLAIN_TEXT"
 },
 "encodingType": "NONE"
}
すると、こんな結果が戻ってきました。
200
 
- Show headers -
  
{
 "entities": [
  {
   "name": "株式会社ジェニシス 技術開発事業部",
   "type": "ORGANIZATION",
   "metadata": {
   },
   "salience": 0.22330247,
   "mentions": [
    {
     "text": {
      "content": "株式会社ジェニシス 技術開発事業部",
      "beginOffset": -1
     },
     "type": "PROPER"
    }
   ]
  },
  {
   "name": "遠藤 太志郎",
   "type": "PERSON",
   "metadata": {
   },
   "salience": 0.19125123,
   "mentions": [
    {
     "text": {
      "content": "遠藤 太志郎",
      "beginOffset": -1
     },
     "type": "PROPER"
    }
   ]
  },
  {
   "name": "Tacy",
   "type": "OTHER",
   "metadata": {
   },
   "salience": 0.19125123,
   "mentions": [
    {
     "text": {
      "content": "Tacy",
      "beginOffset": -1
     },
     "type": "PROPER"
    }
   ]
  },
  {
   "name": "仕事",
   "type": "OTHER",
   "metadata": {
   },
   "salience": 0.07422842,
   "mentions": [
    {
     "text": {
      "content": "仕事",
      "beginOffset": -1
     },
     "type": "COMMON"
    }
   ]
  },
  {
   "name": "システムエンジニア",
   "type": "OTHER",
   "metadata": {
   },
   "salience": 0.07422842,
   "mentions": [
    {
     "text": {
      "content": "システムエンジニア",
      "beginOffset": -1
     },
     "type": "COMMON"
    }
   ]
  },
  {
   "name": "特技",
   "type": "OTHER",
   "metadata": {
   },
   "salience": 0.05605998,
   "mentions": [
    {
     "text": {
      "content": "特技",
      "beginOffset": -1
     },
     "type": "COMMON"
    }
   ]
  },
  {
   "name": "空手道初段",
   "type": "OTHER",
   "metadata": {
   },
   "salience": 0.05605998,
   "mentions": [
    {
     "text": {
      "content": "空手道初段",
      "beginOffset": -1
     },
     "type": "COMMON"
    }
   ]
  },
  {
   "name": "酒",
   "type": "CONSUMER_GOOD",
   "metadata": {
   },
   "salience": 0.03795014,
   "mentions": [
    {
     "text": {
      "content": "酒",
      "beginOffset": -1
     },
     "type": "COMMON"
    }
   ]
  },
  {
   "name": "ウイスキー",
   "type": "OTHER",
   "metadata": {
   },
   "salience": 0.03795014,
   "mentions": [
    {
     "text": {
      "content": "ウイスキー",
      "beginOffset": -1
     },
     "type": "COMMON"
    }
   ]
  },
  {
   "name": "家族",
   "type": "PERSON",
   "metadata": {
   },
   "salience": 0.028858999,
   "mentions": [
    {
     "text": {
      "content": "家族",
      "beginOffset": -1
     },
     "type": "COMMON"
    }
   ]
  },
  {
   "name": "妻",
   "type": "PERSON",
   "metadata": {
   },
   "salience": 0.028858999,
   "mentions": [
    {
     "text": {
      "content": "妻",
      "beginOffset": -1
     },
     "type": "COMMON"
    }
   ]
  }
 ],
 "language": "ja"
}


考察

ほえ~。

「salience」とは突出率という意味で、この数字が高いほど特徴的で、
低いほどありふれた単語、という意味のようです。


  • 株式会社ジェニシス 技術開発事業部


これで一つの単語として認識されています。

TYPE:ORGANIZATION

しかし、「株式会社ジェニシス」が会社名で「技術開発事業部」が部署名であることまでの粒度には到っていません。

  • 遠藤 太志郎

私の名前も抽出出来ています。

TYPE:PERSON

ジェニシスの方は「TYPE:ORGANIZATION」で私の名前は「TYPE:PERSON」ですから、それが人間の名前なのか組織の名前なのかを識別出来るようです。

なるほどなるほど。
機能のイメージは沸いてきますね。
問題はこれをどう役立てるかということですが、試していくには元となるデータが沢山必要ですね。

同僚の日報とか解析してみると面白いかもしれません。

終わりに


引き続きCLOUD NATURAL LANGUAGE APIの検証を進めていこうと思います。

2017年12月11日月曜日

【Googleクラウド・機械学習編】CLOUD NATURAL LANGUAGE API その1

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

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

今回からGoogleクラウドAPIを使い始めていきます。
最初は「CLOUD NATURAL LANGUAGE API」です。

始め方


何事も最初が一番難しい。
「CLOUD NATURAL LANGUAGE APIってどこにあるのよ?」でまず躓きます。

GoogleクラウドAPI全般に言えることですが、APIは管理コンソールの中にあります。

コンソールの中に「APIとサービス」という項目があります。
これを選択して下さい。


その中に「ライブラリ」があります。


ライブラリを選択すると、お待ちかねのライブラリページが表示されます。



沢山あります!!

このライブラリページはGoogleクラウドの全機能が集結しています。

「CLOUD NATURAL LANGUAGE API」に限らず、「GMail」とか、「Googleカレンダー」とか、果ては「Youtube」まで。

Webで実現出来る機能は全部この中に投入されており、この中からお好きなものを選んで使用して下さい、とそういう形態なわけですね。
そして機能毎に使用回数とか伝送データ量とかが計測されており、それに応じてお金を払うという従量課金制で進行しております。

では、目当ての「CLOUD NATURAL LANGUAGE API」を検索しましょう。



出てきましたね。
これを選択するお、「有効にする」のボタンがある画面が表示されます。


さっそく有効にして……。おっと。

課金しろ、と出てきてしまいました!!


課金体系


私は一年間の無料お試しクレジットを貰っているので、当面は課金はされないはず。


とは言え何かミスって爆死したら困るので先に予算体系も調べました。







要約すると、


  • 5,000件までは無料
  • それ以降、1,000件辺り1ドルが必要
  • 大量使用ユーザは1000件辺り0.25ドルまで値下げOK


とのことです。

この「件」というのは、HTTPリクエストの送信回数のことです。
またCLOUD NATURAL LANGUAGE APIは一回当たりの送信文字数が1,000文字毎にも一件という閾値となっています。

そして1ヶ月毎にクリアされていきます。

つまり、


  • 1,000文字のHTTPリクエストを1回送る。⇒1件
  • 1,000文字のHTTPリクエストを2回送る。⇒2件
  • 999文字のHTTPリクエストを1回送る。⇒1件
  • 1,001文字のHTTPリクエストを1回送る。⇒2件
  • 1,001文字のHTTPリクエストを2回送る。⇒4件


こういう計算です。

月々5,000件までは無料というのは、私がチョコチョコと検証している限りは無料と言ってしまっても良いでしょう。

このように、

  • 大規模ユーザにはそれなりのお金を払って貰う。
  • 小規模ユーザには、少々のお金を払って貰う。
  • 個人がちょっと見てるくらいは無料。

クラウド環境は小規模スタートしたい時に有利と言われますが、全くその通りです。

ちなみに夏目漱石の「こころ」は、大体23万文字です。
対して、5,000件× 1,000文字 = 500万ですから、月々文庫本20冊くらいのバイト数は負荷のうちに入らないと見なされるくらいの大量データ処理を想定していることが分かります。

ビッグデータ解析という側面も持ち合わせたサービスなのですね。

有効化


これで無事にAPIの有効化に成功しました。


ここから先は実際にHTTPリクエストを送り込むフェーズになります。

HTTPリクエスト送信時には、認証IDという送信者を一意に認識するキーをリクエスト中に埋め込む必要があります。
次回は認証ID取得から始まります。


続く


結構長い道のりです。
しかしGoogle系のAPIはみんな同じ要領なので、一度経験しておけば二回目以降はスピーディーに作業出来ると思います。

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

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

終わりに


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