小さなエンドウ豆

まだまだいろいろ勉強中

ElasticSearch入門

GW最終日

今年のGWは何もすることができなかった。正確に言えば動けなかったとも言えるだろう。なぜならお金が無いからだ。就職活動がためにとんでしまったのである。普通なら大型連休だし欲望のまあ消費活動に勤しみたいところであったが資金がなかった。そもそもGWって遊ぶための連休なのか?学生の本業は勉学ではないか?と自問自答や屁理屈を言った結果最終日もお勉強することに

今日は研究で今後必要だろうElasticSearchについて勉強していく。

ElasticSearchとは

ElasticSearchは全文検索エンジンであるらしい。 全文検索について知らない私はその意味を調べると、

複数の文書から特定の文字列を検索すること」

らしい。

とりあえずさわってみる

ElasticSearch2.3.2をzipでダウンロードしてくる

$ wget https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/zip/elasticsearch/2.3.2/elasticsearch-2.3.2.zip
$ unzip elasticsearch-2.3.2.zip
$ cd elasticsearch-2.3.2
$ bin/elasticsearch &
$ curl -X GET http://localhost:9200

とサイトに書いてあるインストールステップ律儀にこなす

{
  "name" : "Antiphon the Overseer",
  "cluster_name" : "elasticsearch",
  "version" : {
    "number" : "2.3.2",
    "build_hash" : "b9e4a6acad4008027e4038f6abed7f7dba346f94",
    "build_timestamp" : "2016-04-21T16:03:47Z",
    "build_snapshot" : false,
    "lucene_version" : "5.5.0"
  },
  "tagline" : "You Know, for Search"
}

nameのところの値はにはマーベルのキャラクタの名前をランダムで当てているらしい。ちなみに"Antiphon the Overseer"というのは彼らしい
f:id:h-piiice16:20160503122853j:plain

公式ドキュメント

公式のドキュメントには僕みたいな初心者のためにある銀行の顧客データを模したサンプルのデータセットが用意されている。今回はそれを使う。

まずデータセットをローディングしていく。

$ curl -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary "@accounts.json"
$ curl 'localhost:9200/_cat/indices?v'
health index pri rep docs.count docs.deleted store.size pri.store.size
yellow bank    5   1       1000            0    424.4kb        424.4kb

どうやらできてるっぽい!

Node.js + ElasticSearchで簡単な検索サービスを作る

つい昨日Expressに入門した私は検索エンジン的なものが作れるのではないかと考えやってみることにした。

まずはviwes/index.ejsである。

<!DOCTYPE html>
<body>
 <h1>ES bank Query Test!.</h1>
 <form method="post" action="/">
  <table>
  <tr>
    <td><p>query</p></td>
    <td><input type="text" name="input1" value="<%= query %>"></td>
  </tr>
  <tr>
  <td>fields</td>
  <td><input type="text" name="input2" value="<%= fields %>"></td>
  </tr>
  </table>
  <input type="submit">
 </form>
 <br><br>
 <div>
  <%= content %>
 </div>
</body>

次にapp.jsを書いていく。

var express = require('express');
var ejs = require('ejs');
var bodyParser = require('body-parser');

var elasticsearch = require('elasticsearch');
var client = elasticsearch.Client({
        host: 'localhost:9200'
});

var app = express();

app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());

app.engine('ejs', ejs.renderFile);

app.get('/', function(req, res){
        res.render('index.ejs', {
                query: '',
                fields: '',
                content: ''
        });
});

app.post('/', function(req, res){
        client.search({
                index: 'bank',
                type: 'account',
                body: {
                        query: {
                                multi_match: {
                                        query: req.body['input1'],
                                        fields: req.body['input2'].split(',')
                                }
                        }
                }
        }).then(function(response){
                var hits = response.hits.hits;
                var str = JSON.stringify(hits);
                console.log(hits);
                res.render('index.ejs', {
                        query: req.body['input1'],
                        fields: req.body['input2'],
                        content: str
                });
        }, function(error){
                console.trace(error.message);
        });
});

app.listen(3000);

Nodejsのモジュールでelasticsearchという便利なものがあるのでそれを使いElasticSearchにクエリを流す。elasticsearchはnpmで普通にinstallできる。

これが実行結果である。

f:id:h-piiice16:20160508154303p:plain

f:id:h-piiice16:20160508154311p:plain

今回はさわってみただけでElasticSearchの構造や仕組みについて触れていないが大体イメージをつかむことができた。構造や仕組みについてもこれから勉強するつもりなのでまとまったらまたブログにまとめてみたい。

p.s.
この記事を書いてる途中でネットが切れてしまい記事全部ふっとびました。みなさんもお気をつけ下さい。

Express入門

Webアプリ作ってみたい

こんにちは、最近やる気が散漫している大学生です。
今日は前から気になっていたりサンプルコード動かしたりしていたNode.jsのフレームワークexpressについてちゃんと入門したい。
思えば私はWebアプリケーションを作ったことがなく勉強しなくてと前から思っていた。
他にもいろいろやることがあるがまとまった時間が取れるのが今日くらいなので今日入門を果たしたい。

Express

さっきも言ったがNodejsのフレームワークの名前である。まずはHelloWorld的なことをやってみる。 てきとうにディレクトリ作ってその中でapp.jsを作る。

var express = require('express');
var app = express();

app.get('/', function(req, res){
 res.send('Hello World!');
});

app.listen(3000);

localhost:3000にアクセスするとHello World! と書いたページが現れる。
次にテンプレートejsを使ってWebページを作っていく。ここではejsとはHTMLみたいなものと認知しておいた。
viewsというディレクトリを作り、中にindex.ejsを作る。

<!DOCTYPE html>
<head>
 <title><%= title %></title>
</head>
<body>
 <h1><%= title %></h1>
 <%- content %>
</body>

次にapp.jsを変更する。

var express = require('express');
var app = express();
var ejs = require('ejs');

app.engine('ejs', ejs.renderFile);

app.get('/', function(req, res){
 res.render('index.ejs', {
  title: 'Sample',
  content: '<p>Sample node app!.</p>'
 });
});

app.listen(3000);

node app.jsで実行しlocalhost:3000にアクセスすると、index.ejsの<%= tiltle %>に”Sample”が代入され、<%- content %>のところに<p>Sample node app</p>が代入されページに表示される。

ここまでは公式サイトやいろいろなサイトで触れられているので細かい説明は省いた。今回Expressを勉強するうえで私の中での目標がルーティングについて理解することである。

ルーティング

今までexpressを全くさわったことがなかった私は何回か今回のような入門に手を出したことがある。しかしそのたびに挫折していたのがルーティングの部分である。正直routesとディレクトリを作って何かしらの作業をする意味がわからなかった。

しかし今日しっかりと入門をしてみてわかったのがこれをするとルーティングの部分がモジュール化されすごくすっきりとしたコードになると自分なりに理解した。それでは今日やったことを示していきたい。

まずroutesというディレクトリを作り、index.jsを作り、以下の内容を書く

var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next){
 res.render('index.ejs' {
  title: 'Sample', 
  content: '<p>Sample node app!.</p>'
 });
});

module.exports = router;

次にapp.jsを変更する

var express = require('express');
var app = express();
var ejs = require('ejs');
var index = require('./routes/index.js')

app.engine('ejs', ejs.renderFile);

app.use('/', index);

app.listen(3000);

この実行結果は前回のものと一緒となる。つまり'/'にアクセスするときページを描画する動作を別のファイルに記述しそれをモジュール化することによりわかりやすくしているのだと理解できた。
この例はまだ行数がなくルートが1つため良いが、ルートが増えたり、getだけでなくpostなどの他の操作が加わるとapp.jsの行数が増え可読性に優れないコードが出来上がってしまう恐れがある。そのためルーティングはルートごとに書くことが大事だとわかった。

またgetだけでなくpostメソッドについても使い方を知りたかったので簡単なものを作ってみた。

postについて

まずはコードを示していく。index.ejsである。

<!DOCTYPE html>
<body>
 <h1><%= title %></h1>
 <%- content %>
 <form method="post" action="/test">
  <input type="text" name="input1" value="<%= input %>">
  <input type="submit">
 </form>
</body>

つぎにviewsにtest.ejsというファイルを作る。

<!DOCTYPE html>
<html>
<body>
 <p> get test.ejs!.</p>
 <p><%= input %></p>
</body>
</html>

次にroutesのindex.jsに以下を追加する。

  var str = req.body['input1'];
  res.render('test.ejs', {
    input: str,
  }); 
});

最後にapp.jsに以下を追加

var bodyParser = require('body-parser');

app.use(bodyParser.urlencoded({extended: false }));
app.use(bodyParser.json());

これを追加することによりindex.jsのvar str = req.body['input1'];がうまくいくようになる。おそらくindex.ejsの入力フォームに入力した内容を抜き出す際にパースする処理が必要なのだと思われる。
そしてこれらを実行すると f:id:h-piiice16:20160507171958p:plain

"test"と入力し、Submitすると、

f:id:h-piiice16:20160507172033p:plain

この"test"はさっきindex.ejsで入力した"test"であるはず…

まとめ

今回は割りと真面目にExpressについて入門したつもりだがやはり実用的なものをつくまでには至っていない。まあ一朝一夕にいくとも思っておらずこれからも手を動かしながらやっていきたいと思う。

それと何を作りたいか明確にせねば何を勉強すればよいかわからずまた露頭に迷ってしまうことになってしまう。なのでまた機会があればTODOリストなんか作ってみたいと思う。

とはいえいろいろと途中で投げ出しているものがあるのでそれらを先に片付けていきたい。(ラズパイとか、Tensorflowやらその他もろもろ…)

ラズパイをアラームに 2回目

季節外れの

こんばんは、最近季節外れの風邪にかかり体調が優れません。周りにも風邪ひきが結構いて季節外れでもないのかもしれないがこんな大事な時期にと気を落としております。
私にはまだ就職活動や研究などやらねばならぬことがいろいろとあるというのに…幸いキーボードはタイプできるのでやりかけていたラズパイアラーム化の計画を進めまとめていきたい

ラズパイを喋らせる

ラズパイに喋ってもらわないとアラームにもならないし独り身の僕が寂しいので喋らせることにした。参考したのはコチラである。
Raspberry Pi | ラズパイに喋ってもらう作戦(Open JTalk1.08のインストールと音声出力設定)

記事のタイトルがすごく気に入ってこれを参考にラズパイを喋らせる作戦に僕も成功しました!
ここで私は初めてbin直下のファイルを作るということを経験しましたがシェルの知識が皆無なので勉強しないとファイルの内容は理解できないと新たな課題を見つけることができました。
そして実行です!

jsay お大事に!

ちなみに第一声は「お大事に!」です。デフォルトで女性の声になっていたので安心しました。しかし作業感が拭えなかった アレンジなどできるならやってみたい。

ちっさい蛇

次に前回書いたスクリプトで天気を取得してきたのでその結果をラズパイに喋らせたい、あの事務的な声で天気を明日明後日の天気を喋らせたいと思いすこしスクリプトに編集を加えいざ実行…
しかし動かなかった。原因はPythonのバージョンにあった。Python2でどうやら実行していたみたいでスクリプトはPython3系の文法で書かれているため動かなかったみたい。

ではPython3で実行すれば良いではないかと思わるかもしれないがそもそも僕のラズベリパイ上でろくにPythonを各環境が整っていなかったことがわかったのでまずそれからしようと決意した。

いままでPythonを書くとき頼ってきたのがAnacondaである。今回はMinicondaというものを使いたいと思う。理由はanacondaがRaspbian上で動くか怪しかったためである。

まずはMinicondaのインストールを行うシェルスクリプトのファイルをダウンロードしてきて実行する

$ wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-armv7l.sh
$ bash Miniconda3-latest-Linux-armv7l.sh

あとはAnacondaと同じ要領でインストールを行う。

これで環境は整った!以下が実行したスクリプトである

import urllib.request
import json
import os

city = '330010'

res = urllib.request.urlopen('http://weather.livedoor.com/forecast/webservice/json/v1?city=%s'%city).read()

res = res.decode('utf-8')

res = json.loads(res)

text = res['title']
text = "".join(text.split(" ")[1:])

for forecast in res['forecasts']:
        text = text + forecast['dateLabel'] + forecast['date'] + forecast['telop']

print(text)

cmd = "jsay " + text

os.system(cmd)

読み上げる文字列がコチラである

岡山の天気今日2016-04-24晴れ明日2016-04-25晴れ明後日2016-04-26晴のち曇

ここで必要なのが文字列中にスペースがあると続けて読まれないので注意! そのために14行目あたりにスペース除去のための処理を書いているのだがもっとよい書き方はないかと模索中
あと日付だが数字をそのまま読むためフォーマットを変える必要がある。

  • 14行目の書き方の改善
  • 年月日の形式の変更
  • 天気以外にも何か読ませる(一応予定ではgoogleカレンダーの予定を読ませるつもり)

これらを次までの目標としたい

新企画! ラズパイをアラームに

単位をください

こんばんは、4年生になった今でも講義を取らなくてはいけない大学生です...

意識の高い私大学生は1,2限の講義をとってしまった。というよりその講義しか興味なかったという方が正しいかも

というわけで起きれる目覚まし時計を作りたいのだが、大学生とはいえ多忙()な私にとってただの目覚ましじゃ物足りなくその日の予定なんかも同時に知りたい。更に言うなら天気なんかも知りたい。

ではどうするかとなったときそこにあったのはケース無しのラズパイ!(買ってSSHとかで使ってたけどほぼ使ってないw) これ使って「今日の予定+今週の天気をしゃべる」ものを作ろうと今日決意した。

これから何回かに分けてその経過をここに綴っていきたい…(3日坊主にならないようにしよ)

今日明日くらいの天気

天気を知るために便利なAPIがあるのは知っていたが今回はlivedoorのお天気APIであるWeather Hacksを使うことにした。

リクエストする際のURLは以下である
http://weather.livedoor.com/forecast/webservice/json/v1
これに都市を表すパラメータを付与しリクエストする。例えば岡山だったら
http://weather.livedoor.com/forecast/webservice/json/v1?city=330010
である。
返ってくるレスポンスはリンク先のとおりである。

次に実際に書いたスクリプトである。

import urllib.request
import json

city = '330010' # 岡山

res = urllib.request.urlopen('http://weather.livedoor.com/forecast/webservice/json/v1?city=%s'%city).read()

res = res.decode('utf-8') # レスポンスがバイト列であったためutf-8にデコード

res = json.loads(res) # json形式のレスポンスをデコード

text = res['title']

for forecast in res['forecasts']:
    print(forecast['dateLabel']+'('+forecast['date']+')' )
        print(forecast['telop']) 

これで岡山の今日の天気と明日の天気を得ることができた!

今日は花金なので早く休んで明日あたりでこれを喋らせることにしようと思う

Tensorflow入門

最近

最近は就職活動で忙しくしていたためなかなかブログを書くことができませんでした。
これから頑張って自分のスキルアップのため頑張りたいと思います。。。

Tensorflow

しかし就活中ながら隙間の時間に勉強会などに参加するようには心がけていた。そこでTensorflowの話題が上がった。私もずっとさわってみたいと興味はあったのだが何もしていない状態だったので今回入門してみることにした。

まずAnacondaのvirtualenvを使ってTensorflow用の環境を作る。 pythonのバージョンは最新?の3.5.1を使うことにした。

$ pip install virtualenv
$ conda create --name tensorflow_env python=3.5.1
$ source activate tensorflow_env

次にpipを使ってTensorflowをインストールするのだが...

(tensorflow_env)$ pip install --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.6.0-py3-none-any.whl

…

Collecting setuptools (from protobuf==3.0.0a3->tensorflow==0.6.0)
  Using cached setuptools-20.9.0-py2.py3-none-any.whl
Installing collected packages: six, setuptools, protobuf, numpy, tensorflow
  Found existing installation: setuptools 20.7.0
Cannot remove entries from nonexistent file /home/nori/anaconda3/envs/tensorflow/lib/python3.5/site-packages/easy-install.pth

調べてみるとsetuptoolsがコンフリクトしているのが問題らしくconda removeでsetuptoolsをリムーブすれば大丈夫かと思いいろいろ試行錯誤してみたもののうまく行かず…

結局2系でTensorflowを使ってみることにした。

同じ要領でpython2.7.11の環境を作りTensorflowをインストールする。

$ conda create --name tensorflow_env2 python=2.7.11
$ source activate tensorflow_env2
(tensorflow_env2)$ pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.5.0-cp27-none-linux_x86_64.whl 

インスト−ルが完了すると早速インポートして試してみる

(tensorflow_env2)$ python
>>> import tensorflow
>>>

成功!
また最近jupyter notebookを使ってコードを管理しているためTensorflowのテストコードをipynbのファイルで残したいと思った。
そのままではjupyterでインポートはできなかったため調べてみるとカーネルを設定しなければならないらしい。pyenv-virtualenv + TensorFlow 環境設定覚書を参考にしてみる。
Tensorflow用のカーネルを追加する。

$ cd ~/.ipython/kernels
$ mkdir tensorflow && cd tensorflow
$ vim kernel.json
{
  "display_name": "TensorFlow (Python 2)",
  "language": "python",
  "argv": [
    "/home/User/anaconda3/envs/tensorflow_env2/bin/python",
    "-c", "from IPython.kernel.zmq.kernelapp import main; main()",
    "-f", "{connection_file}"
  ],
  "codemirror_mode": {
    "version": 2,
    "name": "ipython"
  }
}

これでjupyterでもTensorflowが使えた!
ちなみにテストコードはこんな感じ

import tensorflow as tf

hello = tf.constant("Hello Tensorflow!")
a = tf.constant(10)
b = tf.constant(20)
sess = tf.Session()

print sess.run(hello)
print sess.run(a+b)

今後の課題

今後の課題をいかに列挙しておく

  • Python3でなぜTensorflowが使えなかったのか?
  • jupyter notebookで作成したノートブックをはてなブログに埋め込めないのか
  • Tensorflowを使った応用プログラムの作成

これらのことについて今週中に頑張りたい

追記

linuxでpython3.5用のTensorflowをインストールするためにはTensorflowの公式ページにあった以下のコマンドを打てばよかった
(tensor_env)$ pip install --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow-0.8.0rc0-cp27-none-linux_x86_64.whl

Challenge1をデータで見る!

気が気じゃない!

こんにちは、就職活動ってなんか気が気じゃなくいろいろ大変だなーと感じる
息抜きに趣味に没頭してみようとするも頭の片隅にいて集中できない
仕方なくコード書いてみるもうまく行かずにストレスが溜まる
はやく終わらせたいものです。

今日はそんな就職活動を忘れるべくChallenge1について書きたいと思います。

Challenge1 とは

Challenge1とはJリーグのJ2に所属しているファジアーノ岡山が掲げている目標である。
その内容は大きく言うといろいろな'1'を目指すものであるが、中でも数字が絡んでくるのが「平均入場者数1万人」という目標である。
私もその目標を達成すべく微力ながら毎試合ホーム戦は足を運んでいる。しかしその目標は大変でChallenge1初年の去年は8,412人という結果で終わった。
サポータの間でも知り合いを誘ったり、クラブ側もいろいろな施策を行っているように伺えたが数字が1万には達さなかった。
ここで岡山の地で平均1万人はそもそも無謀なのではないかという疑問が湧いた。 まず岡山が平均1万人呼べるポテンシャルがあるか調べてみた。

岡山のポテンシャル

岡山県の人口は全体で192万人で男性が922,294人、女性は999,887人である。(平成27年度国勢調査)意外にも女性の方が多いのがわかった。
数字だけ見ると平均1万人は楽勝に見えるが岡山県域すべての地域の人が毎試合見に行くとは考え難い。
次にスタジアムがある岡山市の人口を調べると、 全体で720,034人、男性は346,276人、女性は373,758人である。
更に岡山市岡山市でもスタジアムは北区にあるので北区の人口を調べてみると、全体で309,685人、男性は 151,163人、女性158,522人であった。
ちょっとわかりづらいので表にまとめると、

地域 男性 女性 全体
岡山県 922,294 999,887 192万
岡山市 346,276 373,758 720,034
北区 151,163 158,522 309,685

(単位は人である)
今回は男性と女性でしか分けていないが意外にも岡山県岡山市北区の男性だけでも毎試合来れば目標が達成できてしまうのである。
まあすべての人がサッカーに興味があるわけでも無いためここから削られて今のような人数になっているのだと思う。 しかし北区だけでも3人に1人、市内では7人に1人と考えると難しいと私は感じた。 しかし平均1万人は無理ではないと感じ、岡山はChallenge1を達成する能力があるとわかった。

では何をすればよいか

岡山県の人口がわかったところで試合にきてくれそうな県民192万人に向けどのように集客を試みればよいか僕なりに考えてみたいと思います。
まずは現状把握をしたいと思います。現在ホーム戦3試合終わり1万人越えた試合がなく、それぞれこのような結果となっている。

相手 入場者(人)
千葉 9288
京都 9098
北九州 7050

なぜこのような結果となっているかは分からないがまだ始まったばかりで判断がしにくい・・・
そこで前年度の結果の分析をしてみることにしてみました。
去年私はこのような分析のために試合後にいろいろなデータを保存してきた。まずはいろいろな属性のデータの中から入場者数と関係があるものを調べたいと思います。
f:id:h-piiice16:20160331001558p:plain
こんな感じである。描画したデータは

  • 日時(x軸のラベル)
  • 曜日(x軸のラベル)
  • 気温(青いグラフ)
  • 勝点(棒グラフの上のテキストの色 青:0点 黒:1点 赤:3点)
  • 入場者数(棒グラフ)

あと10000人を表すx軸に平行な赤い線を追加してみました。

分析

  • 昨季は1万人越えた試合は開幕戦の岐阜戦、セレッソ大阪戦、札幌戦、東京ヴェルディ戦の4試合でした。セレッソ戦では16000人近くの入場者を記録している。今季も幸いセレッソ戦はあるので期待できそうです。

  • 気温が上がると入場者が減っているように思えます。何か関係があるのかもしれません。去年の夏、毎試合うちわを配っていたのを思い出しましたが、それ意外にも何か取り組むと良いかもしれませんね・・・

  • 平日開催のゲームはやはり入場者数が落ちています。今季も3試合?くらいあるので覚悟が必要ですね。

  • 中四国のチーム(愛媛、讃岐、徳島)との試合は比較的入場者数が多い。これはPRIDE OF 中四国のPRのおかげかもしれません。今季はやJ2に所属するチームが昨季から1つ増え5チームとなっているため集客は見込めそうです。

  • あと意外にも勝ち試合で観客が少ないんですね。やっぱり私は勝つ試合が見たいと思うのでせっかくなら観客の多い試合で勝ちいろいろな方に次も見に行きたいと思って欲しいです。今季のホーム戦3試合では2勝1分けで負け無しなのでこれを続け集客にも繋がって欲しいです。


いろいろ偉そうに言ってきましたが本当にこの目標を達成しJ1という1にチャレンジしてほしいという気持ちであります。

matplotlibで書いた図をD3で可視化

なんてったってPython

こんばんは、このブログも長いもので2ヶ月くらい続いています。当初は3日坊主で終わるのだろうと思っていたのだが、案外書くのが楽しくなった。 ここ最近はデータ分析というよりデータの可視化に力を注いでおり、D3.jsを使って大変スマートな図を描画する術を勉強している私ですが、読み込むデータ(主にcsv)を作る作業も必要なのでその部分は大好きなpython(pandas)を用いて行っている。 ここで俺少年は考えた。Pythonにもmatplotlibという図を描画する有名なパッケージがあるではないか! matplotlibでD3書けないかなー そんなこんなで探してみるとmpld3という便利なパッケージがあった。

mpld3

早速使ってみることにした。まずはmatplotlibで普段通りグラフなりを描画する。

import matplotlib.pyplot as plt, mpld3
import numpy as np

a = np.aragen(20)
plt.plot(a, a**2)
plt.grid()
plt.xlabel('x')
plt.ylabel('y')

次にplt.show()ではなくmpld3.show()とするとデフォルトでlocalhost:8888に図が描画される。  

f:id:h-piiice16:20160329234124g:plain

こんな感じです。gifでキャプチャしてしまった…

Pythonなんでもできちゃうなーすごい(ステマ