torchをeclipseでデバッグ

torchというディープラーニングのライブラリが有ります。Luaで書かれているようであまり馴染みがなかったのですが、論文を読んでいて、サンプルをどうしても動かしたくてデバッグできる環境の構築を行った時のメモです

環境

  • MacOS Seirra 10.12.4
  • eclipse 4.6.3

こちらにubuntuの場合の設定方法があるのですが、Macではちょっと違いました。

luaインストール

brew install lua

これだけです

torchインストール

公式の手順通りにやれば問題なく終了します。

git clone https://github.com/torch/distro.git ~/torch --recursive
cd ~/torch; bash install-deps;
./install.sh

eclipseプラグイン

下記URLからLuaプラグインをインストールします。1.4.1が最新でした
http://download.eclipse.org/ldt/releases/milestones/

eclipseの設定

これが一番ハマりました。

環境設定 > Lua > Interpreters で Addで追加します。

Interpreter typeLua JIT 2.0
Interpreter executable/Users/yourname/torch/install/bin/luajit
Interpreter name Lua JIT
interpreter arguments-lenv -e “io.stdout:setvbuf(‘no’); if os.getenv(‘DEBUG_MODE’) then require ‘debugger’ ; require ‘debugger.plugins.ffi’end”
Linked Execution Environmentlua-5.1

また、Import…で/Users/yourname/torch/install/bin/torch-activateをインポートし環境変数を追加します

実行

こちらのサンプルを動かしてみます。
EclipseでLuaプロジェクトを作成し、srcディレクトリ内にファイルを作成します。
ここでポイントは、ファイルのパスをコード中に記述する際にはプロジェクトのトップからの相対パスを書きます。

download.py


print '==> downloading dataset'

-- Here we download dataset files. 

-- Note: files were converted from their original LUSH format
-- to Torch's internal format.

-- The SVHN dataset contains 3 files:
--    + train: training data
--    + test:  test data

tar = 'http://torch7.s3-website-us-east-1.amazonaws.com/data/mnist.t7.tgz'

if not paths.dirp('mnist.t7') then
   os.execute('wget ' .. tar)
   os.execute('tar xvf ' .. paths.basename(tar))
end

train_file = 'src/mnist.t7/train_32x32.t7'
test_file = 'src/mnist.t7/test_32x32.t7'

----------------------------------------------------------------------
print '==> loading dataset'

-- We load the dataset from disk, it's straightforward

trainData = torch.load(train_file,'ascii')
testData = torch.load(test_file,'ascii')

print('Training Data:')
print(trainData)
print()

print('Test Data:')
print(testData)
print()

----------------------------------------------------------------------
print '==> visualizing data'

-- Visualization is quite easy, using itorch.image().
if itorch then
   print('training data:')
   itorch.image(trainData.data[{ {1,256} }])
   print('test data:')
   itorch.image(testData.data[{ {1,256} }])
end

右クリックのRunで実行できます

Tensorflowのエラー

Tensorflowをバージョンアップすると、昔動いていたスクリプトが動かなくなったりします

    cell = tf.nn.rnn_cell.BasicLSTMCell(size, forget_bias=0.0)
AttributeError: 'module' object has no attribute 'rnn_cell'

こんなエラーとか。

こちらを参照し修正します。

これを

tf.nn.rnn_cell.BasicLSTMCell

これに変更

tf.contrib.rnn.BasicLSTMCell

Maven起動時のエラー

Mavenの起動時にエラーが出たのでメモ

エラーメッセージ

$ mvn package
メイン・クラスorg.codehaus.plexus.classworlds.launcher.Launcherが見つからなかったかロードできませんでした

対応方法

こちらを参考に

$ unset M2_HOME
$ mvn package

omp4jによる並列化

Pythonで並列化させたプログラムを走らせていたのですがあまりの遅さにJavaへと変更した際、並列化をomp4jで簡単にできたのでメモ。

omp4j

OpenMPの説明は、Wikipediaをみてもらうことにして、ソースコード中にコメントを書いておいて、コンパイルをすれば並列化プログラムの出来上がるという便利なライブラリ。

ここからJarファイルをダウンロードします。

wget https://github.com/omp4j/omp4j/releases/download/v1.2/omp4j-1.2.jar

Javaプログラム

簡単なプログラムを作成します。スレッド5で10回計算しています。


import java.util.Random;


public class OmpTest {
        private void run() {
                try {
                        // omp parallel for threadNum(5)
                        for (int i = 0; i < 10; i++) {
                                new Task1(i).call();
                        }

                } finally {
                        System.out.println("ThreadTest:finish");

                }
        }

        static class Task1{
                private int number;
                Task1(int number){
                        this.number=number;

                }
                public Long call()  {
                        System.out.println("Task1.start:"+this.number);
                        long sleep=new Random().nextInt(10)*1000;
                        long sum = 0;
                        for (int i = 1; i <= 100 * 10000; i++) {
                                sum += i;
                        }
                        try{
                                Thread.sleep(sleep);
                        }catch(Exception e){}
                        System.out.println("Task1.end:"+this.number+",sleep="+sleep);
                        return sum;
                }
        }

        public static void main(String[] argv){
                new OmpTest().run();
        }
}

シングルスレッド

普通にコンパイルします。シングルスレッドで動作します。


$ javac OmpTest.java
$ java OmpTest
Task1.start:0
Task1.end:0,sleep=3000
Task1.start:1
Task1.end:1,sleep=2000
Task1.start:2
Task1.end:2,sleep=1000
Task1.start:3
Task1.end:3,sleep=0
Task1.start:4
Task1.end:4,sleep=5000
Task1.start:5
Task1.end:5,sleep=6000
Task1.start:6
Task1.end:6,sleep=9000
Task1.start:7
Task1.end:7,sleep=3000
Task1.start:8
Task1.end:8,sleep=8000
Task1.start:9
Task1.end:9,sleep=2000
ThreadTest:finish

シリアルに計算されているのがわかります。

マルチスレッド

並列化できるようにコンパイルします。


$ java -jar omp4j-1.2.jar OmpTest.java
$ java OmpTest
Task1.start:3
Task1.start:1
Task1.start:2
Task1.start:4
Task1.start:0
Task1.end:1,sleep=0
Task1.start:5
Task1.end:0,sleep=3000
Task1.start:6
Task1.end:2,sleep=3000
Task1.end:5,sleep=3000
Task1.start:7
Task1.start:8
Task1.end:3,sleep=4000
Task1.start:9
Task1.end:4,sleep=7000
Task1.end:9,sleep=3000
Task1.end:6,sleep=8000
Task1.end:8,sleep=8000
Task1.end:7,sleep=9000
ThreadTest:finish

並列に計算できているのがわかります。
実際にはコンパイル時にコードを変換してコンパイルしています。
ここにソースコードを貼り付けると変換後のソースが表示されます。上記サンプルだとエラーになってしまいましたが、簡単なコードならばそのコードが表示されます。

まとめ

簡単にJavaのコードが並列化できます。色々と制約はありますが(変数関連など)、簡単に並列プログラムが作成できるのはメリットでしょう。

SQLiteをPythonからインメモリで使う

SQLite、手軽で便利なデータベースですが激しく使っていると速度が気になる時もあります。

SQLiteはインメモリデータベースもサポートしているので、既存のSQLiteのデータベースからインメモリ化して読み取り専用にすると早くなります。

データベース準備

適当に大きなデータベースを用意します。


#!/bin/env python
# coding:utf-8

import sqlite3

con=sqlite3.connect("test.db")
con.cursor().execute("CREATE TABLE test( key integer, val integer , primary key(key))")
con.commit()


for key in range(1,10000000+1):
  con.cursor().execute("insert into test values(?,?)",(key,key+1,))
con.commit()

1000万レコードのデータベースを作成しました。


$ sqlite3 test.db 
SQLite version 3.7.6.3
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select count(*) from test;
10000000

プログラム

こちらを参考にプログラムを作成します。


#!/bin/env python
# coding:utf-8

import sqlite3
from StringIO import StringIO
import time
import random

# in memory化
con=sqlite3.connect("test.db")
tempfile=StringIO()
for line in con.iterdump():
    tempfile.write("%s\n" % line)
tempfile.seek(0)
mcon=sqlite3.connect(":memory:")
mcon.cursor().executescript(tempfile.read())
mcon.commit()
mcon.row_factory=sqlite3.Row


current_milli_times = lambda: int(round(time.time() * 1000))

print "ready.."
# normal
# select 10000 times
N=10000
nstart=current_milli_times()
for i in range(N):
    key=random.randrange(10000000)
    res=con.cursor().execute("select * from test where key=?",(key,))

nend=current_milli_times()
print "normal:"+str(nend-nstart)


# inmemory
mstart=current_milli_times()
for i in range(N):
    key=random.randrange(10000000)
    res=mcon.cursor().execute("select * from test where key=?",(key,))
mend=current_milli_times()
print "inmemory:"+str(mend-mstart)

conのコネクションが通常のデータベースアクセス、mconがデータベースファイルをインメモリ化したものになります。10000回ランダムにSELECTしてみます。

結果

ready..
normal:414
inmemory:171

大学のスパコンで計算したのですが2倍以上の差が出ました。

Rをソースコードからインストール

スーパーユーザ権限のないサーバにソースコードからインストールしてみたのでそのメモ

大学のサーバなど勝手になんでもインストールできない環境ではローカルのユーザ環境に色々とインストールしないといけません。今回はRをインストールしてみました

Rの取得

cranからRのソースコードをダウンロードしコンパイルします

wget https://cran.r-project.org/src/base/R-3/R-3.3.2.tar.gz
tar zxvfp R-3.3.2.tar.gz
cd R-3.3.2
mkdir builddir
cd builddir
../configure --prefix=/work/$USER/local --with-cairo --with-jpeglib --with-readline --with-tcltk --with-blas --with-lapack --enable-R-profiling --enable-R-shlib --enable-memory-profiling 

エラーになります

checking if bzip2 version >= 1.0.6... no
checking whether bzip2 support suffices... configure: error: bzip2 library and headers are required

足りないライブラリを入れていきます

bzip2

wget http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz
tar zxvfp bzip2-1.0.6.tar.gz
cd bzip2-1.0.6

このあたりを参考にMakefileを修正しておきます。CFLAGSに-fPICを追加します

CFLAGS=-fPIC -Wall -Winline -O2 -g $(BIGFILES)

makeします

make -f Makefile-libbz2_so
make clean
make
make -n install PREFIX=/work/$USER/local
make install PREFIX=/work/$USER/local

Rのconfigを再開します。この際、オプションにライブラリのパスを入れます

../configure --prefix=/work/$USER/local --with-cairo --with-jpeglib --with-readline --with-tcltk --with-blas --with-lapack --enable-R-profiling --enable-R-shlib --enable-memory-profiling CPPFLAGS="-I/work/$USER/local/include" LDFLAGS="-L/work/$USER/local/lib"

またエラーです

checking for lzma_version_number in -llzma... no
configure: error: "liblzma library and headers are required"

xz

xzライブラリを入れます。

wget http://tukaani.org/xz/xz-5.2.3.tar.gz
tar zxvfp xz-5.2.3.tar.gz 
cd xz-5.2.3
./configure --prefix=/work/$USER/local
make install

Rのconfigを再開

../configure --prefix=/work/$USER/local --with-cairo --with-jpeglib --with-readline --with-tcltk --with-blas --with-lapack --enable-R-profiling --enable-R-shlib --enable-memory-profiling CPPFLAGS="-I/work/$USER/local/include" LDFLAGS="-L/work/$USER/local/lib"

またエラー

checking for pcre_fullinfo in -lpcre... no
checking whether PCRE support suffices... configure: error: pcre >= 8.10 library

pcre

pcreライブラリを入れる。ここで、UTF8を有効にしておきます

wget https://ftp.pcre.org/pub/pcre/pcre-8.10.zip
unzip pcre-8.10.zip 
cd pcre-8.10
./configure --prefix=/work/$USER/local/ --enable-utf8
make install

Rのconfigを再開

checking if libcurl is version 7 and >= 7.28.0... no
configure: error: libcurl >= 7.28.0 library and headers are required with support for https

またエラーです

curl

wget --no-check-certificate https://curl.haxx.se/download/curl-7.47.1.tar.gz
tar zxvfp curl-7.47.1.tar.gz 
cd curl-7.47.1
./configure --prefix=/work/$USER/local
make -j3
make install

Rのconfigを再開

../configure --prefix=/work/$USER/local --with-cairo --with-jpeglib --with-readline --with-tcltk --with-blas --with-lapack --enable-R-profiling --enable-R-shlib --enable-memory-profiling CPPFLAGS="-I/work/$USER/local/include" LDFLAGS="-L/work/$USER/local/lib"

成功しました

コンパイル

make

またエラー。。

/work/xxxxx/work/R-3.3.2/builddir/bin/exec/R: /usr/lib64/libgomp.so.1: version `GOMP_4.0' not found (required by /work/xxxxx/work/R-3.3.2/builddir/lib/libR.so)

これは使っているGCCとそのライブラリがずれていたためでした。
LD_LIBRARY_PATHに使っているGCCのライブラリパスを前の方に追加し再度make

make
make install

これでOKです。

RASPBIAN JESSIEでSSH接続

ちょっとはまりました。

RASPBIAN JESSIEの2016-11-25バージョンではデフォルトでSSH接続が外部からできなくなってしまいました。

外部から接続しようとするとこんな感じ

$ ssh -vvv 192.168.11.102 -l pi
OpenSSH_7.2p2, LibreSSL 2.4.1
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 20: Applying options for *
debug2: resolving "192.168.11.102" port 22
debug2: ssh_connect_direct: needpriv 0
debug1: Connecting to 192.168.11.102 [192.168.11.102] port 22.
debug1: connect to address 192.168.11.102 port 22: Connection refused
ssh: connect to host 192.168.11.102 port 22: Connection refused

どうやら仕様変更があったようです
http://downloads.raspberrypi.org/raspbian/release_notes.txt

2016-11-25:
  * SSH disabled by default; can be enabled by creating a file with name "ssh" in boot partition
  * Prompt for password change at boot when SSH enabled with default password unchanged
  * Adobe Flash Player included
  * Updates to hardware video acceleration in Chromium browser
  * Greeter now uses background image from last set in Appearance Settings rather than pi user
  * Updated version of Scratch
  * Rastrack option removed from raspi-config and Raspberry Pi Configuration
  * Ability to disable graphical boot splash screen added to raspi-config and Raspberry Pi Configuration
  * Appearance Settings dialog made tabbed to work better on small screens
  * Raspberry Pi Configuration now requires current password to change password
  * Various small bug fixes
  * Updated firmware and kernel

解決方法はブートパーテーションにsshという名のファイルを作るだけ。

$ cd /boot
$ sudo touch ssh
$ sudo reboot

セキュリティのためとはわかりますが、いきなり塞がれると困ってしまいました。

Rで株価データ取得

Rで株価データの取得のメモ
quantmodは素晴らしい!!

DOW

DowはYahoo.comから取得します。srcに”yahoo”をセット

library(quantmod)

# DOW
dow<-new.env()
dow.name<-getSymbols("DOW",env=dow,src="yahoo", from='2016-01-01',to='2016-06-30')
dow.prices<-dow[[dow.name]]
names(dow.prices)<-c("Open","High","Low","Close","Volume","Adjusted")

デフォルトの名前では使いづらいので、必要なデータを別のデータフレームに入れて名前をつけます。

> dow.prices["2016-02-01::2016-03-01"]
            Open  High   Low Close   Volume Adjusted
2016-02-01 41.58 42.77 41.22 42.58  8717200 41.44578
2016-02-02 44.14 45.18 42.82 45.03 16411000 43.83052
2016-02-03 45.73 47.05 45.70 46.74 16750300 45.49497
2016-02-04 46.93 47.64 46.73 47.39 13177300 46.12765
2016-02-05 47.48 47.50 46.41 46.69  8030600 45.44630
2016-02-08 46.46 46.94 45.20 46.23 13511300 44.99855
2016-02-09 45.71 47.20 45.71 46.60  8201200 45.35870
..

取得するデータはxts型ですので扱いやすいです

日本株

日本株はsrcにyahoojとYahooJapanを指定するだけです

jpn<-new.env()
jpn.name<-getSymbols("6758",env=jpn,src="yahooj", from='2016-01-01',to='2016-06-30')
jpn.prices<-jpn[[jpn.name]]
names(jpn.prices)<-c("Open","High","Low","Close","Volume","Adjusted")

> jpn.prices["2016-02-01::2016-03-01"]
             Open   High    Low  Close   Volume Adjusted
2016-02-01 2923.0 2924.0 2700.0 2836.0 32250000   2836.0
2016-02-02 2779.0 2812.0 2662.0 2692.5 18567800   2692.5
2016-02-03 2626.0 2654.5 2610.0 2623.5 15916000   2623.5
2016-02-04 2600.0 2657.0 2600.0 2620.5 10369200   2620.5
2016-02-05 2592.0 2638.5 2580.5 2615.0  8591500   2615.0
2016-02-08 2560.0 2592.0 2515.0 2569.0 10796100   2569.0
2016-02-09 2424.0 2444.0 2356.5 2388.5 13666800   2388.5

追記 19.06.18


上記のやり方ではどうやらエラーが出るようになりました。

> names(jpn.prices)<-c("Open","High","Low","Close","Volume","Adj")
 names(jpn.prices) <- c("Open", "High", "Low", "Close", "Volume",  でエラー: 
   NULL に対して属性を設定しようとしました 

取得方法がどうやら変わったのでしょうか?
下記のやり方でとれるようです

> library(quantmod)
> env<-getSymbols("9434.T", src="yahooj", from="2018-12-19",auto.assign=F)
> jpn<-as.data.frame(env)
> names(jpn)<-c("Open","High","Low","Close","Volume","Adjusted")
> head(jpn)
           Open High  Low Close    Volume Adjusted
2018-12-19 1463 1464 1282  1282 271497800     1282
2018-12-20 1183 1310 1176  1296 106361400     1296
2018-12-21 1279 1375 1275  1316  65040600     1316
2018-12-25 1307 1320 1240  1271  36914400     1271
2018-12-26 1300 1315 1288  1304  12116500     1304
2018-12-27 1350 1356 1325  1354  19368800     1354

CPLUS_INCLUDE_PATH

Cabochaをローカルにインストールさいのメモ

共用環境だと何かライブラリをインストールする際にも自分のローカルにインストールする必要があります。その際にハマったのでメモ

mecab

cabochaはMecabを使用しますので予めインストールしておきます。

CRF++

まず、ライブラリをインストールします。こちらから最新版をダウンロードします。現在はCRF++-0.58が最新版なのでこちらをダウンロードします。その後インストールします

$ tar xzvfp CRF++-0.58.tar.gz
$ cd CRF++-0.58
$ ./configure --prefix=~/local
$ make
$ make install

環境変数

環境変数を設定しておきます。これを設定しておかないとcabochaのコンパイル時に下記エラーが出ます。

make[1]: Entering directory `~/work/cabocha-0.69'
Making all in src
make[2]: Entering directory `~/work/cabocha-0.69/src'
/bin/sh ../libtool  --tag=CXX   --mode=compile g++ -DHAVE_CONFIG_H -I. -I.. -DCABOCHA_DEFAULT_POSSET="\"IPA"\" -DCABOCHA_DEFAULT_CHARSET="\"EUC-JP"\" -DMODEL_VERSION=102  -DCABOCHA_DEFAULT_RC="\"/work/s1630401/local/etc/cabocharc\""    -O3 -Wno-deprecated -Wall -c -o chunk_learner.lo chunk_learner.cpp
libtool: compile:  g++ -DHAVE_CONFIG_H -I. -I.. -DCABOCHA_DEFAULT_POSSET=\"IPA\" -DCABOCHA_DEFAULT_CHARSET=\"EUC-JP\" -DMODEL_VERSION=102 -DCABOCHA_DEFAULT_RC=\"/work/s1630401/local/etc/cabocharc\" -O3 -Wno-deprecated -Wall -c chunk_learner.cpp  -fPIC -DPIC -o .libs/chunk_learner.o
chunk_learner.cpp:6:19: error: crfpp.h: No such file or directory
In file included from chunk_learner.cpp:13:
chunker.h:24: error: ISO C++ forbids declaration of 'crfpp_model_t' with no type
chunker.h:24: error: expected ';' before '*' token
In file included from chunk_learner.cpp:15:
ne.h:27: error: ISO C++ forbids declaration of 'crfpp_model_t' with no type
ne.h:27: error: expected ';' before '*' token
chunk_learner.cpp: In function 'bool CaboCha::::runChunkingTrainingWithCRFPP(CaboCha::ParserType, const char*, const char*, const char*, CaboCha::CharsetType, CaboCha::PossetType, double, int)':
chunk_learner.cpp:171: error: 'crfpp_learn' was not declared in this scope
make[2]: *** [chunk_learner.lo] Error 1
make[2]: Leaving directory `~/work/cabocha-0.69/src'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `~/work/cabocha-0.69'
make: *** [all] Error 2

環境変数

$ export C_INCLUDE_PATH=~/local/include:$C_INCLUDE_PATH
$ export CPLUS_INCLUDE_PATH=$C_INCLUDE_PATH
$ export LD_LIBRARY_PATH=~/local/lib:$LD_LIBRRY_PATH
$ export PATH=~/local/bin:$PATH

cabocha

次にcabochaをインストールします。こちらから同様に最新版をダウンロードします。現在では0.69です。

$ tar zxvfp cabocha-0.69.tar.gz
$ cd cabocha-0.69
$ ./configure --prefix=~/local 
$ make
$ make install

環境変数は.bashrcなどに入れておくと面倒がなくていいです

shinyでデバッグプリントを出す方法

すぐ忘れるのでメモ

shinyとは

Rの軽量Webフレームワークshiny。Rで計算した結果をWebで簡単に表現できるので非常に便利です。

RStudioを使ってデバッグすればいいのでしょうが、サーバサイドでいきなりコーディングし、訳の分からないエラーが発生した時には非常に困ります。
簡単にデバッグする方法は以下のとおりです

ブラウザ

Chromeのメニューから「その他のツール」ー「デベロッパーツール」を選択します。
そのメニューからConsoleを表示させると、Javascriptでサーバ側のエラーを表示してくれます。
これは非常に便利。

デバッグプリント

ソースコード上にデバッグプリントを埋め込んで変数の内容を確認するには

cat(file=stderr(),"debug=",value)

こんな感じでserver.R上に記述します。これで /var/log/shiny-server以下のファイルに出力されます。

まとめ

Rはスクリプト言語なので、エラーになる直前までは普通に実行してくれますので、エラーとなる直前にデバッグプリントを仕込むと良いでしょう