まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

2016/12

マンホールマップを Google の Search Console に登録して、どんなキーワードで検索された結果としてマンホールマップが使われているのか? を解析してみました。

使ったサービスはこれです:
Google Search Console

2016122700



ここにログインし、「検索アナリティクス」メニューから対象期間を選びます。また「クエリ」を選択して、検索キーワードごとに統計を出せるようにしました:
2016122705


ここで得られる結果はこのままだと取り扱いが難しいので CSV 形式でダウンロードしました:
2016122706



これで UTF-8 で書かれたクエリーごとの検索データを CSV で取得することができました。このファイル名を searchs.csv とします。

CSV のままだと取り扱いが不便なので、MySQL データベースに入れちゃいましょう。適当な(笑)MySQL データベースに、こんなスキーマのテーブルを作りました(CSV が UTF-8 なので、テーブルも UTF-8 指定しています):
mysql> create table searchs( id int primary key auto_increment, query varchar(100), clicks int, shows int, ctr float, rank float ) default character set utf8;

mysql> desc searchs
+--------+--------------+------+-----+---------+----------------+
| Field  | Type         | Null | Key | Default | Extra          |
+--------+--------------+------+-----+---------+----------------+
| id     | int(11)      | NO   | PRI | NULL    | auto_increment |
| query  | varchar(100) | YES  |     | NULL    |                |←クエリー
| clicks | int(11)      | YES  |     | NULL    |                |←検索結果からクリックされた回数
| shows  | int(11)      | YES  |     | NULL    |                |←検索結果に表示された回数
| ctr    | float        | YES  |     | NULL    |                |←クリック率
| rank   | float        | YES  |     | NULL    |                |←平均掲載順位
+--------+--------------+------+-----+---------+----------------+

先程の CSV をロードします:
mysql> load data local infile 'searchs.csv' into table searchs fields terminated by ',' (query,clicks,shows,ctr,rank);

これでサーチコンソールから取得した情報が MySQL データベースに入りました。こうなると色々楽ちんです。とりあえず phpMyAdmin あたりを使って、項目ごとに上位クエリーを調べてみましょう。

まずは検索表示回数。要は「マンホールマップが検索結果に表示された時、どのキーワードで検索されていたことが多いか?」です:
2016122702


ある意味想定通りですが、圧倒的一位は「マンホール」でした。マンホールマップを知らない人も含めた多くの人が「マンホール」を検索した結果だと思います。2位が「マンホールマップ」、知名度上がってると解釈していいでしょうか。3位は「豊井 スライド」(間にスペース)でした。これは何??ここからクリックされた形跡はなさそうだけど・・・いきなり深い謎に出会ってしまいました。。

面白いですね。では次はクリック回数。つまり検索結果に表示された回数ではなく、「検索結果に表示され、かつクリックしてマンホールマップに移動した回数」順です:
2016122701


これは「マンホールマップ」で検索した結果、マンホールマップに多く誘導できている、という当然の結果でした。そして「マンホール」で検索した人が「マンホールマップ」にたどり着いている、というパターンが2位でした。これも理想的で、いい結果です。その他地名との組み合わせで検索した結果が多くなっています。驚いたのは「さめがめ」で検索してマンホールマップにたどり着いた人がこの3ヶ月で3人いらっしゃったんですね。。。


次はクリック率(CTR=Click Through Ratio)、検索結果として表示されたうちの何%がクリックされたか、という数字です:
2016122703


いくつか 100% の例もありますが、嬉しいのは「マンホールマップ」で検索した人の 80%、「マンホール マップ」で検索した人の 60% が実際にクリックして訪れている、という結果です。マンホールファンはいい人が多いです(笑)。


最後に平均掲載順位。これは「検索結果の何番目にマンホールマップが表示されたか」の数字で小さいほど目立つ位置に表示されていることになります。そして 10 以下であれば検索結果の1ページ目に表示されていることになりますが・・・
2016122704


実はこの見方が僕もまだよく分かってなくて、例えば上記結果だけを見ると「ゆるキャラ」という検索結果に12回登場していて、その平均順位は 4.7 位(つまり最初のページに出ている)と読み取れます。マンホールマップがそんなに高い位置にいていいんだっけ?さすがにちょっと高すぎるような・・・

おそらくなんですが、実は検索時に "site:*****" とかの特殊なパラメータが付与された上での検索結果ではないかと想像しています。ただこの結果にそこまでの情報はないので、まあそのまま判断するしかないのかな、と。


ちなみにマンホールマップ全体としての平均 CTR は 8.07%、平均掲載順位は 14.3 でした。マニア向けのニッチな情報サイトから、より一般的なコミュニティサイトとして認知されるにはもう少し掲載順位を上げたい所ではあります。


こういう話は DeNA が詳しいのかな(苦笑)。

先日、IBM Bluemix から提供されている IBM Watson の翻訳 API である "Language Translator" サービスが待望の日本語対応を果たしました。現在、日本語翻訳機能としては英語→日本語、および日本語→英語のテキスト翻訳が可能になっています:
2016122808


この翻訳 API は文章の翻訳に加え、入力されたテキストが何語のテキストなのかを識別する機能も備えています。実際にどんな言語翻訳ができるのか、そのサンプル的なアプリケーションが以下で公開されているので、興味ある方は試してみてください:
https://language-translator-demo.mybluemix.net/

2016122809



さて、この IBM Watson 翻訳 API の特徴の1つが「カスタマイズ機能」です。デフォルトで提供される翻訳機能をベースに、自分なりのカスタマイズを加えることができるようになっています。これは日本語翻訳機能においても有効な機能です。

というわけで、早速カスタマイズを試してみましょう。ただし、このカスタマイズを使うには、Language Translator サービスは標準プランではなく、拡張プランを選択する必要があります。標準プランには無料枠が用意されていますが、拡張プランにはありません。サインアップから 30 日間の無料期間を過ぎていたり、既に有償プランに移行済みの場合は、サービスインスタンスを作成した段階でインスタンス料金が発生しますので、ご注意ください:
2016122801


では「拡張プラン」を選択していることを確認した上でインスタンスを「作成」します:
2016122802


こうして拡張プランの Language Translator サービスインスタンスを作りました。この後、実際に API を使うことになるので「サービス資格情報」の「資格情報の表示」からクレデンシャル情報を調べてメモしておいてください(繰り返しですが、拡張プランの資格情報です。流出すると勝手に使われて課金額がどんどん増えていくことになるので、取扱いに注意してください):
2016122803


次に実際にカスタマイズする内容を TMX(Transaction Memory eXchange) という翻訳メモリデータの標準フォーマットである XML ファイルで用意します。今回は以下の内容の osaka.tmx ファイルを手元で作って用意しました:
<tmx version="1.4">
  <header
    creationtool="MyTool" creationtoolversion="1.00"
    datatype="PlainText" segtype="sentence"
    adminlang="en-ja" srclang="en"
    o-tmf="MyTransMem"/>
  <body>
    <tu>
      <tuv xml:lang="en">
        <seg>Hello</seg>
      </tuv>
      <tuv xml:lang="ja">
        <seg>もうかりまっか</seg>
      </tuv>
    </tu>
    <tu>
      <tuv xml:lang="en">
        <seg>I am fine</seg>
      </tuv>
      <tuv xml:lang="ja">
        <seg>ぼちぼちでんな</seg>
      </tuv>
    </tu>
  </body>
</tmx>

(かなり偏見入ってますが・・)大阪弁のカスタマイズをするためのファイルです。英語の "Hello" を「もうかりまっか」に、"I am fine" を「ぼちぼちでんな」に変換する、という内容です。これを元々の英→日翻訳機能に上書きする形でカスタマイズする、という意味です。なお日→英の翻訳カスタマイズは今回の説明には含めませんが、同様にして(同様の TMX ファイルを別途用意する形で)カスタマイズすることは可能です。


これでカスタマイズの準備はできました。 が、カスタマイズの前に、カスタマイズ前の挙動を確認しておきます(後でカスタマイズ後の挙動と比較するためです)。ここからは curl コマンドを使って実際に API を使ってみるので、必要に応じてここなどから curl コマンドをインストールしておいてください。

まず最初に、Language Translator がデフォルトで用意しているモデル(日英とか、英日とか、英仏とか、・・)の一覧を取得してみます(username と password には上記の資格情報で取得したものを指定します。また黒字が入力コマンド、青字が出力結果です):
$ curl -u "username:password" "https://gateway.watsonplatform.net/language-translator/api/v2/models"

{
  "models":[
    {
      "model_id":"ar-en",
      "source":"ar",
      "target":"en",
      "base_model_id":"",
      "domain":"news",
      "customizable":true,
      "default_model":true,
      "owner":"",
      "status":"available",
      "name":"",
      "train_log":null
    },
      :
    {
      "model_id":"en-ja",
      "source":"en",
      "target":"ja",
      "base_model_id":"",
      "domain":"news",
      "customizable":true,
      "default_model":true,
      "owner":"",
      "status":"available",
      "name":"",
      "train_log":null
    },
      :
    {
      "model_id":"ja-en",
      "source":"ja",
      "target":"en",
      "base_model_id":"",
      "domain":"news",
      "customizable":true,
      "default_model":true,
      "owner":"",
      "status":"available",
      "name":"",
      "train_log":null
    },
      :
  ]
}

モデルの一覧が JSON 配列形式で出力されます。"model_id" の値が実際に翻訳する時やこの後のカスタマイズ時に翻訳の種類を指定する値になります。英日であれば "en-ja" 、日英であれば "ja-en" という値になります。

また各モデルの中に "customizable" という値があります。これは「このモデルをカスタマイズ可能か」を示した値であり、true になっているとカスタマイズ可能であることを示しており、このモデルに上書きする形でのカスタマイズが可能です(英日、日英ともに true です)。また "status" の値は現時点で利用可能な状態になっているかどうかを示しています(これも英日、日英ともに "available" となっているので使える状態になっています)。

ではカスタマイズ前の翻訳機能を試してみましょう。英語の "Hello" を日本語に翻訳してみます:
$ curl -u "username:password" "https://gateway.watsonplatform.net/language-translator/api/v2/translate?model_id=en-ja&text=Hello"

こんにちは

カスタマイズ前(model_id に既存の en-ja を指定)なので、期待通りの結果になりました。

ではここからはカスタマイズを加えてみましょう。上記で用意した osaka.tmx を指定して、以下のコマンドを実行します:
$ curl -u "username:password" -X POST -F base_model_id="en-ja" -F forced_glossary=@osaka.tmx "https://gateway.watsonplatform.net/language-translator/api/v2/models"

{
  "model_id":"be81b082-1292-47ac-badf-0beb83846f66",
  "source":"en",
  "target":"ja",
  "base_model_id":"en-ja",
  "domain":"news",
  "customizable":false,
  "default_model":false,
  "owner":"da0dc7f3-87c6-4d82-b965-79b463266291",
  "status":"dispatching",
  "name":null,
  "train_log":null
}

基本モデル(base_model_id)を英日(en-ja)にして、そこに osaka.tmx で指定した内容を上書きでカスタマイズする、という内容のコマンドです。実行結果には新しい model_id (be81b082-1292-47ac-badf-0beb83846f66)が付与されて返っています。また customizable 値は false になっているので、このモデルをベースに更にカスタマイズ、ということはできません。status は "dispatching" となっているので、この時点ではまだ内部処理中です。

少し待ってから再度ステータスを確認し、"available" となっていることを確認できたら翻訳も可能になります。
$ curl -u "username:password" "https://gateway.watsonplatform.net/language-translator/api/v2/models/be81b082-1292-47ac-badf-0beb83846f66"

{
  "model_id":"be81b082-1292-47ac-badf-0beb83846f66",
  "source":"en",
  "target":"ja",
  "base_model_id":"en-ja",
  "domain":"news",
  "customizable":false,
  "default_model":false,
  "owner":"da0dc7f3-87c6-4d82-b965-79b463266291",
  "status":"available",
  "name":null,
  "train_log":null
}

また、この段階でモデル一覧を再確認すると、カスタマイズしたこのモデルも一覧の先頭に含まれて表示されることがわかります:
$ curl -u "username:password" "https://gateway.watsonplatform.net/language-translator/api/v2/models"

{
  "models":[
    {
      "model_id":"be81b082-1292-47ac-badf-0beb83846f66",
      "source":"en",
      "target":"ja",
      "base_model_id":"en-ja",
      "domain":"news",
      "customizable":false,
      "default_model":false,
      "owner":"da0dc7f3-87c6-4d82-b965-79b463266291",
      "status":"available",
      "name":null,
      "train_log":null
    },
    {
      "model_id":"ar-en",
      "source":"ar",
      "target":"en",
      "base_model_id":"",
      "domain":"news",
      "customizable":true,
      "default_model":true,
      "owner":"",
      "status":"available",
      "name":"",
      "train_log":null
    },
      :
    {
      "model_id":"en-ja",
      "source":"en",
      "target":"ja",
      "base_model_id":"",
      "domain":"news",
      "customizable":true,
      "default_model":true,
      "owner":"",
      "status":"available",
      "name":"",
      "train_log":null
    },
      :
    {
      "model_id":"ja-en",
      "source":"ja",
      "target":"en",
      "base_model_id":"",
      "domain":"news",
      "customizable":true,
      "default_model":true,
      "owner":"",
      "status":"available",
      "name":"",
      "train_log":null
    },
      :
  ]
}

ではこのカスタマイズモデルを model_id に指定して、先程と同じ英語を翻訳してみます:
$ curl -u "username:password" "https://gateway.watsonplatform.net/language-translator/api/v2/translate?model_id=be81b082-1292-47ac-badf-0beb83846f66&text=Hello"

もうかりまっか

期待通りのカスタマイズが有効な変換結果になりました。なお "I am fine" でもカスタマイズした結果が翻訳されますが、それ以外の(カスタマイズしていない)テキストについてはベースとなっている英日翻訳が有効になって実行されます:
$ curl -u "username:password" "https://gateway.watsonplatform.net/language-translator/api/v2/translate?model_id=be81b082-1292-47ac-badf-0beb83846f66&text=I%20am%20fine"

ぼちぼちでんな

$ curl -u "username:password" "https://gateway.watsonplatform.net/language-translator/api/v2/translate?model_id=be81b082-1292-47ac-badf-0beb83846f66&text=Good%20evening"

こんばんは

カスタマイズモデルが不要になった場合は以下のコマンドで削除することができます:
$ curl -u "username:password" -X DELETE "https://gateway.watsonplatform.net/language-translator/api/v2/models/be81b082-1292-47ac-badf-0beb83846f66"

{"status":"OK"}

今回紹介したのはごくシンプルなカスタマイズでしたが、より多くの語彙を用意できれば方言や、或いは全く新しい言語の翻訳機能まで実現することができるかもしれません。そんなカスタマイズ機能が IBM Watson の Language Translator API には提供されている、という紹介でした。


なお、Language Translator API の詳しい関数リファレンスはこちらを参照ください:
https://www.ibm.com/watson/developercloud/language-translator/api/v2/

実際に挙動をためせる Watson API Explorer はこちら:
https://watson-api-explorer.mybluemix.net/apis/language-translator-v2#/


#TMX をもう少し楽に作れるツールとかないかな・・・


IBM Bluemix に待望の IBM 製 MySQL サービス(この表現、誤解招くかな・・・IBM がサポートを含めて提供する MySQL サービスという意味です、詳しくは後述)が追加されました。それが Compose for MySQL です:
2016122601


IBM Bluemix 環境で MySQL データベースを使おうとした場合、以前は2つの選択肢がありました。1つは試験提供的な扱いで、ごく小さな容量のデータベースが提供されていたコミュニティ版の mysql サービス、もう1つはビジネスパートナーである ClearDB 社から提供されていた ClearDB MySQL Database サービスでした。後者は段階に応じて容量やサービス内容が選択できるものでしたが、いずれも IBM から提供されていた扱いのものではなく、サブスクリプション契約時の割引対象とはなりませんでした:


今回、新たに追加された Compose for MySQL サービスは、現時点(2016/Dec/26)での扱いはベータ版ですが、IBM サービスとして提供されます。Compose は多くの DBaaS を提供している企業で、2015年7月に IBM が買収し、IBM Bluemix サービスのコンポーネントとしても提供されるようになりました。MySQL は ElasticSearch などと同様に Compose サービスの1つとして Bluemix からも提供され、IBM がサポートします。サービスインスタンスを作成すると 1GB のデータ容量を持ったデータベースが使えるようになります。この容量は実質的には 1GB 単位でスケールし、従量課金となります:
2016122602


サービスインスタンスを作成して、資格情報を参照すると、このインスタンスに接続するための情報を確認することができます:
2016122603


この情報に従ってコマンドラインクライアントや JDBC などのプログラムによって、Compose for MySQL データベースに接続することができます:
2016122604


試しに提供されたデータベースの設定を確認してみました。どうやらデフォルトの文字コードは latin1 になっているようでした。日本語データを扱う場合はテーブル作成時に utf8 を指定するなど、日本語を扱う前提でテーブル定義をする必要がありそうです:
2016122605


私はプライベートではずっと MySQL や MySQL 互換データベースサーバーを使っていたので、個人的にも待望の MySQL サービスが追加されたことになります。


小型コンピュータである Raspberry Pi(以下「ラズパイ」)のデスクトップ環境をラズパイ以外にも提供するプロジェクト "PIXEL" 、その x86(i386) 版が公開されました:
PIXEL for PC and Mac

まだ実験的な段階であり、バージョン番号にも日付が使われている状態です。僕がダウンロードしたものは 2016-12-13 時点のものでした。デフォルトで LibreOfficeChromium ブラウザ、Scratch を含む各種プログラミングによる統合開発環境が搭載されており、最低限以上のデスクトップ環境になっていました:
2016122501


ラズパイはもともと教育用途に開発された経緯があり、低スペックなマシンでもある程度動作することを目標にしていました。その考え方は PIXEL にも受け継がれているようで、古い PC や Mac 環境を蘇らせることができるかもしれません。

現時点では PIXEL のトップページからブート可能な iso がダウンロードできるような形で公開されています。こいつを DVD や USB メモリに保存してそこから起動するか、あるいは仮想環境下でこの iso を指定してブートするだけです。ハードディスクへのインストールして簡単に起動できるような環境はまだ提供されていない模様ですが、今手元で使っている環境に影響を与えずに試せるようなものが提供されている、と考えられます。

日本語環境についてはカスタマイズで可能なように見えますが、その方法はまた別の機会に。


スウェーデン発祥の世界最大の家具量販店 "IKEA(イケア)"。ここは毎年ジンジャーブレッドハウスコンテストを開催しています:
https://www.smartcontest.jp/system/ikeafoodcontest/pc/

2016122301


イケア店内でも売られているジンジャーブレッドハウスキットを使ったデコレーションコンテストです:
2016122302


板状のジンジャーブレッドを組み立てて家を作って、デコレートして、写真に撮って、その出来栄えを競い合う、というものです。昨年の応募作品を見ると信じられないくらいにレベルが高い・・・
2016122303


もともとこのコンテストを知っていたわけではないのですが、たまたま近所の TOKYO BAY 店(旧船橋店)で実物を見かけた時、ふと
  「この家、ラズベリーパイがちょうど入るくらいのサイズなんじゃね?」
とアレなアイデアが浮かんでしまったのでした。。

いやでもクッキーだし、粉とかラズパイみたいな精密機械にいい影響があるわけないし、何より食べ物を粗末にするのはよくないし・・・うーん、、、


行けばわかるさ!
IMG_0082


ジンジャーブレッドハウスを作るのは初体験です。軽く「組み立てるだけだよね?」と考えて購入しましたが、その「組み立てるだけ」が難しいのなんのって。。 自分は一応は大工の息子ですが、そのDNAはもう残ってないと実感しました(苦笑)。屋根が自分の重みで落ちてきちゃって、、、みんなどうやって固定させるんだろ・・・

苦労しながらもなんとか家が家の形になってきました。外から見たお家の中の様子。一瞬「業務用キッチン?」と見間違えそうですが、USB ポート x 4です:
IMG_0083


煙突立てて、サンタ人形を載せて、外観は完成。なんかケーブルが見えてますが気のせいです:
IMG_0085


気のせいなケーブルをコンセントに挿すと、家の中にほのかな明かりが灯ります。意外と悪くないかも!(慣れない創作作業で結構苦労したせいか、この辺りから判断基準がおかしくなってるかもしれません):
IMG_0086


ラズパイはもちろん無線 LAN で Linux サーバーとしても稼働中なので、GPD WIN 機から ssh で接続してみました。このゲーム機みたいな PC から家の中の様子を覗いてるイメージです:
IMG_0091


最後にシュガーとグミでデコレーションを追加。本当は砂糖の粉雪を降らせたかったのですが、さすがにラズパイの動作への影響と、何より危険だと思ったので断念しました。GPD WIN から IBM Bluemix の Node-RED スターター環境にアクセスして、この家(ラズパイ)からのセンサーデータを取得できるようにしました。わかりにくいのですが、家の中の状態をこの PC から監視しています。一応これが完成品です(コンテストにはこの写真で応募する予定w):
IMG_0097


微妙なタイミングを測って、ラズパイの LED が2つ(赤と緑)点灯した瞬間を撮影してみました。僕の脳内では少女とその両親が、キャンドルの周りで神様にお祈りをしている姿まで見えています:
2016122300


お約束ですが、この後美味しくいただきます!

なお、ジンジャーブレッドハウスコンテストへの投票はこちらから。よろしくお願いします(笑):
ジンジャーブレッドハウスコンテスト | IKEA FOOD


Happy Merry Christmas!

このページのトップヘ