なまもの備忘録

気になったことをつらつらと書いていきます

(Ruby) Hashの要素を非破壊的に削除する

こういう欲求に出くわすたびに一々調べて、思い出すのに割合時間を喰っている気がするので。 "Ruby"、"Hash"、"要素"、"非破壊的"、"削除"、でこの方法が引っかかる様にしたかったのが大きいです。

結論

rejectを使う。

[41] pry(main)> hash = {a: 1, b: 2, c: 3}
=> {:a=>1, :b=>2, :c=>3}
[42] pry(main)> hash.reject {|key| key == :a}
=> {:b=>2, :c=>3}
[43] pry(main)> hash
=> {:a=>1, :b=>2, :c=>3}

deleteは破壊的なので使いづらいですね。 ActiveSupportHash#exceptも手軽ですが、バニラなRubyだけで終わらせられると嬉しいこともあるので。

環境

[47] pry(main)> pry-version
Pry version: 0.12.2 on Ruby 2.5.1.

tmuxでのコピー内容をMacのクリップボードに共有する[emacsキーバインド]

tmuxでコピーしたものをMacクリップボードに流し込めると割合便利なことは多い。 ただ、いざこの方法を調べようとするとviキーバインドの場合の設定方法ばかり出てくるので、せっかくなので纏めて置くことにした。

  1. 必要なソフトをインストールする。
$ brew install reattach-to-user-namespace
  1. .tmux.confの設定をする。
# Setup 'C-@' to begin selection as in Emacs
bind-key -T copy-mode C-@ send -X begin-selection
bind-key -T copy-mode C-w send -X copy-pipe "reattach-to-user-namespace pbcopy"

# Update default binding of `Enter` to also use copy-pipe
unbind -T copy-mode Enter
bind-key -T copy-mode Enter send -X copy-pipe "reattach-to-user-namespace pbcopy"

.tmux.confにはtmuxのバージョン2.3と2.4の間で互換性のない変更が入っているので、2.3以前の場合は別の方法で設定する必要がある(ググればすぐ出て来る)。

tmux -V
tmux 2.7

Macのバージョンは10.13.2。

参考

scipyによる3次スプライン補完

未知の関数に出会った時3次スプライン補完をしたいと思うのは人類の普遍的欲求です。 普遍的欲求はだいたいpythonのライブラリが満たしてくれるもので、今回のケースではscipyがその役割を担ってくれます。

scipyの3次スプライン補完についてはいくつか日本語解説ページがあるのですが、

qiita.com

ここで使われているkind='cubic'interp1d関数だと、スプライン補完の係数取得に少々非自明な処理をする必要が出てきます。 人間が3次スプライン補完をするときって、欲しいものは大抵関数そのものではなく係数なので、これは困りますね。

さて、scipyではinterp1d以外にもCubicSpline関数で3次スプライン補完を実行することができ、こちらを使えばこの問題は解決します。 使い方は以下

import numpy
from scipy import interpolate
import matplotlib.pyplot as plt

if __name__ == '__main__':

    x_coordinates = []
    y_coordinates = []
    for line in open('test.txt', 'r'):
        point = [float(coord.split()[0]) for coord in line.split(',')]
        x_coordinates.append(point[0])
        y_coordinates.append(point[1])
        
    spline_func = interpolate.CubicSpline(x_coordinates, y_coordinates)
    print(spline_func.c) # ここで係数を取得しています
    
    x_res = numpy.linspace(1, 5, 200)
    y_res = spline_func(x_res)
   
    plt.plot(x_coordinates, y_coordinates, 'o', x_res, y_res)
    plt.show()

CubicSplineの返り値であるPPolyオブジェクトのcを呼び出すことで、係数にアクセスしています。

テストデータとしては下記を使用しました。

1.5, 1.65
1.677, 5.64
2.3, 5.53
3.0, 4.354
3.8, 3.555

出力グラフ

f:id:purple-apple:20180226130144p:plain

標準出力(コメント部分は後から追記)

[[ 25.17215028  25.17215028  -3.16687764  -3.16687764] # 3次の係数
 [-52.99186318 -39.62545138   7.42129748   0.77085443] # 2次の係数
 [ 31.13331437  14.74004969  -5.32313819   0.41136815]    # 1次の係数 
 [  1.65         5.64         5.53         4.354     ]]    # 定数項

バージョン情報

$ python -V
Python 3.5.2
>>> import scipy as sp
>>> sp.version.full_version
'0.18.1'

参考

https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.CubicSpline.html

https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.PPoly.html#scipy.interpolate.PPoly

バランスドネットワーク理論

「バランスドネットワーク」という言葉は、Computational Neurosience界隈では割とよく聞く言葉じゃないのかな、と思うのですが、日本語で検索をかけても引っかかる文献があまりないので、勉強がてらにメモを残すことにしました。下記の記事が綺麗にまとまっていそうだったので、その要約になっています。管理人はこの分野に関してほぼ素人なので、間違いなどありましたらご指摘いただけると幸いです。

Pierre Yger » The Balanced Network

背景

大枠として、in vivo実験で観察されるニューロンの不規則な発火をネットワークを介してモデリングしたい、という要求がある。 この際、天下り的にネットワークに確率的なinputを与えないとすると、ニューロンに大きな揺らぎを導入して不規則性を付与することになる。具体的には、興奮性ニューロンと抑制性ニューロンが重み付き結合を介して閾値を下回った状態で釣り合い、揺らぎが上振れした時に閾値を超えてスパイクする。

バランスドネットワークとは

integrate-and-fire modelのニューロンで形成されたスパースなネットワークのモデル。上記のような仕組みで不規則な発火を実現する。

  • 興奮性ニューロンと抑制性ニューロンの二つの集団からなり、それぞれのニューロンは確率的に重みを持って結合している。
  • 一般に、ニューロンは相互の結合以外にもいくつかのパラメータの影響を受ける。外部からのノイズを入力として受け取るケースなどがメジャー。 f:id:purple-apple:20180221111722p:plain

ネットワークの動態は、同期的/非同期的(ニューロン集団について)、規則的/不規則的(特定のニューロンについて)などの観点から分類することができる。

  • 同期的/非同期的の分類は、特定集団での発火率が一定に近いかどうかで判定することができる。一定に近ければ非同期的で、振動していれば同期的。
  • 規則的/不規則的の分類は、変動係数を用いて判定されることが多い。変動係数は、ポアッソン分布に基づく発火であれば1に近く、発火が規則的であればあるほど0に近づく。

in vivoでの発火計測では変動係数が1に近い値を示すことが多く、そのため、モデルも非同期現象の再現に焦点を当てることが多い。

f:id:purple-apple:20180221111828p:plain

上図はネットワークの動態を先の観点から4種類に分類したもので、同期的/規則的(左上)、同期的/不規則的(右上)、非同期的/規則的(左下)、非同期的/不規則的(右下)となっている。

関数的メソッドをメソッド引数として渡す

関数的メソッドを引数にとる関数の定義がしたかったのだが、調べてもなかなか丁度良い記事がなかったのでメモ代わりに。 関数的メソッドとは明示的なレシーバを持たないメソッドのこと。素直にグローバルスコープにメソッドを定義するとこれになる。

def test_func(a,b,c)        
  p a + b + c
end

def test_func_func(func)    
  func.call(1,2,3)
end

func = BasicObject.method(:test_func)
test_func_func(func)

# 6
# => 6

どうもにメソッドに引数としてメソッドを渡すときはObject#methodを使ってメソッドを一度オブジェクト化する見たいなのだが、Object#methodは呼び出し時にメソッドのレシーバを明示する必要がある。 では関数的メソッドのレシーバとして記述するオブジェクトは何が適切なのか、という話になるが、これについて明確にこれが良い、というものは分からなかった。 例には、取り敢えず余計な要素を持たないBasicObjectなんか適しているんじゃないだろうか、という推測のもとBasicObjectを用いている。 どなたかご存知でしたら教えてください。

20/2/3追記

id:ikngttyさんがコメントで下記のことを教えてくださいました。

  • トップレベル(グローバルスコープ)に定義されたメソッドはObjectのprivateインスタンスメソッドとして定義される。
  • トップレベルでの挙動はself.test_func(args...)に相当(selfはmainを指す)する。
  • selfは省略可能なので、method(:test_func)でのオブジェクト化が可能。

ですので、上記を踏まえると以下の書き方が適切に思えます。

def test_func(a,b,c)        
  p a + b + c
end

def test_func_func(func)    
  func.call(1,2,3)
end

func = Object.new.method(:test_func) # メソッドの所属先を明示的に表記する場合
func = method(:test_func) # 簡潔に表記する場合
test_func_func(func)

id:ikngttyさんもおすすめされていますが、トップレベルでレシーバが省略されている時点Objectのメソッドであることは確定するので、selfを省略する書き方が個人的にもしっくりきます。メソッドの所属先を明示するためだけにObjectクラスのインスタンスを生成するのはかなり気が引けます。 また、こちらもid:ikngttyさんがおすすめされていますが、特にメソッドを使い回すなどしない場合であればラムダやProcが適切そうです。

いただいたコメントにとても丁寧な解説がありますので、そちらも是非ご覧下さい。

他参考:Ruby のトップレベルメソッドって結局なんなの - Qiita

20/2/25追記

id:ikngttyにいただいたコメントがMarkdown形式のものだったので、許可をいただき、コメントをそのままここに載せさせていただくことにしました。 大変丁寧な解説をありがとうございました。

以下コメントです。

取り敢えず余計な要素を持たないBasicObjectなんか適しているんじゃないだろうか、という推測のもとBasicObjectを用いている。

残念ながら、お望みの効果は得られていない状態になっています。

Object#method と Module#instance_method

Ruby には似たような役割を持つメソッドとして、Object#methodModule#instance_method があります。

# Object#method
abs123 = -123.method(:abs)
p abs123 # => #<Method: Integer#abs>
p abs123.call # => 123

# Module#instance_method
abs = Integer.instance_method(:abs)
p abs # => #<UnboundMethod: Integer#abs>
abs234 = abs.bind(-234)
p abs234 # => #<Method: Integer#abs>
p abs234.call # => 234

つまり、以下の2つが大体同じ関係になっています。

インスタンス.method(:name) クラス.instance_method(:name) これを混同して クラス.method(:name) としてしまうと、以下のようになります。

abs = Integer.method(:abs) # => undefined method `abs' for class `#<Class:Integer>' (NameError)

本記事の

func = BasicObject.method(:test_func)

こちらも同様の構造です。

クラス.method(:name) では何が起きているのか

紛らわしい文章になりますが、クラスをインスタンスとして見た場合、それのクラスはClass クラスです。

紛らわしいので、以下のコードを見た方がおそらく早いです。

class Foo
end

foo = Foo.new
p foo.class # => Foo
p Foo.class # => Class

p BasicObject.class # => Class

なので BasicObject.method(:name)Class.instance_method(:name) と意味合いが近いです。

p BasicObject.methods == Class.instance_methods # => true

これは BasicObject に限らず全てのクラスについて言えます。

p Foo.methods == Class.instance_methods # => true

つまり、以下の2つのコードは同じということです。

func = BasicObject.method(:test_func)
func = Foo.method(:test_func)

この辺が「(BasicObject を用いても)お望みの効果が得られてない」という根拠です。

「グローバルスコープに定義したメソッド」の正体

では改めて、何がレシーバーとして適切なのか。これは、「グローバルスコープに定義したメソッド」について詳しく調べることが近道となります。

main オブジェクトについてのリファレンスに、この辺の挙動が詳しく書いてあります。

要約

トップレベルでの self を表すオブジェクトです。

main では参照できない事に注意してください。トップレベルで self から参照してください。

トップレベルで定義したメソッドは Object の private インスタンスメソッドと して定義されます。

(太字による強調はコメント主の私による)

例えば以下のコードで test_func を呼べるのも、test_func が「グローバルスコープ」だからなのではなく、 FooObject を継承してるから、というのが真相です。

def test_func(a,b,c)
p a + b + c
end

class Foo
def hoge
test_func(2, 3, 4)
end
end

Foo.new.hoge # => 9

また、BasicObject.method(:test_func) がうまく動いたのも、ClassObject を継承しているからです。

余談ですが、pputs などの多くの組み込み関数も似たような仕組みになっています。実はこれらは Kernel クラスのメソッドとして定義されていて、 Object はこの Kernel を継承しています。なので、test_func と同様に pputs もいろんな場所から呼べるというわけです。

適切なレシーバーは何なのか

ここまでを踏まえてようやく本題です。

案1. BasicObject のインスタンス

とりあえず記事内での考えを延長して、以下のようなコードを考えたくなるかもしれません。しかしこれはエラーになります。

func = BasicObject.new.method(:test_func) # => undefined method `method' for #<BasicObject:0x00007f9c988641b0> (NoMethodError)

理由はもちろん、test_funcObject のメソッドだからであり、BasicObject には含まれないからです。

案2. Object のインスタンス

じゃあ Object なら動くのか。その通りです。

func = Object.new.method(:test_func)
test_func_func(func) # => 6

案3. main オブジェクト(オススメ)

トップレベルで動かすのと全く同じ状態で渡したいなら、トップレベル(=main オブジェクト)をレシーバーにするのが良いです。上で抜粋した通り、main オブジェクトは self で参照します。

func = self.method(:test_func)
test_func_func(func) # => 6

なお、self は省略できます。

func = method(:test_func)
test_func_func(func) # => 6

なんと、「レシーバーなんて要らなかったんや!」というオチ。

案4. そもそもメソッドを使わない(一番オススメ)

レシーバーが必要なのはメソッドだからです。Proclambda を使えばレシーバー無しの「関数」が扱えます。

test_func = lambda { |a, b, c| p a + b + c }

def test_func_func(func)
func.call(1, 2, 3)
end

test_func_func(test_func) # => 6

ちなみに lambda の代わりとして -> という特殊なリテラル記法もあります。

test_func = ->(a, b, c) { p a + b + c }

以上、コメントで長々と書いてしまいましたが、参考になりましたら幸いです。

ブロック付きgsubの返り値の違いについて

基本的な話なのだがRubyのブロックには二通りの記法がある。

Objects.each { |object|
    object.method
}

Objects.each do  |object|
    object.method
end

だ。

僕は、手続き上両記法は等価なものだと思っていたのだが、どうもそうでは無いらしい、ということが分かったのでメモとして残しておく。

違い

さて、どのようなケースで等価ではないかというと、下記のような時だ。

pry(main)> s = "hello, world"
pry(main)> puts s.gsub(/\w+/) {|word| word.capitalize }
Hello, World
=> nil

このコードをdo...endによる記法で書くと以下の様な挙動になる。

pry(main)> s = "hello, world"
pry(main)> puts s.gsub(/\w+/) do |word|
pry(main)*   word.capitalize
pry(main)* end
#<Enumerator:0x000056474a99ef70> 
=> nil 

原因

原因は、{...}do...endの結合の強さの違いにある。 Ruby 2.4.0 リファレンスマニュアルには下記のようにある

{ ... } の方が do ... end ブロックよりも強く結合します。 次に例を挙げますが、このような違いが影響するコードは読み辛いので避けましょう:

foobar a, b do .. end # foobarの引数はa, bの値とブロック
foobar a, b { .. } # ブロックはメソッドbの引数、aの値とbの返り値とがfoobarの引数

つまり、

pry(main)> s = "hello, world"
pry(main)> puts s.gsub(/\w+/) do |word|
pry(main)*   word.capitalize
pry(main)* end
#<Enumerator:0x000056474a99ef70> 
=> nil 

では、putsメソッドの引数はs.gsub(/\w+/)do...endブロックと解釈されているのだ。

それぞれ、分けて実行してみると、以下のようになる

pry(main)> puts s.gsub(/\w+/)
#<Enumerator:0x0000560d6a307a78>
=> nil
pry(main)> puts do
pry(main)*   s = 10
pry(main)* end

=> nil

なるほどこの2つが合わさっていたのか。

Rubyではブロックを取るメソッドをブロックを省略して書いた場合、Enumeratorオブジェクトを返す。 gsubの引数に正規表現パターンのみを与えた場合、ブロックを使っての置換の記法になるため、1つめはこれだろう。

2つめはなんだろうか。 チラッと調べてみた所、ブロックを取らないメソッド(内部にyieldがない)にブロックを渡した場合、ブロックは単に無視される、というが引っかかった。 多分これなんじゃないだろうか。こっちについてはもう少し確認する必要がありそうだけれども。

バージョン

$ ruby --version
ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-linux]
=> nil 

参考

Enumerator とブロックの省略 - まめめも

ブロックをdo…endで書くか{…}で書くかにより挙動が変わる例 - Qiita

ブロックを与えない場合にEnumeratorを返すメソッドを作る - Qiita

Ubuntu 16.04 LTSに最新のrbenvを入れた

概要

手持ちのUbuntu 16.04 LTSにaptでrbenvを入れたのだが、バージョンが古くて2.4系のrubyがインストールできなかった。 どうしても2.4系が使いたい気持ちだったため、purgeして野良ビルドを試みた。 その時の記録。

参考

ほぼ上記の内容の通りなので、英語が読めるならこっちを読めばいい。

rbenvのビルド

# リポジトリをクローンしてくる
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv 
# rbenvを高速化するためにbash拡張を試みる。失敗しても別に気にしなくて良い
$ cd ~/.rbenv && src/configure && make -C src
# パスを通す。zshを使うなら~/.zshrcにリダイレクトする
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc

以上で完了。下記を実行して、

$ curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-doctor | bash

下のような表示が出ればうまくビルドできている。

Checking for `rbenv' in PATH: /usr/local/bin/rbenv
Checking for rbenv shims in PATH: OK
Checking `rbenv install' support: bash: line 114: : command not found ()
Counting installed Ruby versions: none
  There aren't any Ruby versions installed under `~/.rbenv/versions'.
  You can install Ruby versions like so: rbenv install 2.2.4
Checking RubyGems settings: OK
Auditing installed plugins: OK

ruby-buildのビルド

rbenv installコマンドを使えるようにするために、ruby-buildをインストールする。 rbenvのプラグインとしてruby-buildをインストールする。

# プラグイン用ディレクトリの作成
$ mkdir -p "$(rbenv root)"/plugins
# 先のディレクトリ内にリポジトリをクローンしてくる
$ git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build

インストール可能なrubyバージョンの確認

$ rbenv install --list

で確認できる。後は、希望のバージョンを

rbenv install 2.4.2

でインストールすれば良い。