たけのこブログ

凡人が頑張って背伸びするブログ

JuliaでBitArray{n}をArray{Bool, n}に変換する方法

スパイク関連のニューラルネットを作っていたりすると特定の条件下でtrue/flaseを1 or 0に変換された配列を使いたくなる時がありますが、例えばiszero.やisone.で要素ごとに生成された乱数を1 or 0で纏めようとすると、BitArrayで出てきてしまいます。

spikes = rand(0:3,100)
spikes = isone.(spikes)

結果:
100-element BitArray{1}:

これでも問題ないのですが、個人的にはなるべく配列で関数内部を処理したいことが多いです。例えば以下のように配列で処理したい関数を作ります。

function func_call!(spikes::Vector{Bool})
    hogehogeな処理をする
end

そして、先程のspikesを入力としてfunc_call!に入れると配列ではないのでmethod errorになってしまいます。

func_call!(spikes)

MethodError: no method matching func_call!( ::BitArray{1})
Closest candidates are:
  func_call!(::Array{Bool,1}) at In[1]:1

BitArrayとArray{Bool}の違いについては以下のstackoverflowにも説明されています。

stackoverflow.com

簡単に説明すると、Arrayはtrue/falseをそれぞれBoolとして格納していて、それぞれがUInt8で表現されています。8ビット=1バイトになりますので、Array{Bool}の場合は格納するためにNバイトの容量が必要になります。

一方で、BitArrayはtrue/falseを一つのビットで表現しており、8つのビットがUInt8に格納される方式になります。従って、Array{Bool}と比較するとN/8バイトしか必要としないメリットがあります。また、ビット操作を行うことができるのも魅力です。

違いをまとめると、以下のようになります。

・Array{Bool}...一つずつの要素をUInt8(1バイト)で表現

・BitArray...一つずつの要素を1ビットで表現したものを8つ集めてUInt8で表現

しかし、なるべくこちらとしては「配列で扱いたい」ので、BitArrayではなくArray{Bool}に変換したいです。変換方法についてですが、juliaはcollectで簡単に配列として変換することができます。

spikes = rand(0:3,100)
spikes = collect(isone.(spikes))

結果:
100-element Array{Bool,1}:

まとめ

今回はjuliaでのBitArrayとArray{Bool}の違いを説明して、BitArrayからArray{Bool}に変換する方法を説明しました。