Rのh2oでエラー対応法

H2Oパッケージを触っていてエラーが出たのでメモ

環境

  • ubuntu14.04
  • R-3.3.1
  • h2o-2.0.1

インストール

まずここを参考にインストールします

cmake

wget https://cmake.org/files/v3.6/cmake-3.6.1.tar.gz
tar zxvfp cmake-3.6.1.tar.gz 
cd cmake-3.6.1
./configure  
make
make install

h2o

wget https://github.com/h2o/h2o/archive/v2.0.1.tar.gz
tar zxvfp v2.0.1.tar.gz 
cd h2o-2.0.1/
cmake .
make
make install

設定

mkdir /usr/local/etc/h2o/
cd /usr/local/etc/h2o/
openssl genrsa 2048 > cert.key
openssl req -new -key cert.key  > cert.csr
openssl x509 -days 3650 -req -signkey cert.key < cert.csr > cert.pem
touch /usr/local/etc/h2o/error-log

起動

sudo /usr/local/bin/h2o -m daemon -c /usr/local/etc/h2o/h2o.conf

サンプル

ここのサンプルを実行してみます

library("h2o")
localH2O <- h2o.init(ip = "localhost", port = 54321, startH2O = TRUE, nthreads=-1)
cfData<-h2o.importFile(localH2O,path="https://raw.githubusercontent.com/ozt-ca/tjo.hatenablog.samples/master/r_samples/public_lib/jp/conflict_sample.txt")

ここでエラー発生

Error: is.character(key) && length(key) == 1L && !is.na(key) is not TRUE

どうやら、h2oの仕様が変わったようです。こちらを参考に修正します

cfData<-h2o.importFile(path="https://raw.githubusercontent.com/ozt-ca/tjo.hatenablog.samples/master/r_samples/public_lib/jp/conflict_sample.txt")
res.err.dl<-rep(0,100)
numlist<-sample(3000,100,replace=F)
for(i in 1:100){
 cf.train <- cfData[-numlist[i],]
 cf.test <- cfData[numlist[i],]
 res.dl <- h2o.deeplearning(x = 1:7, y = 8, data = cf.train, activation = "Tanh",hidden=rep(20,2))
 pred.dl <- h2o.predict(object=res.dl,newdata=cf.test[,-8])

 pred.dl.df <- as.data.frame(pred.dl)
 test.dl.df <- as.data.frame(cf.test)

 res.err.dl[i] <- ifelse(as.character(pred.dl.df[1,1])==as.character(test.dl.df[1,8]),0,1)
 }

またまたエラー

Error in h2o.deeplearning(x = 1:7, y = 8, data = cf.train, activation = "Tanh",  : 
  unused argument (data = cf.train)

仕様をみると、また変わっていました。以下のように修正します

 res.dl <- h2o.deeplearning(x = 1:7, y = 8, training_frame = cf.train, activation = "Tanh",hidden=rep(20,2))

続けます

sum(res.err.dl)

これでうまく実行できました

終了

sudo kill -TERM `cat /usr/local/etc/h2o/pid-file`

仕様がよく変わるので、メジャーバージョンアップ時は要注意です

Word Cloudを使って見る

WordCloudなるライブラリがあるので使ってみました。
自分の環境ではそのままではちょっとうまく動かなかったのでメモです。

こちらを参考にしました。

環境

– MacOS10.11
– python 2.7.12
– mecab 0.996

インストール

brew install python
brew install mecab
brew install mecab-ipadic


git clone https://github.com/amueller/word_cloud
cd word_cloud 
pip install -r requirements.txt
python setup.py install
pip install beautifulsoup4
pip install requests

エラー

こちらのサンプルをそのまま実行するとエラーが出ます

/usr/local/lib/python2.7/site-packages/bs4/__init__.py:181: UserWarning: No parser was explicitly specified, so I'm using the best available HTML parser for this system ("html.parser"). This usually isn't a problem, but if you run this code on another system, or in a different virtual environment, it may use a different parser and behave differently.

The code that caused this warning is on line 53 of the file word_cloud.py. To get rid of this warning, change code that looks like this:

 BeautifulSoup([your markup])

to this:

 BeautifulSoup([your markup], "html.parser")

  markup_type=markup_type))
Traceback (most recent call last):
  File "word_cloud.py", line 53, in 
    wordlist = get_wordlist_from_QiitaURL(url)
  File "word_cloud.py", line 30, in get_wordlist_from_QiitaURL
    return mecab_analysis(text)
  File "word_cloud.py", line 10, in mecab_analysis
    t = mc.Tagger('-Ochasen -d /usr/local/Cellar/mecab/0.996/lib/mecab/dic/mecab-ipadic-neologd/')
  File "/usr/local/lib/python2.7/site-packages/MeCab.py", line 307, in __init__
    this = _MeCab.new_Tagger(*args)
RuntimeError

HTMLパーサーを明示的に入れます

    soup = BeautifulSoup(res.text,"html.parser")

そのまま実行するとまたまたエラー

Traceback (most recent call last):
  File "word_cloud.py", line 59, in 
    create_wordcloud(" ".join(wordlist).decode('utf-8'))
  File "word_cloud.py", line 50, in create_wordcloud
    stopwords=set(stop_words)).generate(text)
  File "/usr/local/lib/python2.7/site-packages/wordcloud-1.2.1-py2.7-macosx-10.11-x86_64.egg/wordcloud/wordcloud.py", line 463, in generate
    return self.generate_from_text(text)
  File "/usr/local/lib/python2.7/site-packages/wordcloud-1.2.1-py2.7-macosx-10.11-x86_64.egg/wordcloud/wordcloud.py", line 448, in generate_from_text
    words = self.process_text(text)
  File "/usr/local/lib/python2.7/site-packages/wordcloud-1.2.1-py2.7-macosx-10.11-x86_64.egg/wordcloud/wordcloud.py", line 391, in process_text
    self.stopwords_lower_ = set(map(str.lower, self.stopwords))
TypeError: descriptor 'lower' requires a 'str' object but received a 'unicode'

どうもUnicodeがらみのエラーです。stop_wordsのUnicode変換がうまくいっていないようなので普通の文字列にします

コード修正

自分の環境に合わせていじります

#!/bin/env python
# coding:utf-8
#%matplotlib inline
import urllib2
from bs4 import BeautifulSoup

import matplotlib.pyplot as plt
from wordcloud import WordCloud
from bs4 import BeautifulSoup
import requests
import MeCab as mc



def mecab_analysis(text):
    t = mc.Tagger('-Ochasen -d /usr/local/Cellar/mecab/0.996/lib/mecab/dic/ipadic/')
    enc_text = text.encode('utf-8')
    node = t.parseToNode(enc_text)
    output = []
    while(node):
        if node.surface != "":  # ヘッダとフッタを除外
            word_type = node.feature.split(",")[0]
            if word_type in ["形容詞", "動詞","名詞", "副詞"]:
                output.append(node.surface)
        node = node.next
        if node is None:
            break
    return output


def get_wordlist_from_QiitaURL(url):
    res = requests.get(url)
    soup = BeautifulSoup(res.text,"html.parser")

    text = soup.body.section.get_text().replace('\n','').replace('\t','')
    return mecab_analysis(text)

def create_wordcloud(text):

    # 環境に合わせてフォントのパスを指定する。
    #fpath = "/System/Library/Fonts/HelveticaNeue-UltraLight.otf"
    #fpath = "/Library/Fonts/ヒラギノ角ゴ Pro W3.otf"
    fpath = "/Library/Fonts/Osaka.ttf"

    # ストップワードの設定
    #stop_words = [ u'てる', u'いる', u'なる', u'れる', u'する', u'ある', u'こと
', u'これ', u'さん', u'して', u'くれる', u'やる', u'くださる', u'そう', u'せる', u'した',  u'思う',  u'それ', u'ここ', u'ちゃん', u'くん', u'', u'て',u'に',u'を
',u'は',u'の', u'が', u'と', u'た', u'し', u'で', u'ない', u'も', u'な', u'い', u'か', u'ので', u'よう', u'']
    stop_words = [ 'てる', 'いる', 'なる', 'れる', 'する', 'ある', 'こと', 'これ
', 'さん', 'して', 'くれる', 'やる', 'くださる', 'そう', 'せる', 'した',  '思う',  'それ', 'ここ', 'ちゃん', 'くん', '', 'て','に','を','は','の', 'が', 'と', 'た', 'し', 'で', 'ない', 'も', 'な', 'い', 'か', 'ので', 'よう', '']

    wordcloud = WordCloud(background_color="white",font_path=fpath, width=900, height=500, \
                          stopwords=set(stop_words)).generate(text)

    plt.figure(figsize=(15,12))
    plt.imshow(wordcloud)
    plt.axis("off")
    plt.show()

url = "http://qiita.com/t_saeko/items/2b475b8657c826abc114"
wordlist = get_wordlist_from_QiitaURL(url)
create_wordcloud(" ".join(wordlist).decode('utf-8'))

実行

python word_cloud.py

これで画像が表示されます

CentOS5にbzip2-1.0.6をインストール

未だCentOS5を使っているといろいろと不都合が生じてきます。まず、最新のアプリケーションを使おうとすると、デフォルトで入っているライブラリ群が古く全くインストールできません。

今回はCentOS5.11にbzip2-1.0.6をインストールしてみます

ダウンロード

$ cd /usr/local/src
$ wget http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz
$ tar xzvfp  bzip2-1.0.6.tar.gz
$ cd bzip2-1.0.6

コンパイル

シェアードライブラリも同時にコンパイルします
まずは本体

$ make
# make install

次にシェアードライブラリ

$ make -f Makefile-libbz2_so 
$ make
gcc -shared -Wl,-soname -Wl,libbz2.so.1.0 -o libbz2.so.1.0.6 blocksort.o huffman.o crctable.o randtable.o compress.o decompress.o bzlib.o
/usr/bin/ld: blocksort.o: relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
blocksort.o: could not read symbols: Bad value
collect2: ld はステータス 1 で終了しました
make: *** [all] エラー 1

ここでエラーが

解決方法

どうもfPICをつけてコンパイルしないとダメなようです
本体側も修正、Makefileを修正します

CFLAGS=-Wall -Winline -O2 -g $(BIGFILES) -fPIC  # -fPICを追加
CXXFLAGS=-fPIC   # 行追加

コンパイル

$ make clean
$ make
# make install

次にシェアードライブラリ。Makefile-libbz2_soを修正

CXXFLAGS=-fPIC # 行追加

コンパイル

$ make -f Makefile-libbz2_so 
# mv libbz2.so.1.0* /usr/local/lib

Rでword2vec

こちらを参考にRでWord2Vecを実行してみたが、ちょっとハマったのでメモ

パッケージインストール

必要なパッケージをインストールします

install.packages("devtools")
library(devtools)
install.packages("tsne")
install.packages("magrittr")
install.packages("stringi")
library(tsne)
library(magrittr)
library(stringi)
devtools::install_github("bmschmidt/wordVectors")

データ作成

青空文庫から夏目漱石の三四郎をテストデータとします

$ wget http://www.aozora.gr.jp/cards/000148/files/794_ruby_4237.zip
$ unzip 794_ruby_4237.zip
$ nkf -w  --overwrite sanshiro.txt
$ mecab -Owakati sanshiro.txt -o data.txt

UTF8へ文字コードを変換しておきます。ちなみにmecabはUTF8のものをインストールしておいてください

R実行

Rから実行します

library(devtools)
library(wordVectors)
library(magrittr)
library(tsne)
library(magrittr)
wordVectors::train_word2vec(
  train_file = "data.txt", output_file = "model.txt",
  vectors = 200, window = 10,
  threads = 3
)

threadsはCPU数−1あたりで設定します
これを実行すると

 type.convert(data[[i]], as.is = as.is[i], dec = dec, numerals = numerals,  でエラー: 
   '(;;{ֺ3:q9<9a><99>
8(c<91>:' に不正なマルチバイト文字があります 追加情報: 警告メッセージ: 1: utils::read.table(filename, header = F, skip = 1, colClasses = c("character", で: line 1 appears to contain embedded nulls 2: utils::read.table(filename, header = F, skip = 1, colClasses = c("character", で: line 2 appears to contain embedded nulls 3: utils::read.table(filename, header = F, skip = 1, colClasses = c("character", で: line 3 appears to contain embedded nulls 4: utils::read.table(filename, header = F, skip = 1, colClasses = c("character", で: line 4 appears to contain embedded nulls 5: utils::read.table(filename, header = F, skip = 1, colClasses = c("character", で: line 5 appears to contain embedded nulls 6: utils::read.table(filename, header = F, skip = 1, nrows = 1, で: line 1 appears to contain embedded nulls

このようなエラーが出ます
この場合には気にせずRで

word2vec_model <- read.vectors("model.txt",binary=TRUE)

これで読み込み直してやります。

確認

> nearest_to(word2vec_model,word2vec_model[["三四郎"]])
      三四郎       与次郎       じっと           秋     ますます         勇気     見合わせ     おかしく           次 
3.330669e-16 4.131871e-01 4.873280e-01 4.886600e-01 4.895344e-01 4.948309e-01 5.033392e-01 5.220245e-01 5.278047e-01 
      腹の中 
5.329964e-01 
> nearest_to(word2vec_model,word2vec_model[["東京"]])
        東京       生まれ     これから       ずっと         変る         おれ       いなか         うえ       いっそ 
5.551115e-16 3.663971e-01 3.754231e-01 3.864140e-01 4.024397e-01 4.056571e-01 4.078920e-01 4.080678e-01 4.103215e-01 
    文芸時評 
4.340431e-01 

ま、こんなもんです

ubuntu14.04へRの最新版をapt-getでインストール

ubuntu14.04にapt−getでインストールできるRのバージョンは3.0.2とちょっと古いです。
最新版をインストールするには以下のようにします

$ sudo echo "deb http://cran.rstudio.com/bin/linux/ubuntu trusty/" >> /etc/apt/sources.list
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9
$ sudo add-apt-repository ppa:marutter/rdev
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install r-base

PROXY環境下の場合には

export http_proxy="http://server:port/"

の環境変数を入れる必要があります

ここを参考にしました

RSRubyの使い方

よく忘れるのでメモ

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

require  "rsruby"
require "rsruby/dataframe"

r=RSRuby.instance
r.class_table["data.frame"]=lambda{|x| DataFrame.new(x)}
RSRuby.set_default_mode(RSRuby::CLASS_CONVERSION)

x=[1,2,3]
y=[2,4,6]
df=r.as_data_frame(:x=>{'x'=>x,'y'=>y})
r.assign('df',df)
res=r.eval_R(<

CentOS5.11へgcc-4.8.5をインストール

たまたま余っていたCentOS5.11のサーバにpython2.7.12をインストールし、pylabをインストールしようとするとエラー。

 error: ‘SOCK_CLOEXEC’ was not declared in this scope
    error: command 'gcc' failed with exit status 1

どうもOSが古いと色々問題があります。

そこでこちらを参考にGCCをインストールします

ダウンロード

以下のサイトからダウンロードします。とりあえず最新版をダウンロードしました。

コンパイル

# mkdir /usr/local/gcc-4.8.5
# export LD_LIBRARY_PATH=/usr/local/gcc-4.8.5/lib:$LD_LIBRARY_PATH
# bunzip2 gmp-6.1.1.tar.bz2 
# tar xvfp gmp-6.1.1.tar
# cd gmp-6.1.1
# ./configure --prefix=/usr/local/gcc-4.8.5
# make && make install
# xz mpfr-3.1.4.tar.xz 
# cd mpfr-3.1.4
# ./configure --prefix=/usr/local/gcc-4.8.5 --with-gpm=/usr/local/gcc-4.8.5
# make && make install
# tar zxvfp mpc-1.0.3.tar.gz 
# cd mpc-1.0.3
# ./configure --prefix=/usr/local/gcc-4.8.5 --with-gmp=/usr/local/gcc-4.8.5 --with-mpfr=/usr/local/gcc-4.8.5
# make && make install
# tar zxvfp gcc-4.8.5.tar.gz 
# cd gcc-4.8.5
# ./configure --prefix=/usr/local/gcc-4.8.5 --enable-checking=release --with-gpm=/usr/local/gcc-4.8.5 --with-mpfr=/usr/local/gcc-4.8.5 --with-mpc=/usr/local/gcc-4.8.5 --enable-languages=c,c++
# make && make install

環境設定

使う際には、環境変数に入れて使い分けます

$ export LD_LIBRARY_PATH=/usr/local/gcc/lib:/usr/local/gcc/lib64:$LD_LIBRARY_PATH
$ export PATH=/usr/local/gcc/bin:$PATH
$ alias gcc="gcc-4.8.5"
$ alias g++="g++-4.8.5"

RでLDA

自分用メモ

こちらのRでLDAのサンプルがありますが、うまく動かなかったので修正メモ

環境

  • MacOS10.11
  • RStudio 0.99.484
  • R version 3.3.0

エラー

こちらのスクリプトを順番に実行していくと

# ggplotで可視化
ggplot(topic.proportions.df, aes(x=topic, y=value, fill=document)) + geom_bar() + facet_wrap(~ document, ncol=N) + coord_flip()

この部分で以下のエラーが出ます

 eval(expr, envir, enclos) でエラー:  オブジェクト 'topic' がありません 

以下のように修正します

# ggplotで可視化
ggplot(topic.proportions.df, aes(x=variable, y=value, fill=document)) + geom_bar() + facet_wrap(~ document, ncol=N) + coord_flip()

次はこのエラーです

 エラー: stat_count() must not be used with a y aesthetic.

ここを参考に修正します

修正スクリプト

# coraデータの読み込み(2410の科学記事のデータセット。LISTで2410成分ある)
data(cora.documents)
head(cora.documents, n = 2)

# 科学記事で使われているユニーク単語(2910個)のベクトル
data(cora.vocab)
head(cora.vocab)

# 科学記事で使われているタイトル(2410個)のベクトル
data(cora.titles)
head(cora.titles)

# 分析データの作成(トリッキーな参照をしているので注意)
# 1列目がcora.documentsの第一成分で使われる単語のリスト、2列目がその出現回数
data_cora <- as.data.frame(cbind(cora.vocab[cora.documents[[1]][1, ] + 1], cora.documents[[1]][2,]))
# coreの1番目の記事はこれらの単語とその出現回数で構成されていることが分かる。
head(data_cora)

### LDA
# 推定するトピック数の設定
k <- 10

# ldaパッケージはギブスサンプラーでやるようです。
# ギブスサンプラーの中でも3つくらいmethodがあるようです。
result <- lda.collapsed.gibbs.sampler(cora.documents, 
                                      k,
                                      cora.vocab,
                                      25,  # 繰り返し数
                                      0.1, # ディリクレ過程のハイパーパラメータα
                                      0.1, # ディリクレ過程のハイパーパラメータη
                                      compute.log.likelihood=TRUE)

# サマリを見ると、10成分のリストで構成されている。
# assignments:文書Dと同じ長さのリスト。値は単語が割り当てられたトピックNoを示す。
# topic:k × vの行列。値はそのトピックに出現する単語数を表す。
# topic_sums:それぞれのトピックに割り当てられた単語の合計数
# document_sums:k × Dの行列。割り振られたトピックにおける一文章内の単語数を示す。
summary(result)

# 各クラスターでの上位キーワードを抽出する
# 例は各トピックにおける上位3位の単語の行列。
top.words <- top.topic.words(result$topics, 3, by.score=TRUE)
top.words

# 最初の3記事だけトピック割合を抽出してみる
N <- 3
topic.proportions <- t(result$document_sums) / colSums(result$document_sums)
topic.proportions <- topic.proportions[1:N, ]
topic.proportions[is.na(topic.proportions)] <-  1 / k

# 上位3番までのトップワードを用いて列名をつけて、意味付けを行う。
colnames(topic.proportions) <- apply(top.words, 2, paste, collapse=" ")
par(mar=c(5, 14, 2, 2))
barplot(topic.proportions, beside=TRUE, horiz=TRUE, las=1, xlab="proportion")


###
# ggplotで可視化するために、meltを駆使してデータを作成(トリッキーなので注意)
topic.proportions.df <- melt(cbind(data.frame(topic.proportions), document=factor(1:N)), variable.name="topic", id.vars = "document")

# ggplotで可視化  この部分がうまく動かないので修正
#http://tutorials.iq.harvard.edu/R/Rgraphics/Rgraphics.html
ggplot(topic.proportions.df, aes(x=variable, y=value, fill=document)) + geom_bar(stat="identity") + facet_wrap(~ document, ncol=N) + coord_flip()

# 予測はこんな感じ
predictions <- predictive.distribution(result$document_sums[,1:2], result$topics, 0.1, 0.1)
top.topic.words(t(predictions), 5)


まとめ

Rのパッケージは時々仕様が変わってしまいますので自分でコードを修正する必要があります。