rubyのtest/unitを失敗ケースがあっても続けたい!

今回はrubyのテストツール?であるtest/unitについて使っていて不便だと感じた点があったので、まとめました。

私はある業務で、「テストケースをどれくらい網羅しているのか」を測定し、精度を図りたいことがありました。
その時にこのtest/unitを使ったのですが、test/unitでは、テストケースで「失敗」してしまうとそこで処理が中断してしまします。
そのため、それ以降に書いたテストは実行されません。
そうすると、トータルで何回成功して、何回失敗したのかはわかりません。

そこで調べてみると、失敗した際にはrubyの方で例外処理扱いされているようなので、その部分をrescueして、その際にあるインスタンス変数のカウントを1加えるというようにすることにしました。

@failures_num= 0
begin
  assert_equal テスト内容	
rescue => e
  @failures_num = @failures_num + 1
end				

何かの参考になれば幸いです

Mysql2::Error: MySQL client is not connected: ROLLBACKを解消した話

今回題名の通り「Mysql2::Error: MySQL client is not connected: ROLLBACK」というエラーがなかなか消えなかったので、その対処法をメモしておきます。
原因1:時間切れ
1つ目の原因として考えられるのが「タイムアウトしてしまった」という場合です。
その場合はタイムアウトする時間を指定してあげましょう。
MySQLには「innodb_lock_wait_timeout」というものがあり、ここでタイムアウトの時間を指定してあげることができます。
指定の方法(mac)は、
1、ターミナルでMySQLにログインする
2、以下のコマンドを実行

SET GLOBAL innodb_lock_wait_timeout = 数値

以上です。ここの数値に入れた値が反映されます。
確認の方法は
1、ターミナルでMySQLにログインする
2、以下のコマンドを実行

SHOW VARIABLES LIKE 'innodb_lock_wait_timeout';

Variable_nameValue
innodb_lock_wait_timeout28800
以上です。

原因2:パケットのサイズによるもの
2つ目の原因として考えられるのが「いれようとするデータ容量が大きすぎる」という場合です。
この場合は、入れられるデータ容量の最大値を指定してあげましょう。
MySQLには「max_allowed_packet」というものがあり、ここでデータ容量の最大値を指定してあげることができます。
指定の方法(mac)は、
1、ターミナルでMySQLにログインする
2、以下のコマンドを実行

SET GLOBAL max_allowed_packet = 数値;

以上です。ここの数値に入れた値が反映されます。
確認の方法は
1、ターミナルでMySQLにログインする
2、以下のコマンドを実行

SHOW VARIABLES LIKE 'max_allowed_packet';

Variable_nameValue
max_allowed_packet4194304

私は、この二つの方法を実装したところ無事解決しました。(もしかしたら後半だけだったかもしれない・・・)

参考までに

スマホ対応のWebページを作ってみる2

前回に引き続き行き詰まったところのメモをする。

1、動的に生成した要素は要素であって要素でない
 jQueryなどで動的に要素を書き込むと、document.getElementsByClassNameなどでアクセスした時に「そんなものはない」と言われることがあります。なので、その要素がクリックされたら、と言うイベントを設定してもうまく動かない時があります(実際動きませんでした)。

2、SVGで超簡単に折れ線グラフを書いてみる
 SVGでグラフを書くのは一見難しそうですが、単純なものなら一瞬でかけます。

<svg width='200px' height='200px'>
  <polyline points='0,113.61 40,185.6 80,77.61 120,131.62 160,41.54 200,23.54' stroke='red' stroke-width='1' fill='none' />
</svg>

 これで終わりです。svg自体の大きさを指定して、その後に、座標を指定するだけで簡単に描画できるのです。

スマホ対応のWebページを作ってみる

今までwebアプリケーションは何度か作ってみたことはあったが、スマホ用のものは作ったことがなかった。
今後も作る機会があると思うので、ここに気づいたことをまとめておこうと思う。

1.viewportの設定
 まずスマホに対応させるために一番最初に行ったことがviewportの設定である。
qiita.com
細かいことはここに書いてあるみたいだが結局のところ以下のように宣言しておけばいいらしい。

<meta content="width=device-width, initial-scale=1.0" name="viewport">


2.bootstrapを使う
 webアプリを使う時に私の中で必須なのがこのbootstrapである。全く労力をかけずにそれなりのデザインができるのでお勧めである。導入の方法は簡単で、公式ページからbootstrapをダウンロードして、自分のディレクトリに移し、呼び出してあげるだけである。
http://getbootstrap.com/
 bootstrapは、あらかじめCSSが書かれているものにid名やクラス名を合わせることでスタイルを適応させるというものである。「bootstrap table」と検索すればどのようにクラス名をつければいいデザインになるかわかったりする。

3.スーパーリロード
 まあ、これはローカルにサーバーを立ててる時に起こりやすいことなんだけど、cssを書き換えてもサーバーにキャッシュされてしまって更新しても変更が反映されないことがある。そんな時はこのスーパーリロードである。キャッシュとかもの含め更新してくれるので、cssの変更がきちんと反映される。
Mac+chromeの場合は「Ctrl+更新ボタン」である。ブラウザとOSによって異なるので詳しいことはこれを見ると良い。
www.netyasun.com

とりあえず今回はこんなところかな。

rubyでのスクレイピングはCapybaraに決まり2

では、早速Capybaraを使うための準備をしたいと思います。
今回は
rubyはバージョン2.2.5
Bundlerはバージョン1.13.6
を使って説明します。

準備

動くようにするためには以下のサイトを参考にしました
qiita.com
とりあえずこのサイトの言われる通りにしましょう。
以下のコマンドを実行

brew install phantomjs

Gemファイルを作成(今の作業ディレクトリに「Gemfile」というものを作りそこに書き込みます。)

gem 'nokogiri'
gem 'poltergeist'
gem 'capybara'

これで準備は完了です。
rubyのバージョンが古いとうまくいかない可能性が高いです。

とりあえず動かしてみよう

では早速Capybaraを使っていきましょう。
まずはこのコードをコピペして適当なファイル名をつけて保存してください。
test.rb

require 'bundler/setup'
require 'capybara/poltergeist'
Bundler.require

Capybara.register_driver :poltergeist do |app|
  Capybara::Poltergeist::Driver.new(app, {:js_errors => false, :timeout => 100 })
end
session = Capybara::Session.new(:poltergeist)
session.visit "http://www.yahoo.co.jp/"
puts session.title

そして、試しに実行してみましょう。

Yahoo! JAPAN

これが出たら成功です。
これが最小限のサンプルです。タイトルを取るだけならNokogiriでもできます。あくまで動作確認のためのサンプルです。
次回はログインが必要なサイトにログインして、その中のデータを取ってきたいと思います。

rubyでのスクレイピングはCapybaraに決まり

今回は、rubyスクレイピングを行う際におそらく最強(わたし的に)だと考えているCapybaraについて紹介します。

そもそもCapybaraとは

Capybaraは、本来はWebページのテストを行うためのツールです。
そのため、「フォームに値を入れて、あるボタンをクリックしたら」といったGUI的な観点でwebページを遷移させることができます。(そういうメソッドがあります。)
今までURLをひたすらたどっていたスクレイピングとは根本から違います。

Capybaraの何がすごいの?

先ほども話しましたが、従来のスクレイピングではURLがすべてでした。
Mechanizeを使えばログイン後のページを取得したりもできましたがJSが動かないなどの問題もありました。
しかし、このCapybaraではログインというのもクリック操作でできてしまうため裏でJSが動いていたとしても問題ないのです。
本当にすごい。
まあ、こんなに熱く語ってもスクレイピング自体をやったことがない人には伝わらないんでしょうけど。。。

Capybaraのデメリット

一応デメリットもあります。それは速度の遅さです。NokogiriやMechanizeのスクレイピングではsleepを挟まなければいけないほど早かったですが、Capybaraは標準で2秒間のインターバルを置くので遅いです。
そのため、簡単なスクレイピングでは用いらないのが常識です。

次回以降使い方などを紹介していこうと思います。

【初心者が1時間で】Rubyでsvmを用いた機械学習プログラムを作ってみる

今回は、rubysvmを用いた機械学習プログラムについてまとめます。

私のもっていた知識

私が機械学習という言葉を聞いたのはつい最近で、色々な文献を見て回りましたがイマイチ理解しきれませんでした。
というのも、ある程度わかったつもりになっていてもそれを実際に動かすことができなかったからです。
今回扱ったsvmもその一つです。文献を読んだ感じでは、
「多くのデータを与えることでデータの境界線を自動で引いてくれて、それを元に分類をしてくれるもの」
みたいな感じかな?という理解でした。
そして、どの文献を読んでも「理屈は難しいが動かせばわかる」と書いてあって「だから、動かせないんだよ!」って思ってました。
そこで、とりあえずどんなに小さいものでもいいから動かせるようにしたいと思い、どうにかしてruby機械学習(今回はsvmを用いた分類)を行うようなプログラムを動かせるようになったのでどのような準備をしたのかから詳しくまとめたいと思います。 

準備するもの

まずはrubysvmを用いた機械学習プログラムを作る上で必要となるものの準備を行います。
今回、私はMacでこの作業を進めました。
libsvm
・liblinear
この二つのインストールには
http://blog.tsuda.me/computer/2013/05/19/ruby-svm/
このサイトを参考にしました。
一応コマンドだけ抜粋すると

libsvmのインストール

brew install libsvm
gem install libsvm-ruby-swig

・liblinearのインストール

brew install liblinear
gem install liblinear-ruby-swig

これで、

require 'svm'

をすればsvmが使えるようになります。

まず準備が完了です。
ここから実際にコードを動かすことをしていきます。

実際に動かす

今回一番最初に動かしたコードがこちらです。
sample.rb----------------

require 'svm'
class SvmKlass
def train
prob = Problem.new([1,-1],[[1,0,1],[-1,0,-1]])
params = Parameter.new(:kernel_type => RBF, :C => 10)
m = Model.new(prob,params)
m.save("svm.model")
end

def test
m = Model.new("svm.model")
res = m.predict([0,0,-1])
puts res
end
end

svm = SvmKlass.new
svm.train
svm.test
                                            • -

http://hongo35.hatenablog.com/entry/2013/08/04/133348より引用
なんとなくですが、trainの部分で学習して、それを元にtestで予測のテストをしているのがわかると思います。
実際、
prob = Problem.new([1,-1],[[1,0,1],[-1,0,-1]])
この行で行っていることは
prob = Problem.new([データAに対する答え,データBに対する答え],[[データA],[データB]])
このような形で教師データを与えているのです。
と言ってもこのサンプルは3次元なのでよくわからなかったので、こんな感じに書き換えました。
sample.rb----------------

require 'svm'
class SvmKlass
def train
prob = Problem.new([1,-1],[[1,1],[-1,-1]])
params = Parameter.new(:kernel_type => RBF, :C => 10)
m = Model.new(prob,params)
m.save("svm.model")
end

def test
m = Model.new("svm.model")
res = m.predict([0,1])
puts res
end
end

svm = SvmKlass.new
svm.train
svm.test
                                            • -

これで以下のような感じの線が引かれてるイメージになります。
f:id:mr-itaya-magic:20161109202645p:plain
あくまでイメージなのでこのようなグラフは描画されません。
この線に対して上の部分が「1」、下の部分が「-1」というように分類されます。
試しに0,1という点について分類させると「1」という結果が返ってきたと思います。
これが一番簡単なsvmを用いた分類を行うプログラムです。

教師データを増やすと、この境界線が変わっていくことがわかると思います。
興味がある方は細かくデータを変え、予測させるデータを変えるとわかると思います。
今回は分かりやすくするために、2値の分類(1と-1)を行いましたが、データの与え方さえ変えれば3値の分類もできます。

以上です。