「パフォーマンス・マネジメント」を読んだ

どこかのブログで薦められていて面白そうだったので読んでみたが、非常に面白かった。 行動を強化する好子と弱化させる嫌子とで行動を解釈していく。嫌子つまり行動の弱化はモチベーションの強化とか動機付けにはプラスに働かないというのは経験的にもしっくりくる話だ。一方でしつけとか、(子供時代に養われると思う)ある種のストイックさとか自分への厳しさってのは好子では説明できないと思うんだよなぁ。ま、そういうあたりは置いといてある程度成熟したというか自我形成された大人と言われる人達は行動の弱化というのはあまり良い方法ではないなということは理解した。

p.92

組織がパフォーマンスの向上につながらない行動に価値をおく危険を「行動の罠」と呼んでいる

同じ成果を、100%全力出し切って達成するのと70%の力で達成するのは後者が評価されるべきなんだけど、前者を評価する傾向があるよね。みたいなことが具体例としてあげられていた。

p.94

パフォーマンスに依存して報酬を与えると内発的動機が弱まる

モチベーション3.0で時代遅れと書かれているが、本書では

行動分析学では内発的動機を、仕事の成果が好子となって仕事をするという行動を自動的に強化している状態と考える。つまり、パフォーマンスそのものが好子となればいい。

と書いてある。報酬与えると内発的動機が弱まるというのは報酬そのものが嫌子または行動を弱化させる方向にはたらくものなのであろうか?それとも報酬という刺激は常に増加させないと効果がないもので、増加がないという状況が嫌子になるんだろうかね?

p.145

「タバコをやめる」とか「夫婦ゲンカをしない」など、望ましくない行動を減らすのが目標の場合、その代わりに増やしたい行動についても目標を設定しておくと効果的である。

  • 行動随伴性(Antecedent, Behavior, Consequence)
  • すべての行動の原理は「〜する」という行動にあてはまり、「〜しない」という行動にはあてはまらない
  • パフォーマンスとは行動の成果である
  • 組織がパフォーマンスの向上につながらない行動に価値をおく危険を「行動の罠」と呼んでいる
  • パフォーマンスに依存して報酬を与えると内発的動機が弱まる
  • パフォーマンス・マネジメントでは知識も行動と考える

怒らないこともあわせて読んどくとよいかも

サーバー起動時にFastladderが一緒に立ち上がるようにする(途中)

うちの職場のFastladderの延べユーザーは7割を超えていて、サーバーが落ちてるとすぐに苦情がくるような状況だ。このアクティブユーザー率にすんのに3年以上の地味な努力と啓蒙活動があったわけだが。

で、そもそもこういったインフラは僕の仕事じゃないので障害対応しても給料に反映されるわけじゃなくて、むしろ時間を奪われるので、クローラーをdaemontoolsで動かしたりして手間を減らした。おかげで、一回起動させればサーバーが安定に動いている限りなにもしなくても良くなった(ここ一年くらいは障害対応ほとんどしてない)んだけど、今週から始まった計画停電で毎日起動してシャットダウンをしてというの繰り返しつつ、mongrel立ち上げて、クローラー動かしてっていうのはだるいのできちんと起動、停止するようにしようとした。

けど、いまのとこうまくいってないのでやっつけスクリプトでしのいでいる。

mongrel

rc.localで/usr/local/fastladder/tmp/pids/mongrel.pidが存在したらrmするように書いておいて以下のシェルスクリプトをcronで実行するようにしている。

#!/bin/sh

if [ ! -e /usr/local/fastladder/tmp/pids/mongrel.pid ];
then
  cd /usr/local/fastladder; script/server -d -e production
fi

ほんとはShapadoのようにpassengerで動かせれば楽なんだろうけどFedoraCore6だからなぁ。インストール出来んのかな?明日調べてみるか。

crawler

シャットダウン時に

svc -d /service/fastladder

するようにしてみたんだけど、どうもうまくいってないのでドキュメント読みなおす。あと日本語訳も。

とりあえず、リブートするとプロセスが即落ちする(svstatで継続時間が1秒以内に落ちてプロセスがどんどん大きくなる状況になる)ので、この場合に

svc -dx /service/fastladder /service/fastladder/log

を適当な感覚でまわし続けるcronを動かしておいた。

#!/usr/bin/python

import commands
import time
import re
reup = re.compile("(\d+) seconds")

def get_uptime():
  uptime = 0
  svresult = commands.getoutput('svstat /service/fastladder')
  m = reup.search(svresult)
  if m != None:
    uptime = m.group(1)
  return uptime

if __name__ == '__main__':
  for i in range(300):
    if get_uptime() > 2:
      break
    else:
      commands.getoutput('svc -dx /service/fastladder /service/fastladder/log')
      time.sleep(10)

Pythonのdisモジュール

逆アセンブル用のモジュール

ソースコードも200行程度で読みやすそうなので、読んでみようかと。

その前にドキュメント読んだら面白かった。

Rubyで作る奇妙なプログラミング言語でスタックマシンを作ってみた経験が理解において非常に役に立った。

ProductName Rubyで作る奇妙なプログラミング言語 ~Esoteric Language~
原 悠
毎日コミュニケーションズ / ?円 ( 2008-12-20 )


リスト内包標記

>>> def cp(l): return [e for e in l]
... 
>>> dis.dis(cp)
  1           0 BUILD_LIST               0
              3 DUP_TOP             
              4 STORE_FAST               1 (_[1])
              7 LOAD_FAST                0 (l)
             10 GET_ITER            
        >>   11 FOR_ITER                13 (to 27)
             14 STORE_FAST               2 (e)
             17 LOAD_FAST                1 (_[1])
             20 LOAD_FAST                2 (e)
             23 LIST_APPEND         
             24 JUMP_ABSOLUTE           11
        >>   27 DELETE_FAST              1 (_[1])
             30 RETURN_VALUE

ループで書いてみる

>>> def cp2(l):
...   ll = []
...   for e in l:
...     ll.append(e)
...   return ll
... 
>>> dis.dis(cp2)
  2           0 BUILD_LIST               0
              3 STORE_FAST               1 (ll)

  3           6 SETUP_LOOP              27 (to 36)
              9 LOAD_FAST                0 (l)
             12 GET_ITER            
        >>   13 FOR_ITER                19 (to 35)
             16 STORE_FAST               2 (e)

  4          19 LOAD_FAST                1 (ll)
             22 LOAD_ATTR                0 (append)
             25 LOAD_FAST                2 (e)
             28 CALL_FUNCTION            1
             31 POP_TOP             
             32 JUMP_ABSOLUTE           13
        >>   35 POP_BLOCK

  5     >>   36 LOAD_FAST                1 (ll)
             39 RETURN_VALUE

参考

ProductName エキスパートPythonプログラミング
Tarek Ziade
アスキー・メディアワークス / 3780円 ( 2010-05-28 )


linuxのatコマンド

うちは輪番停電の第5グループなので、明日は正午に停電が起こるわけだ。

そのタイミングで自宅サーバーも落としておきたいがcronだと毎日同じ時間に設定されるし、毎度毎度変更するのも面倒くさい。

そういう時にはatを使えばいいらしい。

echo "shutdown -h now" | at 11:50 3/15/2011

なにげにatを使うのは初めてだな。

ProductName プロのための Linuxシステム構築・運用技術 (Software Design plus)
中井 悦司
技術評論社 / 3024円 ( 2010-12-22 )


というわけで、このブログは第5グループの停電に応じてアクセスできなくなることが判明した。

「数学ガール/乱択アルゴリズム」は数学ガールシリーズの中で一番読みやすかった

確率、組み合わせ、乱択アルゴリズム。

ProductName 数学ガール/乱択アルゴリズム
結城 浩
ソフトバンククリエイティブ / 1995円 ( 2011-03-02 )


この後にPRMLに進むのもよいかもしれん。

ProductName パターン認識と機械学習 上 - ベイズ理論による統計的予測
C. M. ビショップ
シュプリンガー・ジャパン株式会社 / 6825円 ( 2007-12-10 )


Pythonのcontextlibモジュール

contextlib — with -構文コンテキストのためのユーティリティ。

functoolsのwrapsで包んだヘルパー関数を返す

def contextmanager(func):
    @wraps(func)
    def helper(*args, **kwds):
        return GeneratorContextManager(func(*args, **kwds))
    return helper

GeneratorContextManagerクラス(例外処理をのぞいて把握しやすくした)__enter__実行してからyieldして最後に__exit__が実行される

class GeneratorContextManager(object):
    """Helper for @contextmanager decorator."""

    def __init__(self, gen):
        self.gen = gen

    def __enter__(self):
        return self.gen.next()

    def __exit__(self, type, value, traceback):
        if type is None:
            try:
                self.gen.next()
            except StopIteration:
                return
            else:
                raise RuntimeError("generator didn't stop")

実際に使う場合はこんな感じでジェネレータを包む

@contextmanager
def tag(name):
    print "<%s>" % name
    yield
    print "</%s>" % name

>>> with tag("h1"):
...    print "foo"
...
<h1>
foo
</h1>

functoolsのwraps

10.8. functools — 高階関数と呼び出し可能オブジェクトの操作

これはラッパ関数を定義するときに partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated) を関数デコレータとして呼び出す便宜関数です。

Pythonのwebbrowserモジュール

ソース読んでたらmain関数が

def main():
    import getopt
    usage = """Usage: %s [-n | -t] url
    -n: open new window
    -t: open new tab""" % sys.argv[0]
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'ntd')
    except getopt.error, msg:
        print >>sys.stderr, msg
        print >>sys.stderr, usage
        sys.exit(1)
    new_win = 0
    for o, a in opts:
        if o == '-n': new_win = 1
        elif o == '-t': new_win = 2
    if len(args) != 1:
        print >>sys.stderr, usage
        sys.exit(1)

    url = args[0]
    open(url, new_win)

    print "\a"

ということなので

python -mwebbrowser -n "http://blog.kzfmix.com"

と打てば任意のURLをwebbrowserで開くことが出来る。

地震の次の日

僕の住んでいるあたりは、震度4でそのまま夜中まで停電したのだが、朝には電気と水が復旧してたので一安心。

週末は家の冷蔵庫にほとんどなにも入ってないので、朝一で近所のスーパーに買物に行ったら混んでた。

特に年配の女性の方々がカート2つとか3つとか操って買い占めにはしっていたのは印象に残った。レジ待ちの際、前のおばさんの買い物っぷりが豪快すぎて、「おいおい溜め込むのは脂肪だけにしとけって」と軽く心の中で突っ込んだが、もしかしたら10人位の家族だったのかもしれないなぁ。

富士宮のジャスコではトイレットペーパー買いまくったりしてるんだってさ。被災地に送るのかな?これまたよくわからん行動様式だなぁ。


避難用品は登山用のザック(45-50L)に詰めてあるけど結構ギュウギュウで水なんてそんなに入れられない(必要最低限)。暖をとれるようなもののほうが重要かなぁ。軽くて暖かいシュラフはあったほうがいいかなぁ。一度見直す必要があるなぁ。

ProductName Coleman(コールマン) キッズマミー/0 オレンジ 170S0205J

Coleman(コールマン) / 3680円 ( 2008-09-18 )


あと地震後はちょっと慌てるのでチェックリストにして玄関に置いておけばいいかもしれんな。

地震で停電が夜中まで続いた

金曜は風邪で会社を休んでいたのだが、コード読んでたら15時くらいに自宅サーバーが突然停電と同時に落ちて、すぐに強い揺れ。

そのまま夜中まで停電に突入、マンションの上階に住んでいるので停電=断水を意味する。さらに昇降式の車庫を使っているので危うく車も出せないパターンであったが、たまたま妻の平置きの駐車場に一時駐車していたために、娘と息子を幼稚園に迎えに行けた。地下式駐車場に入れてたら、徒歩お迎えだし、もし御殿場に出社してたらどうなっていただろうと考えるとゾッとする。あんまり長距離通勤するのも考えものか。

固定電話はもちろん、携帯電話(softbank)は全然つながらずgmail経由で妻とやり取り。妻は最近はiPadを持って出かけて行くことが多くなったので連絡とれた。

夜は停電のためライトが何本か使えたがちょっと暗かった。emobileが使えたのでmacbookから共有させてみんなでネットにアクセスしてた。CQW-MRBは2時間くらいしかもたないから、D02HWをmacbookに差してもそんなに変わらんね。

災害用に水とか食料とかバッグに詰め込んであるのでいつでも抱えて出られる状態にはなっているのだけど、実際に停電、断水状態で夜を過ごしてみて気づいたことがいくつかあるのでメモっておく。

  • 固定電話も携帯電話もつながらなかった。twitter,gmail,skypeのほうが災害時の通信手段としてはより良い
  • 停電時の夜の明かりは重要。ライトだとそんなに明るくないし、安心感を得る為にもLEDランタンを常備しておく必要性はある
  • マンション上階だと水はちょっと多めに用意しておく必要がある、断水前に風呂に水を貯めるとかできない(停電と同時に断水してしまうので)

とりあえずLEDランタンは1つ発注しておこう。単三を単一として使うためのスペーサーも必要だな。

風邪はもちろん悪化した。


110312 追記

あとはスマートフォン用の予備電源確保かな

Pythonのinspectモジュールを読んでみた。

今日も体調がすぐれないのというか、余計ひどくなった気がする(喉痛い)ので会社を休む。有休あまりまくってるしまぁここらへんで消費するのもいいかなと。

寝ながら本を読むにも軽めのちょうどいいのがないので、ソースコードリーディングでもとinspect読んでみた

getargs,getsource,classify_class_attrsあたりは参考になった。

こんな感じでK-meansのコードがあったとする。

from itertools import groupby
from math import sqrt

zipWith = lambda f, xs, ys : [f(x, y) for x,y in zip(xs, ys)]
snd  = lambda x: x[1]
fst  = lambda x: x[0]
euclid  = lambda x, y : (x-y)**2

def distance(a,b): 
    return sqrt(sum(zipWith(euclid,a,b)))

def centroid(clusters): 
    sums = reduce(lambda x,y: zipWith(lambda a,b:a+b,x,y),clusters)
    return map(lambda x: x / float(len(clusters)), sums)

def closest(pts, pt):
    closest_ct = pts[0]
    for ct in pts[1:]:
        if distance(pt,closest_ct) > distance(pt,ct):
            closest_ct = ct
    return closest_ct

def recluster_(centroids,points):
    reclustered = [(closest(centroids,a), a) for a in points]
    reclustered.sort()
    return [map(snd,list(g)) for k, g in groupby(reclustered, fst)]

def recluster(clusters):
    centroids = map(centroid, clusters)
    concated_clusters = reduce(lambda a,b: a+b, clusters)
    return recluster_(centroids,concated_clusters)

def part(l,points):
    size = len(l)/points
    return [l[i:i+size] for i in range(0,len(l),size)]

def kmeans(k,points):
    cluster = part(k,points)
    newcluster = recluster(cluster)
    while(cluster !=  newcluster):
        cluster = newcluster
        newcluster = recluster(cluster)
    return newcluster

if __name__ == "__main__":
    pts = [[1,2,4],[1,3,3],[4,3,0],[2,5,1],[7,3,8],[0,0,0],[4,3,2],[6,1,8]]
    print kmeans(pts,3)

モジュールロード

>>> import kmeans
>>> import inspect

どんな関数があったかなぁというのは、まぁdirでわかる

>>> dir(kmeans)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', \
'centroid', 'closest', 'distance', 'euclid', 'fst', 'groupby', 'kmeans', \
'part', 'recluster', 'recluster_', 'snd', 'sqrt', 'zipWith']

引数どうだっけ?となったばあいにはgetargsつかえばいいけどコードオブジェクトを引数にとるのでfunc_codeを渡してる

>>> inspect.getargs(kmeans.distance.func_code)
Arguments(args=['a', 'b'], varargs=None, keywords=None)

distanceって何の距離計算してんだっけ(マンハッタン?ユークリッド?)ソースみたいなあってなったらgetsource

>>> inspect.getsource(kmeans.distance)
'def distance(a,b): \n    return sqrt(sum(zipWith(euclid,a,b)))\n'
>>> inspect.getsource(kmeans.euclid)
'euclid  = lambda x, y : (x-y)**2\n'

というわけでユークリッド距離で定義された距離でのK-meansのコードだということがわかる。

>>> inspect.getfile(kmeans.distance)
'kmeans.py'
>>> inspect.getabsfile(kmeans.distance)
'/Users/kzfm/python/kmeans.py'

getabsfileでファイルの場所探してemacsで開いて直接読んじゃうことのほうが多いかもしれんけど。