機械学習(1)TensorFlowをMacにインストールする

TensorFlowは、Googleが開発し公開している機械学習ライブラリ。

インストール方法

Pythonパッケージ管理ツール「easy_install」を使うとよいとのことなので、以下のコマンドを実行。このとき、XCodeのコマンドラインツールのインストールも求められる。

sudo easy_install pip
sudo easy_install --upgrade six
sudo pip install --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.8.0-py3-none-any.whl

tensorflow-0.8.0-py3-none-any.whl is not a supported wheel on this platform.

TensorFlowを入れるためにはpip3(python3)が必要とのこと。
brewからpython3のインストールを行う。

このときpythonのバージョン管理を行うことのできるpyenvを入れておくと、Python2.7とPython3を切り替えることができるので便利。

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install pyenv

現在のPythonバージョンを確認することができる。

pyenv versions
* system (set by /Users/***/.pyenv/version)

まだ何も入れていないので、systemのみ。

ここで、~/.profileファイル(ログイン時に読み込むbash設定)に以下を追加。
設定を読み込ませるためにOS再起動。

vi ~/.profile

export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init -)"

インストール可能なバージョンを確認して、Python3(今回は3.5.1)をインストール。

pyenv install --list
pyenv install 3.5.1

使用するPythonのバージョンを3.5.1に変更。

pyenv global 3.5.1
pyenv versions
  system
* 3.5.1 (set by /Users/eiji/.pyenv/version)

このときにもし以下のようなエラーが発生する場合は…

Downloading Python-3.5.1.tgz...
-> https://www.python.org/ftp/python/3.5.1/Python-3.5.1.tgz
Installing Python-3.5.1...

BUILD FAILED (OS X 10.11.4 using python-build 20160130)

Inspect or clean up the working tree at /var/folders/my/txp4p33n1lzf2hbzp0vmqbc40000gn/T/python-build.20160515224141.3027
Results logged to /var/folders/my/txp4p33n1lzf2hbzp0vmqbc40000gn/T/python-build.20160515224141.3027.log

Last 10 log lines:
  File "/private/var/folders/my/txp4p33n1lzf2hbzp0vmqbc40000gn/T/python-build.20160515224141.3027/Python-3.5.1/Lib/ensurepip/__main__.py", line 4, in <module>
    ensurepip._main()
  File "/private/var/folders/my/txp4p33n1lzf2hbzp0vmqbc40000gn/T/python-build.20160515224141.3027/Python-3.5.1/Lib/ensurepip/__init__.py", line 209, in _main
    default_pip=args.default_pip,
  File "/private/var/folders/my/txp4p33n1lzf2hbzp0vmqbc40000gn/T/python-build.20160515224141.3027/Python-3.5.1/Lib/ensurepip/__init__.py", line 116, in bootstrap
    _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
  File "/private/var/folders/my/txp4p33n1lzf2hbzp0vmqbc40000gn/T/python-build.20160515224141.3027/Python-3.5.1/Lib/ensurepip/__init__.py", line 40, in _run_pip
    import pip
zipimport.ZipImportError: can't decompress data; zlib not available
make: *** [install] Error 1

XCodeのコマンドラインツールもインストールする。

xcode-select --install

最後に、TensorFlowをインストール。

sudo pip3 install --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.8.0-py3-none-any.whl

インストールされたかどうかの確認は、以下のコマンドを打ってエラーが発生しないことを確認する。

python

Python 3.5.1 (default, May 15 2016, 09:29:31) 
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

import tensorflow as tf 

PHPプログラムをデーモン起動する(CentOS)

PHPで作成したプログラムをデーモン化しサービス起動させる場合には、デーモン化対応した「PHPプログラム」とそれを起動する「起動スクリプト」の2種類を用意する必要がある。

PHPプログラム

PHPプログラムでは、まず自プロセスをfork/execし端末から切り離し、実行中のプログラムをPIDファイルに書き込む。そのあと自分のプロセスをセッションリーダに指定する処理を行う。

<?php
// pid fileの生成
$pidfile = "/var/run/hoged/hoged.pid";
// 全てのエラー出力をOFF
error_reporting(0);
// 子プロセスの生成
$pid = pcntl_fork();
if($pid < 0){
        // 失敗時
        exit();
}else if($pid){
        // 親プロセスの終了
        exit();
}else{
        // pidファイルを生成
        $pid = getmypid();
        $fp = fopen($pidfile, "w");
        @fwrite( $fp, $pid, strlen($pid) );
        fclose($fp);
        // 現在のプロセスをセッションリーダにする
        $sid = posix_setsid();
        if($sid<0){
                // 失敗時
                exit();
        }
        // ループ処理
        while(TRUE){
                //////////////////////////
                //      定期処理       //
                /////////////////////////
        }
}
?>

起動スクリプト

起動スクリプトは、/etc/rc.d/init.dに設置される各デーモンの起動や終了を行うスクリプトである。/etc/init.d/skeletonもしくは/usr/share/doc/initscripts-*/sysvinitfilesにサンプルが存在する。スクリプト内chkconfigの欄は、RunLevel, 起動時のPriority, 終了時のPriorityの順に記述する。PIDを置くディレクトリは事前にmkdirしておく必要がある。

#!/bin/bash
#
# hoged                Startup script for the Hoge System
#
# chkconfig: 345 99 01
# descroption: The Hoge System.
# processname: hoged
#

# Source function library.
. /etc/init.d/functions

# Path to the script
hoged=/home/hoge/hoged.php
prog=hoged
pidfile=${PIDFILE-/var/run/hoged/hoged.pid}
lockfile=${LOCKFILE-/var/lock/subsys/hoged}
RETVAL=0

start() {
        if [ -f $lockfile ]; then
        echo "$prog is Started"
        exit 1
        fi

        echo -n "Starting $prog: "
        daemon --pidfile=${pidfile} --user hoge php $hoged
        RETVAL=$?
        echo
        [ $RETVAL = 0 ] && touch ${lockfile}
        return $RETVAL
}       

stop() {
        echo -n "Shutting down $prog: "
        killproc -p ${pidfile} $hoged
        RETVAL=$?
        echo
        [ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    status)
        status -p ${pidfile} $hoged
        RETVAL=$?
        ;;
    restart)
        stop
            start
        ;;
    *)
        echo "Usage: $prog {start|stop|status}"
        exit 1
        ;;
esac
exit $RETVAL

Pythonプログラムをデーモン起動する(Raspbian)

Pythonで実装したプログラムを、Raspberry Pi(Raspbian)でデーモン起動させるときのメモ。

python-daemonのインストール

python-daemonは、Pythonプログラムをdaemon化できるパッケージである。

sudo apt-get install python-daemon

デーモンプログラム

Pythonプログラムはこんな感じ。

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

import serial
import time

from daemon import DaemonContext
from daemon.pidlockfile import PIDLockFile

if __name__ == '__main__':
        # 以下がデーモンプロセスとして実行される
        # pidfileが/tmpにないと、動作しないらしい
        with DaemonContext(pidfile=PIDLockFile('/tmp/serial-arduino.pid')):
                main()

起動スクリプト

サービス起動させるための起動デーモンは以下の通り。

$ sudo vi /etc/init.d/hoged

#!/bin/sh

### BEGIN INIT INFO
# Provides:        hoged
# Required-Start:  $local_fs $remote_fs $syslog
# Required-Stop:   $remote_fs
# Default-Start:   2 3 4 5
# Default-Stop: 
# Short-Description: Start hoged daemon
### END INIT INFO

PATH=/sbin:/bin:/usr/sbin:/usr/bin
# Source function library.
. /lib/lsb/init-functions

# Path to the script
DAEMON=/usr/local/sbin/python-hoge.py
PROG=serial-arduino
PIDFILE=/tmp/hoged.pid
LOCKFILE=/tmp/hoged.pid.lock

test -f $DAEMON || exit 0

lock_hoged() {
        if [ -x /usr/bin/lockfile-create ]; then
                lockfile-create $LOCKFILE
                lockfile-touch $LOCKFILE &
                LOCKTOUCHPID="$!"
        fi
}

unlock_hoged() {
        if [ -x /usr/bin/lockfile-create ] ; then
                kill $LOCKTOUCHPID
                lockfile-remove $LOCKFILE
        fi
}

case "$1" in
    start)
        log_daemon_msg "Starting $PROG server" "$PROG"
        lock_hoged
        start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --startas $DAEMON -- -p $PIDFILE
        status=$?
        unlock_hoged
        log_end_msg $status
        ;;
    stop)
        log_daemon_msg "Stopping $PROG server" "$PROG"
        start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE
        log_end_msg $?
        rm -f $PIDFILE
        ;;
    status)
        status_of_proc -p $PIDFILE $DAEMON $PROG
        ;;
    restart)
        stop
            start
        ;;
    *)
        echo "Usage: $PROG {start|stop|status|restart}"
        exit 1
        ;;
esac

最後に変更を反映。

sudo update-rc.d hoged defaults