Gradient Descent

Courseraの講義なので、ルー語になってしまうことをご了承ください。

概要

Cost functionをminimizeするには、傾きが0になる方向にθを近づけていく。

Cost functionをθで(Partial )derivativeすることで傾きを求めると、どちらの方向に行けば最小の地点があるかわかる。

なお、今回Cost functionは二乗誤差なので常に凹型。

θ - 傾き は傾きが大きすぎて収束しないor収束が遅い可能性があるので、学習率x傾きとする。学習率が小さすぎても収束が遅くなる。

最急降下法の「最急」とは、方向がメインであって、大きさはさほど関係ない

J(θ1,θ2)のθ1とθ2をそれぞれPartial derivativeして得られた学習率x傾きのベクトルが合成されるところをイメージ(上から見る)すると、まさに「最急」の方向になることがわかる。

 

Cost function Partial derivative

calculus - Partial derivative in gradient descent for two variables - Mathematics Stack Exchange

u = θ0+θ1x(i)−y(i) のように分けて、チェーンルールを使う。

CentOS7 PHP7.0にtidyをインストール

  1. インストールされているPHPのバージョンに合ったパッケージを探す。
    yum list | grep tidy 
  2. PHP7.0に合うパッケージはPHP70から始まる。7.1はPHP71から始まる。
    今回はphp70-php-tidy.x86_64が見つかった。
    yum install php70-php-tidy.x86_64
  3. インストールしますか?という問いに答える前に、依存パッケージ一覧にlibtidyがあることを確認する。
  4. インストール完了後、rpm -ql {パッケージ名}で、エクステンションのインストール先のパスをメモっておく。
  5. php.iniにextension="{先程メモったパス}"を追加。自分の環境ではextension=/opt/remi/php70/root/usr/lib64/php/modules/tidy.soとなりました。
  6. apacheを再起動して、phpinfo()にtidyがあることを確認。
  7. PHP: Tidy の例 - Manual

flat-uiのvaliables.lessを編集してPHPStorm(WebStorm)でコンパイル

まず、この記事に従って設定します。

mugimugi.hatenablog.com

もし、どこにインストールされたかわからず、コマンドプロンプトでlesscも使えない場合は、グローバルインストール先にPATHが通っていないのでこちらを参照してください。

phiary.me

次に、空のプロジェクトを作成してください。何の言語でも多分いいです。

そこにGitHubからflat-uiをダウンロードしてプロジェクト直下に入れましょう。

これで設定は終わりました。後はlessファイルを編集すると、自動的にflat-ui.lessからflat-ui.cssが生成されます。

エラーが出た:the requested PHP extension intl is mising from your system.

phpのextensionがないらしい。

yum list | grep intlで、自分のPHPのバージョンに合ったものを見つける。

yum install {パッケージ名}する。

rpm -ql {パッケージ名}でextensionの.soの場所を調べる。

php.iniにextension={調べた場所}でインストールしたextensionをPHPに読み込ませる。

CentOS7のGUI(gnome)で.sh(シェルスクリプト)をコマンドラインではなくダブルクリックで実行できるようにする

d.hatena.ne.jp

CentOS7にXAMPPとCakePHP3とNode.js&Socket.ioをセットアップするまでの流れ

CakePHP上にチャットを構築しようとするとき用の備忘録

Socket.ioが通信方法をwebsocketに変更しようとすると、
変更を知らせるパケットのステータスコードが101ではなく
200になってしまうという問題(ポーリングは可能なため一応通信は可能だが、
socket.ioの意味がない)が起こり、その原因が分かりません。

そのため、今回はsocket.io.jsの読み込みはリダイレクトしますが、
そのjsがconnectする先は直接Node.jsにします。スマートじゃないですが
オーバーヘッドは少ないかもしれません。

 
参考にさせていただいたもの

wtbm.necocen.info

qiita.com

得られた知見 

  • ApachePHPにはログファイルがある。

  • php -mやphpinfo();で読み込まれているモジュールを確認できる。
    今回はここでredisとigbinaryが読み込まれていることを確認した。

  • RedisとNode.jsにはデバッグモードがある。

  • elephant.ioはクライアントとして動作する(その為node.jsでフィルタ可)
    php-emitterはサーバから送信(emit)する(その為node.jsではフィルタ出来ない、イベントもない)
    今回はphp-emitterを使用し、こちらからのみ配信する仕様だったので、socket.ioにはほぼ何も書いていません。

  • class not foundに悩まされているときは以下を試す。

  • //ロード済みのextension一覧を表示する
    debug(get_loaded_extensions());

  • //include / require済みのファイル一覧を表示する、
    今回これでcomposerのファイルが読み込めてないことに気づいた
    debug(get_included_files());

  • //宣言済みのクラス一覧を表示する
    debug(get_declared_classes());

  • yumでインストールしたパッケージがどこにインストールされたか確認する
    rpm -ql パッケージ名

  • yumでインストール可能なorインストールした(リポジトリ名の前に@がつく)
    パッケージ一覧を表示する
    yum list (お好みでgrep)

  • yumでインストールしたパッケージ一覧を表示する
    yum list installed

  • runやshをダブルクリックで実行するには実行権限を付加することが必要。
    chmod以外には右クリックのオプションから変更可能。

全部書いているので適度に読み飛ばしてください。

  1. CentOS7をインストールする。今回はGUIにしました。

  2. XAMPP for Linuxをダウンロードしてインストールする。
    もし、PHPのバージョンを7.1にした場合は unable to initialize module Module compiled with module API=20151012 PHP compiled with module API=20160303と出る。この場合動作するPHPのバージョンは7.0。

  3. もしSELinuxが有効になっていたらApacheが起動しない可能性があるので無効にする←場合に依るんでしょうか?CUIの時は遭遇したがGUIでは遭遇しなかった。

  4. ファイアウォールの80と3000(Node.js用、3000じゃなくても良い)を開ける
    --permanentを忘れずに

  5. まずゲストOS側でApachePHPMyAdminが動いているか確認

  6. ホストOSからphpMyAdminにログインしようとすると新しいXAMPPのセキュリティコンセプトなどとエラーが出るので、/opt/lampp/etc/extra/httpd-xampp.confのrequire localをコメントアウトし、適当なアドレスを許可する。今回はとりあえず動かしたかったので、require all grantedとした。

  7. ゲストOSがNATの場合はポートフォワーディングを設定する

  8. ホストOS側でApachePHPMyAdminが動いているか確認

  9. phpMyAdminCakePHP用のユーザを作る。ホスト名は%だとなぜか動かなかったのでlocalhostとした。

  10. CakePHPのconfig/app.phpのDB設定を編集する。

  11. MariaDBに論理バックアップしておいたSQLをぶちこむ

  12. phpのPATHを通すために~/.bashに以下を追記。
    export PATH=$PATH:/opt/lampp/bin/php←場合による。

  13. composerそのものをインストールする

    CentOS7にComposerをインストールする - Qiita

  14. composer installする。
  1. CakePHPプロジェクトを閲覧すると実行権限がないなどと怒られるので、
    chmod -R 777 /opt/lampp/htdocs/{プロジェクト名}/logs
    chmod -R 777 /opt/lampp/htdocs/{プロジェクト名}/tmp
    のように権限を変更する。777はとりあえず動かしたかったので。

  2. この時点でCakePHPMariaDBとの間に有効なデータベース接続があることを確認する

  3. 【ここからNode.js&Socket.io】

    localhost:3000/nodejs/socket.ioの通信をApacheからNode.jsに移譲する(リバースプロキシ)ために
    Apachehttpd.confをいじる。

    今回は、socket.io.jsの読み込みのみApacheを経由させ、
    socket.io自体の通信は直接Nodeに渡します。なのでLoadModule ws-tunnelなどは記述せず、

    ProxyRequests Off

    ProxyPass /nodejs http://localhost:3000 retry=0 timeout=600 keepalive=On

    ProxyPassReverse /nodejs http://localhost:3000

    とした。
    余談ですが、socket.ioが起動した時にsocket.io.jsは自動で生成されます。

  4. node js,npmをインストールする
    node.jsは最新ではなくLTS版の6.11.0を使用しました。

  5. redisをインストールする

    socket.io-php-emitter で PHP から emit する方法 - Qiita

    wget http://download.redis.io/releases/redis-3.2.3.tar.gz
    tar xzf redis-3.2.3.tar.gz
    cd redis-3.2.3
    make
    make install
    utils/install_server.sh

  6. package.jsonがsocket.io,redisなど適切に書かれていることを確認してnpm installする(うまいこと行かなかったらnpm install -g)

  7. use socket.io;を書く

  8. Redisクラスを使えるようにするphp-redisをインストールする

  9. extension=なんたらかんたら/redis.soとphp.iniに書くと、Unable to load dynamic library '/usr/lib64/php/modules/redis.so' - /usr/lib64/php/modules/redis.so: undefined symbol: igbinary_serialize in Unknown on line 0とエラーが出るのでyum install php70-php-igbinaryする

  10. なんやかんやする。以下実際に書いたコード

今回のVIrtualBoxの設定は、NAT接続でポートフォワーディングを23000→3000, 27780→80としています。
Apacheは80, Node.jsは3000, Redisは6379 です。

Node.js

ただCakePHPの一部に表示したかっただけなので、expressは入れていません。

上に書いた通り、PHP-emitterはサーバとして動作するのでconnectionイベントには接続されたことを通知するemitのみしています。

 

var app = require('http').createServer(handler); var io = require('socket.io')(app); app.listen(3000); var redis = require('socket.io-redis'); var adapter = io.adapter(redis({ host: '127.0.0.1', port: 6379 })); function handler (req, res) { res.writeHead(200); res.end(); } io.on('connection', function (socket) { socket.emit("messageFromPHP",""); });

 CakePHP3 Controller

最初の方でPHP7.1を使用していたため、useが使用できずrequire_onceでphpファイルを一つ一つ読み込んでいましたが、PHP7.0に替えたところ特に読み込まずとも認識しました。6379はredisの標準ポートです。

TomController.php

$redis = new \Redis; $redis->connect('127.0.0.1', '6379'); $emitter = new \SocketIO\Emitter($redis); $emitter->emit('messageFromPHP', $num);

composer.json

上と同じく、PHP7.1を使用していたためにautoloadにemitterを入れたりしましたが、PHP7.0に入れ替えたところ、結果的にrequireを書き換えるのみでした。

 

 "ashiina/socket.io-emitter": "0.8.0"

package.json

ただCakePHPの一部に表示したかっただけなので、expressは入れていません。

nodemonはコードが変更されたとき即時に変更を反映するものです。

 

{
"name": "sample-server",
"main": "off.js",
"dependencies": {
"socket.io": "^1.4.8",
"socket.io-redis": "^1.0.0"
},
"devDependencies": {
"nodemon": "^1.9.1"
}
}

CakePHP3 Template

Apache経由でNode.jsからsocket.io.jsを読み込んだあと、直接Node.jsにconnectしています。Apache経由で読み込む利点は、ApacheとNode.jsが異なるオリジン(ポート番号が違うため)であるので、Node.js側にクロスオリジンの設定(res.header("Access-Control-Allow-Origin", "*"など)がいらないことです。
ここのlocalhostは必要に応じて$_SERVER['SERVER_ADDR']とでもしてください。

bobby.ctp

    <script src="/nodejs/socket.io/socket.io.js"></script>
    <script type="text/javascript">
        var socket = io('http://localhost:23000');
        socket.on('messageFromPHP', function (data) {
            console.log(data);
            $('#activity-text').text(data);
        });
    </script>

httpd.conf

websocketの通信を媒介する場合はws-tunnelのモジュールをロードなどするらしいです。私は出来ませんでした。

retry=0はリダイレクト先(Node.js)に接続出来ない状況でその情報をキャッシュさせないものです。つまり0ならば接続のたびにNode.jsに接続できることを確認します。実用的には3秒程度なんでしょうか?

 

ProxyRequests Off
ProxyPass /nodejs http://localhost:3000 retry=0 timeout=600 keepalive=On
ProxyPassReverse /nodejs http://localhost:3000

追記

きちんとReadme.mdを読んだらRedisクラスはsocket.io-php-emitterにあった。確かにcomposer.jsonにrequire ptrofimov/tinyredisclientとある。しかし高機能なものを使うならPHP-redisをインストールしろということらしい。

 

CentOS7のGUIでXAMPPをインストールする

XAMPPの公式サイトから.runをダウンロードし、

実行権限を付加した後、sudo ./xamp-*.runとCentOS上で実行する。

./は必要。これがあることで、システムは./~.runがコマンドではなくファイルパスであることを認識できる。