読者です 読者をやめる 読者になる 読者になる

なお。のつれづれ

つれづれに書くよ

TED: Dan Pink氏の「やる気に関する驚きの科学」がすごかった件

これです。

www.ted.com

Candle Problem

f:id:nao_0x2c6:20170512225658p:plain

↑動画スクショ

So, ladies and gentlemen of the jury, take a look at this. This is called the candle problem. Some of you might know it. It’s created in 1945 by a psychologist named Karl Duncker. He created this experiment that is used in many other experiments in behavioral science. And here’s how it works. Suppose I’m the experimenter. I bring you into a room. I give you a candle, some thumbtacks and some matches. And I say to you, “Your job is to attach the candle to the wall so the wax doesn’t drip onto the table.” Now what would you do?

1945年、Karl Duncker氏が「ローソク問題」という問題を考えた。「ロウソク、画鋲、マッチを使って、ロウソクを壁にとりつけよ。ただし、蝋をテーブルに落としてはならない」という問題。

答えはこれ

f:id:nao_0x2c6:20170512231842p:plain

画鋲の入っていた箱を使う、というもの。

普通に解かせると、大体のひとは5~10分で解けるらしい

Sam Glucksbergによる実験

I want to tell you about an experiment using the candle problem, done by a scientist named Sam Glucksberg, who is now at Princeton University, US, This shows the power of incentives. He gathered his participants and said: “I’m going to time you, how quickly you can solve this problem.” To one group he said, “I’m going to time you to establish norms, averages for how long it typically takes someone to solve this sort of problem.” To the second group he offered rewards. He said, “If you’re in the top 25% of the fastest times, you get five dollars. If you’re the fastest of everyone we’re testing here today, you get 20 dollars.” Now this is several years ago, adjusted for inflation, it’s a decent sum of money for a few minutes of work. It’s a nice motivator.

Sam Gluckbsberg氏が

  • この問題を解くのにかかる平均的な時間を調査する

といって普通に問題を解かせたグループ

  • 問題を解くのが早かった上位25%のグループには5ドルを、さらに最も早かったものには20ドルを与える

インセンティブを与えたグループの2つに被験者を分け、ローソク問題を解かせるという実験を行った。

How much faster did this group solve the problem?

インセンティブを与えた方のグループは、どれだけ早く問題を解けたのか?

Answer: It took them, on average, three and a half minutes longer. 3.5 min longer.

平均して3.5分、より多くの時間がかかった

これ衝撃的でした

外的な動機づけと内的な動機づけ

次の状態で同じ問題を与えると、インセンティブを与えた方が成果はよくなる(早く問題は解ける)らしい

f:id:nao_0x2c6:20170512234750p:plain

この画像では画鋲が箱に入っていない。つまり、答えが自明なものでは、インセンティブを与えた方が能率は上がる。

Let me tell you why this is so important. In western Europe, in many parts of Asia, in North America, in Australia, white-collar workers are doing less of this kind of work, and more of this kind of work. That routine, rule-based, left-brain work — certain kinds of accounting, financial analysis, computer programming — has become fairly easy to outsource, fairly easy to automate. Software can do it faster. Low-cost providers can do it cheaper. So what really matters are the more right-brained creative, conceptual kinds of abilities. Think about your own work. Think about your own work. Are the problems that you face, or even the problems we’ve been talking about here, do they have a clear set of rules, and a single solution? No. The rules are mystifying. The solution, if it exists at all, is surprising and not obvious. Everybody in this room is dealing with their own version of the candle problem. And for candle problems of any kind, in any field, those if-then rewards, the things around which we’ve built so many of our businesses, don’t work!

今はルーティン的な作業(左脳的作業)は、アウトソーシングしたりコンピュータが行うようになってきている。

目の前の仕事(右脳的創造)は、自分自身のローソク問題であり、それは今までのような餌で釣るようなやり方で能率を上げるという手法は、機能しにくくなっている。

There is a mismatch between what science knows and what business does. And what worries me, as we stand here in the rubble of the economic collapse, is that too many organizations are making their decisions, their policies about talent and people, based on assumptions that are outdated, unexamined, and rooted more in folklore than in science. And if we really want to get out of this economic mess, if we really want high performance on those definitional tasks of the 21st century, the solution is not to do more of the wrong things, to entice people with a sweeter carrot, or threaten them with a sharper stick. We need a whole new approach.

Dan氏はこれを「21世紀の答えのないようなタスクで高いパフォーマンスを発揮させるには、これまでのアメとムチを与えるようなやり方は科学的ではない」と言っている。

And to my mind, that new operating system for our businesses revolves around three elements: autonomy, mastery and purpose. Autonomy: the urge to direct our own lives. Mastery: the desire to get better and better at something that matters. Purpose: the yearning to do what we do in the service of something larger than ourselves. These are the building blocks of an entirely new operating system for our businesses.

アメとムチによる動機づけ(外的動機づけ)ではパフォーマンスは発揮できない。

  • Autonomy: 自主性
  • Mastery: 成長
  • Purpose: 目的

の3つを伸ばす動機づけ(内的動機づけ)が21世紀的なアプローチである。

つれづれ

現職のとある海外部署は、サボりがすごいらしい。私もマニラでのオフショア開発部門を担当する予定なのだが、「チケット駆動開発にして成果量で歩合的なものを導入したらやる気だして開発できるかな」くらいに考えていた。

が、Dan氏のスピーチを聞いてそれはとても安易な発想であると痛感した。

《余談》竜馬の居眠り堤

ここで急だが坂本龍馬の話。

高知に「竜馬の居眠り堤」という堤防がある。これはかつて、高知城下の小高坂に屋敷をもっていた池田虎之進が現在の中村市を流れる四万十川の堤防工事の普請奉行を命ぜられたとき、十区ほどにわけたうちの一区の長に、竜馬を選んだ。

各区競争となったが、どの区も人夫は怠けたり喧嘩沙汰をおこし、責任者は刀を抜いて脅すこともあったらしい。

だが、竜馬の担当した具同村の堤防だけは、他の区の半分の日数だけで終わった。

ばかに早く進む作業に、池田虎之進は不思議に思って何度か見回りにくると、いつも竜馬は松の木によりかかって居眠りをしていた。詳しく虎之進が訊くと、竜馬は仕事の責任者を巧みに選び、分掌させた上で競争させたらしい。

また、毎日の進捗を確認して、褒美を与えたそうだ。

参考: 竜馬がゆく 3

勘違い

私はこの話を「報酬さえ与えておけば成果は出る」程度のことで記憶してしまい、Dan氏の動画を観て衝撃を受けたあとに再度確認した。

そしたらなんてことはない。竜馬は、人夫の能力を見極め、人材を適材適所におき、さらに成果を認めて褒美を与えただけである。

人をマネジメントする上での基礎であり本質である。そして、Dan氏の動画とはあまり関連がなかった…

だが、とてもいい教訓になった。人を扱うことは、単純ではない。愛情である。(Dan氏の動画とこれも関連がないが…)

権利的なもの

一応このブログは下記利用規約を読んだ上で書いてます。

TED.com Terms of Use | Our policies + terms | Our Organization | About | TED.com

nginxでCGI実行環境を整える

MovableTypeのサイトをAWSに移行した際のメモ。

環境はAWSubuntu 16.04 LTS。PerlCGI環境を整えた。

nginxインストー

$ sudo apt -y install nginx

CGI実行ラッパをインストー

nginxはCGIを実行できないらしく。CGIFCGIでラップするfcgiwrapを用いる。

$ sudo apt -y install fcgiwrap

nginx設定

nginxの大元の設定ファイルは

/etc/nginx/nginx.conf

で、当該ファイルのincludeで読み込むファイルに下記を追記することで、.cgi のファイルをCGIとして実行できる。

server {
~~~ 中略 ~~~
    location ~ \.cgi$ {
        root /path/to/root;
        fastcgi_pass unix:/var/run/fcgiwrap.socket;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
~~~~~~~~~~
}

nginxを再起動しておくこと。

$ sudo service nginx restart

fcgiwrapの設定

/etc/init.d/fcgiwrapを編集する

 FCGI_CHILDREN

この数だけCGI実行プロセスがforkされる?

ぶっちゃけよくわかっていない。

サーバのスペックや実行アプリケーションの処理コスト(起動数?)とかで最適化するものなのか。

FCGI_USER
FCGI_GROUP

CGIを実行するユーザとグループ。 nginx側の設定に合わせる。

aptでnginxを普通に入れてたら単純にnginxでいい。

FCGI_SOCKET_OWNER
FCGI_SOCKET_GROUP

/var/run/fcgiwrap.socketの所有者。直前行のコメントにも書いてあるけどコメントアウトする。

設定したらfcgiwrapを再起動。

$ sudo systemctl restart fcgiwrap

テスト

正常にアクセスできるか確認する。

#!/usr/bin/perl

print "Content-Type: text/html\n\n";
print "<html>";
print "<head><title>Test</title></head>";
print "<body>";
print "<p>This is CGI Test</p>";
print "</body>";
print "</html>";

忘れちゃならないのは実行権限をつけておくこと。

$ chmod 755 testcgi.cgi

アクセスすると、unable to resolve host が表示された。。

/etc/hostsにホスト名を追加する

$ sudo echo "127.0.1.1 $(hostname)" >> /etc/hosts

127.0.1.1はubuntudebianのよくわからない仕様で必要らしい。

とりあえずこんな感じ。

知るっていうこと

最近、人の数だけ信仰があるなって感じる。

 

宗教的な意味合いではなくて。いや、宗教的な意味合いも含めて。

 

で、特にそれに大きな影響をもつのが「知る」ということ。

 

信仰という言葉を使ったので宗教的にいうと、

終末を知る。カルマを知る。目に見えない世界を知る。

 

これによって、心を改めようとか、こういう生き方をしようとか、

もっというと、他の人からみて何でもないものに対して、怯えたり拠り所にしたりする。

 

宗教的でなくても、3.11の原発のときなんか特にそうでしたよね。

目に見えない放射線に過度に怯えて、子供の間では福島出身の子がいじめられたり。

 

人は、知識を得て、知って、そこから価値観を形成する。

それって、一つの自分の生き方で、それを信仰としているんだな、と思う。

 

民主主義も共産主義も宗教みたいなものだな、と。

なんて、誰もが思い付きそうなことでもあるのですがね。

 

 

何が正しいのかはわからない。

いや、何も正しくなんかないのかも知れない。

あるのは単に、法則だけかな、と思う。

 

木からりんごが落ちるように。

仮にカルマがあったとして、そのせいで不幸なことが起こるとして。

けどその不幸なことって、単にカルマを消すひとつの現象なだけで

 

幸不幸とかではなくて、単なる現象で事象。

人の主観的な心の意味付け。

だから、幸せを感じるか不幸せを感じるかは、自分次第。

 

 

そう思うのと同時に、知るというのは怖いな、とも思う。

 

明日死ぬことを知れば、

今日一日を思いっきり生きるのだろうか。

今日一日を怯えながら過ごすのだろうか。

 

自由に意味づけなんか、思い通りにできやしない。

 

だったら何も知らない方が、平和に前も進めるのかも。

 

まとまりませんが、この辺で。

Ubuntu16.04 にPhantomJSをnodeでインストールする際にエラーになる

詰まったのでメモ。

$ sudo npm install -g phantomjs

実行

> phantomjs@2.1.7 install /usr/local/lib/node_modules/phantomjs\ > node install.js

sh: 1: node: not found\ npm ERR! Linux 4.4.0-51-generic\ npm ERR! argv "/usr/bin/nodejs" "/usr/bin/npm" "-g" "install" "phantomjs"\ npm ERR! node v4.2.6\ npm ERR! npm v3.5.2

あちゃー。

解決策がgithubに記載されていた。

https://github.com/Medium/phantomjs#im-on-debian-or-ubuntu-and-the-installer-failed-because-it-couldnt-find-node

Some Linux distros tried to rename node to nodejs due to a package conflict. This is a non-portable change, and we do not try to support this. The official documentation recommends that you run apt-get install nodejs-legacy to symlink node to nodejs on those platforms, or many NodeJS programs won't work properly.

ので、nodejs-legacyをインストールする。

$ sudo apt-get install nodejs-legacy

これでphantomjsをインストールできるようになった。めでたしめでたし。

shの引数の利用

shの引数を扱い方メモ。

引数をスクリプト内から参照する

./sample.sh arg1 arg2

とshスクリプトを実行したときに、sample.sh中でarg1arg2の文字列はそれぞれ$1$2で参照できます。同様に、$3から$9にそれぞれ3つめから9つめまでの引数が順にわたされます。10コ以上引数を指定した際は、${10}のように変数を書いて扱ってください($10と書くと、変数$1と文字列0が連結したものと解釈されます)

引数の存在判定

わりとよくやるのが、引数があるかないかの判定。 これは、 -z条件式を使うと楽です。-z条件式は、文字列長さが0なら真を返します(shでの真は、値としては0になります)。

#!/bin/sh

if [ -z $1 ] ; then
    echo "Please args!"
else
    echo "First arg is [ $1 ]"
fi

上記をsample.shとして保存します。chomd 755 sample.shとでもして実行権限を与えてから実行します。

$ ./sample.sh

実行権限を与えなくても、sourceコマンドでも実行されます。

$ source sample.sh

上記のように引数を与えないと、出力は以下になります。

Please args!

英語のクオリティはつっこまない。

引数を与えると、以下の通り。

$ ./sample.sh hogehoge
First arg is [ hogehoge ]

以上。

補足

  • 文字列長が「0より大きい」場合を真とする条件は、-n条件式を使います。
  • #!/bin/shなど、読み込みインタプリタを記述する一行目のことをシェバン(シバン)行といいます

CasperJSめも

CaperJSを触り始めたのだが、まとまってる記事がそんなにない。徒然なるメモをここに。

そもそも論

CaperJSはNode.jsのスクレイピングモジュールでありスクレイピングツールである。スクレイピングツールじゃなくてテストツールかも知れないが、スクレイピングに使えるのは間違いない。

また、Node.jsのモジュールなので当然Javascriptで書く。

CasperJSはPhantomJSというヘッドレスブラウザをハンドルする。ヘッドレスって何かというと、GUIがないブラウザ。かといってLynxとかW3mとかみたいなCUIブラウザとも違う。JavaScriptも基本実行してくれたりとレンダリング処理は内部で走るのだが、ユーザに表示する画面を持たない。だから、うまいことPhantomJSをハンドルすれば、「あそこのここをクリックして表示されたページのここんとこのこのテキストを抽出!」とかを自動化できたりする(雑)。

導入

CasperJSはnpmパッケージにある。nodejsとnpmは先に入れておくこと。

Macbrewが入ってるなら下記で両方導入できる。

$ brew install nodejs

ubuntuなどのdebian系でもapt-getで可能だが、npmも指定する必要があったはず(下記)

$ sudo apt-get install nodejs npm

まぁ普通にnode.jsのページからダウンロードするのでもいい。Windowsだとこれがお手軽(というか他は知らない)。

Node.js

node.jsを導入してnpmコマンドが使えるようになったら、 下記コマンドでCasperJSをインストールする。

$ npm install -g casperjs

なお、カレントディレクトリのみにインストールしたい場合は、-gオプションをつけないこと。

PhantomJSの導入

PhantomJSもnpmでインストールできるはず。

$ npm install -g phantomjs

ただ、筆者のlubuntu環境ではうまく行かなかった。(windowsMacでは大丈夫だった) だが、普通にapt-getでインストールできた(下記)。

$ sudo apt-get install phantomjs

一応補足で、PhantomJSは単体でインストールできる。PhantomJSはCasperJSのものではなく、Seleniumなどのスクレイピングツールでも利用される。というかむしろCasperJSがPhantomJSしか使えない。いや、正確にいうと他にも使えるのだが…そこらへんは知識がない。

というかCasperJS使うと、いちいちthenの中にfunctionとか書かなきゃで面倒だし今CasperJSの制御なのかPhantomJSの制御なのか意味不明になるしそもそも2つの間で共通でないObjectとかあったりしてややこしさ極まりないので素直にSeleniumで書くべきだと思う。

げふんげふん。

とりあえず動くもの

習うより慣れろが一番早い習得方法だと思ってる。

はてなブログの、おすすめ記事一覧を取得するサンプルコード(ファイル名sample.js)。

var url = "http://hatenablog.com/";
var useragent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36";

var casper = require('casper').create();

casper.userAgent(useragent);
casper.start(url, function() {
    var ret = casper.evaluate(function() {
        /////////// ここからPhantomJS内でのコンソール実行だと思うといい //////////////
        var recommends = document.querySelectorAll(".serviceTop-entry-title > a");
        return Array.prototype.map.call(recommends, function(self){ return self.text });
        //////////////////////////////////////////////////////////////////////////////
    });

    casper.echo("<<< おすすめ記事一覧 >>>");
    casper.eachThen(ret, function(_ret) {
        casper.echo(_ret.data);
    });
});


casper.run();

実行

$ casperjs sample.js

<<< おすすめ記事一覧 >>>
『友人の家でのえ?』な話
今までで面白かったナンパ、怖かったナンパ厳選まとめ
ZOZOTOWN(ゾゾタウン)がツケ払いOKに!今後は洋服や靴を買ってから最大2ヶ月間、支…
人間の闇を掘り尽くすNHKの「ねほりんぱほりん」が凄い
2016秋クールのアニメ&ドラマがおもしろすぎてやっぱりテレビは最高
涼宮ハルヒ、29歳。
これから先10年、フロントエンドに関する予言
グッド・モーニング
あなたはこの文章を読んで「こいつめんどくせえな」と思う
これから先10年、フロントエンドに関する予言
プログラミング学習日記 PHP編2-3日目 -ゲストブック作成-
PHPカンファレンス2016で発表してきました #phpcon2016
git/githubのマイナーな便利コマンド
風邪をひきやすい時期は、鍋で体を温めよう!
weekend Ramen|牡蠣と四方竹の中華炒めあんかけ醤油ラーメン
砂糖・バター不使用 はちみつヨーグルトケーキ
なすのミートソースグラタン。
システム手帳論考9_【スピンオフ】
男性の失業で起きるお金以外の4つのデメリットとは
「ソフトウェアテスト勉強会~テスターと創る開発現場~」感想
10月のブログ・クラウドソーシングの収入と今後の目標など
小学校高学年に読んでほしい50冊。いや、「子どもと一緒に読みたい本」。
たった4ヶ月でTOEIC350点から日常英会話が出来るようになった英語勉強方法
【お題】 まだヒートテックなんかで冬を過ごしているの?

ざっくり解説

var casper = require('casper').create();

CasperJSのモジュール読み込み。createでコンストラクタ的なことやってくれると思えばいい。

createの引数にユーザエージェントやタイムアウトなどの設定も書ける。例えばユーザエージェントを指定する場合

var casper = require('casper').create(
    {
        userAgetnt : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36");
    }
);

みたいに書ける(ただ、筆者はうまく行かなかったので、サンプルコードでは別途ユーザエージェントを指定した)。

casper.start(url, function() {
    var ret = casper.evaluate(function() {
        /////////// ここからPhantomJS内でのコンソール実行だと思うといい //////////////
        var recommends = document.querySelectorAll(".serviceTop-entry-title > a");
        return Array.prototype.map.call(recommends, function(self){ return self.text });
        //////////////////////////////////////////////////////////////////////////////
    });

    .....

});

casper.startでオープンするurlと、オープンしたあとの処理を記述した関数を渡す。

別のurlを再度オープンしたいときはcasper.thenOpenを使うこと。

casper.evaluateに渡された関数は、PhantomJS内で実行される。途中、わざわざArray.prototypeを駆使してmap関数を利用したが、これは取得したDOM配列(もどき)はArrayオブジェクトではなくNodeListオブジェクトであり、map関数を持たないためである。

(試しにChromeデバッグコンソールでdocument.querySelelctorAll()を実行して返ってきたオブジェクトでmap関数を使うとエラーになる)

casper.evaluate内は基本的にブラウザ側での実行処理になるので、Chromeデバッグコンソールで記述できる制御は、casper.evaluateでも記述できると思っていいはず。細かい仕様の差分はあるかもしれないが。

カンのいい方はお気づきかも知れないが、casper.evaluate内で実行される関数はPhantomJS側で実行されるので、console.log("hogehoge")とか書いても、何も表示されない。これは、Itsukaraさんのブログに細かく記載されている。

itsukara.hateblo.jp

こちらのブログは、CasperJSのデバッグ方法についても細かく書かれているので、ぜひ参考にされてほしい。

casper.evaluate内で最後に

return Array.prototype.map.call(recommends, function(self){ return self.text });

と書いているが、CasperJS側に単純なオブジェクトなら返すことができる。逆に、CasperJS側からPhantomJSにオブジェクトを渡したいとき(グローバル変数だろうとcasper.evaluate内では別の(PhantomJSの)世界での出来事になるので、その変数は参照できなくなる)は、

casper.evaluate(function(_data){
    ...
}, data);

と書けば、data_dataに渡される。

単純なオブジェクトと書いたが、これが地味に厄介である。単純な配列や連想配列程度なら問題なく渡せるのだが、連想配列の値に配列をもつ、など多少複雑になった途端、なんだかよくわからないオブジェクトが渡される。

思いつきで、

return document.querySelectorAll(".serviceTop-entry-title > a");

とか書いてCasperJS側でDOMをごにょごにょやりたい気持ちはとてもわかるが、残念ながらできない。謎のオブジェクトが返ってきて、持て余す。

ただこれは、自分で定義したオブジェクトくらいなら、後述する裏技で無理やり回避しようと思えばできないこともない。

    casper.echo("<<< おすすめ記事一覧 >>>");
    casper.eachThen(ret, function(_ret) {
        casper.echo(_ret.data);
    });

この出力部分で注意する必要があるのは、下記のように書くと出力されないことである。

    casper.echo("<<< おすすめ記事一覧 >>>");
    for(var idx in ret) {
        casper.echo(ret[idx]); // 何も出力されない\(^o^)/
    }

正直細かい理由はわかってないが、for文で書くと、CasperJSとは同期しない何かで動くらしい(すごく曖昧)。

casper.run();

これまで書いてきたcasper.start内の記述は、言ってみればプログラムの実行計画部分で、実際に走査処理(スクレイピング処理)が行われるのは、casper.run()してからである。これを書かないと、何もおきない。

【おまけ】CasperJSとPhantomJS間のオブジェクトの受け渡し

前述したように、多少複雑なオブジェクトはCasperJSとPhantomJS間で受け渡しがそのままできない。

これは会社の同僚のひらめきから生まれた裏技なのだが、いっそJSON文字列にして受け渡してしまえば、なんとかなったりする。

具体的には、casper.evaluate内でretObjを返すならreturn JSON.stringify(retObj)すればいい。

受け取った側はJSON.parseでもとのオブジェクト(にそっくりなもの)を復元できる。

ただ、これはDOMオブジェクトほど複雑になるとうまくJSON文字列化できなかったので、限界がある。 藁にもすがりたいときの藁程度の知識として、一応知っておくといいと思う。