元バイオ系

元バイオウェット系がデータサイエンスやらを勉強していくブログ。 基本自分用のまとめ。

Julia tips #5: MCMC法(Metropolis-Haisting法)を実装してみた

JuliaにてMCMC法(Metropolis-Haistings法)を実装してみました。

  • コードの利用・改変・再配布は自由にして構いませんが、何か起きても責任は取りません。
  • 一部いらない変数や無駄実装が混じってます。動作に問題はありません。バイオ実験系なので許して...。
  • 一番下にコードを全部まとめたものを書いておきました。 パパっと試してみたい方はコピペしてどうぞ。

環境

実装

使うパッケージのインポート

using Distributions
using Gadfly
using StatsBase

目標分布を定義する

MCMCでよく出てくる有名なあれです。

μ = [-5.0, -5, 5.0]
σ = [1.0, 0.1, 1.0] 

function target(x::Array{Float64, 1})
    arr = zeros(length(x))
    Normal_val_1(x) = 0.45 * 1/sqrt(2π*σ[1]^2)*exp(-(x-μ[1])^2/(2σ[1]^2))
    Normal_val_2(x) = 0.45 * 1/sqrt(2π*σ[2]^2)*exp(-(x-μ[2])^2/(2σ[2]^2))
    Normal_val_3(x) = 0.1 * 1/sqrt(2π*σ[3]^2)*exp(-(x-μ[3])^2/(2σ[3]^2))
    for i in 1:length(x)
        arr[i] = Normal_val_1(x[i]) + Normal_val_2(x[i]) + Normal_val_3(x[i])
    end
    
    return arr
end

function target(x::Float64)
    arr = zeros(length(x))
    Normal_val_1(x) = 0.45 * 1/sqrt(2π*σ[1]^2)*exp(-(x-μ[1])^2/(2σ[1]^2))
    Normal_val_2(x) = 0.45 * 1/sqrt(2π*σ[2]^2)*exp(-(x-μ[2])^2/(2σ[2]^2))
    Normal_val_3(x) = 0.1 * 1/sqrt(2π*σ[3]^2)*exp(-(x-μ[3])^2/(2σ[3]^2))
    val = Normal_val_1(x) + Normal_val_2(x) + Normal_val_3(x)
    return val
end

多重ディスパッチを利用して、スカラーが来たら値を一つだけ返し、ベクトルが来たらベクトルを返すようになっています。
変な分岐処理を書かなくていいので楽ですね。

上記の関数を定義後に、このコードで分布を見ることができます。

x = Array{Float64}(linspace(-10, 10, 1000))
y = target(x)
p=plot(x=x, y=y, Geom.line)

こんな感じ。 f:id:hotoke-X:20180121050147p:plain

Sampler型を定義

Pythonのようにクラスを作って、メンバ変数としてMCMC法の状態を保持したいなーと思ったのですが、JuliaにはPythonのようなクラスがありません。*
無いならそれっぽい使い方ができればいいじゃん!
という発想です。

ここで定義した型をMCMCモジュールへ投げて、変数の保持に使います。

mutable struct Sampler
    x0::Float64
    x_present::Float64
    target::Any
    propose_next::Any
    burn_in::Int
    count::Int
    acceptance::Float64
    seed::Int
    random_state::MersenneTwister
end

各変数の説明
x0: 初期値
x_present: 現在の値を保持
target: 目標分布の密度関数
propose: 次点を生成する関数 burn_in: 焼きなまし期間
count: 現在のステップ数
acceptance: 採択回数(本当は採択率を入れたいが考え中。今回は不要。)
seed: 乱数の初期パラメータ
random_state: 乱数ジェネレータ(これを保持することで、途中からサンプリングを再開できる)

回してみる

seed = 0
rng = srand(seed)
gaussian = Normal(0,2)
uniform = Uniform(-10, 10)
inits = rand(uniform)
target = target
generator(x) = x + 0.5*rand(gaussian)
burn_in = 10000
num_sample = 1000000
cnt = 0
acceptance = 0

sampler = Sampler(inits, inits, target, generator, burn_in, cnt, acceptance, seed, rng)
burn_in = MCMC.burn_in(sampler)
samples = MCMC.run(sampler, num_sample)

結果のプロット

set_default_plot_size(9inch, 12inch/golden)

# プロット範囲
_start = 990000
_last = 1000000

p1 = plot(y=autocor(samples), Geom.line, Guide.ylabel("Autocorrelation\ncoefficient"),
    Guide.xlabel("Lag"), Guide.title("Autocorrelation"))
p2 = plot(x=_start:_last, y=samples[_start:_last], Geom.line,
    Guide.xlabel("Steps"), Guide.ylabel("Value"), Guide.title("Trajectory"))
p3 = plot(layer(x=x, y=y, Geom.line, Theme(default_color="magenta")),
     layer(x=samples, Geom.histogram(density=true)),
     Guide.ylabel("Frequency"), Guide.xlabel("Samples"),
     Guide.title("Posterior distribution"),
     Guide.manual_color_key("Color", ["Target", "Posterir"], ["magenta", "cyan"]))

p = title(vstack(hstack(p1, p2), p3), "Metropolis-Hastings (σ=2)",  Compose.fontsize(14pt))

f:id:hotoke-X:20180121050013p:plain

できました。

全コードまとめ

using Distributions
using Gadfly
using StatsBase
using Cairo

# 目標分布の定義--------------------------
μ = [-5.0, -5, 5.0]
σ = [1.0, 0.1, 1.0] 

function target(x::Array{Float64, 1})
    arr = zeros(length(x))
    Normal_val_1(x) = 0.45 * 1/sqrt(2π*σ[1]^2)*exp(-(x-μ[1])^2/(2σ[1]^2))
    Normal_val_2(x) = 0.45 * 1/sqrt(2π*σ[2]^2)*exp(-(x-μ[2])^2/(2σ[2]^2))
    Normal_val_3(x) = 0.1 * 1/sqrt(2π*σ[3]^2)*exp(-(x-μ[3])^2/(2σ[3]^2))
    for i in 1:length(x)
        arr[i] = Normal_val_1(x[i]) + Normal_val_2(x[i]) + Normal_val_3(x[i])
    end
    
    return arr
end

function target(x::Float64)
    arr = zeros(length(x))
    Normal_val_1(x) = 0.45 * 1/sqrt(2π*σ[1]^2)*exp(-(x-μ[1])^2/(2σ[1]^2))
    Normal_val_2(x) = 0.45 * 1/sqrt(2π*σ[2]^2)*exp(-(x-μ[2])^2/(2σ[2]^2))
    Normal_val_3(x) = 0.1 * 1/sqrt(2π*σ[3]^2)*exp(-(x-μ[3])^2/(2σ[3]^2))
    val = Normal_val_1(x) + Normal_val_2(x) + Normal_val_3(x)
    return val
end

# Sampler型を定義(MCMCモジュール内で状態を保持する)
mutable struct Sampler
    x0::Float64
    x_present::Float64
    target::Any
    propose_next::Any
    burn_in::Int
    count::Int
    acceptance::Float64
    seed::Int
    random_state::MersenneTwister
end

# MCMC法の本体
module MCMC
    function present(sampler)
        return sampler.x_present
    end

    function next(sampler)
        proposed = sampler.propose_next(sampler.x_present)
        odds = sampler.target(proposed)/sampler.target(sampler.x_present)
    
        if rand(sampler.random_state) < odds
            sampler.x_present = proposed
            sampler.acceptance += 1
            return proposed
        else
            return sampler.x_present
        end
    end

    function burn_in(sampler)
        arr = zeros(sampler.burn_in)
        for i in 1:sampler.burn_in
            arr[i] = next(sampler)
            sampler.count += 1
        end
        sampler.acceptance = 0
        return arr
    end

    function run(sampler, n_steps)
        arr = zeros(n_steps)
        for i in 1:n_steps
            arr[i] = next(sampler)
            sampler.count += 1
        end
        return arr
    end

end

# 実行コード
seed = 0
rng = srand(seed)
gaussian = Normal(0,2)
uniform = Uniform(-10, 10)
inits = rand(uniform)
target = target
generator(x) = x + 0.5*rand(gaussian)
burn_in = 10000
num_sample = 1000000
cnt = 0
acceptance = 0

sampler = Sampler(inits, inits, target, generator, burn_in, cnt, acceptance, seed, rng)
burn_in = MCMC.burn_in(sampler)
samples = MCMC.run(sampler, num_sample)


# 結果のプロット
set_default_plot_size(9inch, 12inch/golden)

_start = 990000
_last = 1000000

p1 = plot(y=autocor(samples), Geom.line, Guide.ylabel("Autocorrelation\ncoefficient"),
    Guide.xlabel("Lag"), Guide.title("Autocorrelation"))
p2 = plot(x=_start:_last, y=samples[_start:_last], Geom.line,
    Guide.xlabel("Steps"), Guide.ylabel("Value"), Guide.title("Trajectory"))
p3 = plot(layer(x=x, y=y, Geom.line, Theme(default_color="magenta")),
     layer(x=samples, Geom.histogram(density=true)),
     Guide.ylabel("Frequency"), Guide.xlabel("Samples"),
     Guide.title("Posterior distribution"),
     Guide.manual_color_key("Color", ["Target", "Posterir"], ["magenta", "cyan"]))

p = title(vstack(hstack(p1, p2), p3), "Metropolis-Hastings (σ=2)",  Compose.fontsize(14pt))

*burn in 期間が短いときに途中から再計算させたいので。

Julia tips #4: Cairoのインストールに失敗する

環境


JuliaでグラフをプロットするライブラリとしてはGadlyが有名?ですが、プロットをpng形式で保存するためにはCairoというパッケージが必要です。

そこでPkg.add("Cairo")したらインストールに失敗したというお話。
解決法も書いておきます。

エラーメッセージ

Pkg.add("Cairo")したら何やらダウンロードエラーが...

WARNING: Unknown download failure, error code: 2148270086
WARNING: Retry 1/5 downloading: https://cache.julialang.org/http://download.opensuse.org/repositories/windows:/mingw:/win64/openSUSE_Leap_42.2/noarch/mingw64-zlib1-1.2.8-8.15.noarch.rpm
WARNING: Unknown download failure, error code: 2148270086
WARNING: Retry 2/5 downloading: https://cache.julialang.org/http://download.opensuse.org/repositories/windows:/mingw:/win64/openSUSE_Leap_42.2/noarch/mingw64-zlib1-1.2.8-8.15.noarch.rpm
WARNING: Unknown download failure, error code: 2148270086
WARNING: Retry 3/5 downloading: https://cache.julialang.org/http://download.opensuse.org/repositories/windows:/mingw:/win64/openSUSE_Leap_42.2/noarch/mingw64-zlib1-1.2.8-8.15.noarch.rpm
WARNING: Unknown download failure, error code: 2148270086
WARNING: Retry 4/5 downloading: https://cache.julialang.org/http://download.opensuse.org/repositories/windows:/mingw:/win64/openSUSE_Leap_42.2/noarch/mingw64-zlib1-1.2.8-8.15.noarch.rpm
WARNING: Unknown download failure, error code: 2148270086
WARNING: Retry 5/5 downloading: https://cache.julialang.org/http://download.opensuse.org/repositories/windows:/mingw:/win64/openSUSE_Leap_42.2/noarch/mingw64-zlib1-1.2.8-8.15.noarch.rpm
INFO: try running WinRPM.update() and retrying the install

大事なのは最後の1行のメッセージでした。
この通りにやってみるとインストールできました。

julia> using WinRPM
julia> WinRPM.update()

最後にさっきインストールに失敗したCairoをビルドし直します。

Pkg.build(Cairo)

これでうまくインストールできました。

Julia tips #3: ODE solverの速度比較 with Python

JuliaではSundials.jlをインストールするだけで、SundialsのODEソルバ、CVODEが使えます!!(マニアックすぎ?)

未知システムのパラメータ推定をする際、数値積分区間をうまいこと刻まないと値が飛びすぎて計算できなかったり、刻む必要のないところで刻んでしまって計算不能に陥ることがあります。

そこでCVODEなどのAdaptive stepなODEソルバが必要なわけです。

何個か種類がありますが、有名どころでは

  • LSODA
  • CVODE

が2強といったところで、Pythonでよく使われるodeintもadaptive stepです(内部的にはLSODEとかいうやつらしいけど...良く知りません)。

じゃあ、JuliaでCVODEを呼び出して使うのと、Pythonでodeint使うのはどっちがどんくらい速いのよ?と思ったので比べてみました。

なお、Juliaのソルバについては比較してくれている方がいました。

CVODEの圧勝です。

Juliaのコードもこちらから借りてきて、Pythonと比較したいと思います。

qiita.com

実装


Julia(上記リンク先から部分的に拝借)

using Sundials

# 非線形パラメータ
mu = 0.2
# 関数定義
function vdp_sun(t, u, du)
    # dx/dt
    du[1] = u[2]
    # dy/dt
    du[2] = mu * (1.0 - u[1]^2.0) * u[2] - u[1]
    du
end
# パラメータ設定
u0 = [0.2; 0.2]
t = [0.0:0.1:10.0;]

Python (3.6)

import numpy as np
from scipy.integrate import odeint

# 非線形パラメータ
mu = 0.2
# 関数定義
def vdp_sun(u, t):
    # dx/dt
    dxdt = u[1]
    # dy/dt
    dydt = mu * (1.0 - u[0]**2.0) * u[1] - u[0]
    return [dxdt, dydt]
    
# パラメータ設定
u0 = [0.2, 0.2]
t = np.arange(0,10.1,0.1)
# メインの計算
res = odeint(vdp_sun, u0, t) 

速度比較

Juliaは1ループごとに出力、Pythonのtimeitではループにかかった平均時間を出力していますが、大雑把な比較はこれで良いでしょう。
見やすさのため10回だけ回しています。

Julia

res = Sundials.cvode(vdp_sun, u0, t);
for i in 1:10
    @time res = Sundials.cvode(vdp_sun, u0, t);
end

Python (3.6)

%timeit -n 10 odeint(vdp_sun, u0, t)

結果

Julia

  0.000206 seconds (1.81 k allocations: 43.734 KiB)
  0.000132 seconds (1.81 k allocations: 43.734 KiB)
  0.000130 seconds (1.81 k allocations: 43.734 KiB)
  0.000117 seconds (1.81 k allocations: 43.734 KiB)
  0.000118 seconds (1.81 k allocations: 43.734 KiB)
  0.000115 seconds (1.81 k allocations: 43.734 KiB)
  0.000115 seconds (1.81 k allocations: 43.734 KiB)
  0.000115 seconds (1.81 k allocations: 43.734 KiB)
  0.000116 seconds (1.81 k allocations: 43.734 KiB)
  0.000124 seconds (1.81 k allocations: 43.734 KiB)

Python (3.6)

716 µs ± 5.63 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

まとめると以下のようになります。

  • Julia: 128.8 µs ± 26.43 µs
  • Python: 716 µs ± 5.63 µs

Juliaの方が5倍ほど速い!

シミュレーションを何千回、何万回と繰り返すものにとっては5倍の高速化は結構大きいと思います。

予想ではもっと変わるかなと思っていたのですがこんなものでした。

Pythonを高速化

Pythonを高速化したら、Sundialsに迫るのでは??

と考えたので、numbaで高速化したPythonで戦ってみた。

odeintに渡す微分方程式jit+型指定すると速くなる。

from scipy.integrate import odeint
import numpy as np
from numba import jit

# 型指定jit, tが逐次的に渡されることに注意
@jit("float64[:](float64[:], float64)", nopython=True)  
def vdp_sun_jit(u, t):
    # dx/dt
    dxdt = u[1]
    # dy/dt
    dydt = mu * (1.0 - u[0]**2.0) * u[1] - u[0]
    return np.array([dxdt, dydt]).astype(np.float64)
    
# パラメータ設定
u0 = np.array([0.2, 0.2]).astype(np.float64)   # 渡す型に合わせる
t = np.arange(0,10.1,0.1).astype(np.float64)   # 渡す型に合わせる
# メインの計算
res = odeint(vdp_sun, u0, t)

%timeit -n 10 odeint(vdp_sun_jit, u0, t)

結果

387 µs ± 11.6 µs

うーん、速くはなりましたが2倍行かないくらいでしたね。

まとめ

  • Julia: 128.8 µs ± 26.43 µs
  • Python: 716 µs ± 5.63 µs
  • Python+numba: 387 µs ± 11.6 µs

やっぱSundials凄い。

数値計算ではJuliaを使おう!

Julia tips #2: ファイル検索

スタックオーバフローより。

「組み込み関数はないけどワンライナーで書けるよ」

とのこと。

関数化したほうが便利ですね。以下コードです。

searchdir(path,key) = filter(x->contains(x,key), readdir(path))

readdir (path)
渡したpathの中にあるディレクトリ、ファイルを文字列として出力してくれる

contains (x, key)
文字列 x に 文字列 key が含まれているかtrue or falseで返してくれる

filter (function, collection)
collectionを受け取る関数functionがtrueを返したら、そのcollectionのコピーを返す

例)

a = 1:10
julia> filter(isodd, a)
1
3
5
7
9

Julia tips #1:【超簡単】コードのテスト

テストマクロについてのメモ(2017/12/03時点)

環境

windows 10 Pro (Fall Creators Update)
WSL有効化済み
WSLのbashにて実行
環境構築の仕方はこちらをどうぞ

hotoke-x.hatenablog.com

テストマクロの使い方

まずはJuliaのバージョン確認から

$ julia --version
julia version 0.5.2

foo(x)という関数があったとして、その挙動を引数ごとにまとめて行う方法

julia> @testset "Foo Tests" begin
           @test foo("a")   == 1
           @test foo("ab")  == 4
           @test foo("abc") == 9
       end
Test Summary: | Pass  Total
Foo Tests     |    3      3

全部で3回テスト(Total)して、3回ともクリアしたぞ(Pass)って意味。

ネストしていても大丈夫

julia> @testset "Foo Tests" begin
           @testset "Animals" begin
               @test foo("cat") == 9
               @test foo("dog") == foo("cat")
           end
           @testset "Arrays $i" for i in 1:3
               @test foo(zeros(i)) == i^2
               @test foo(ones(i)) == i^2
           end
       end
Test Summary: | Pass  Total
Foo Tests     |    8      8

結果が全部まとめられているが、エラーを吐いている場合は展開して表示してくれる。

Arrays: Test Failed
  Expression: foo(ones(4)) == 15
   Evaluated: 16 == 15
 in record at test.jl:297
 in do_test at test.jl:191
Test Summary: | Pass  Fail  Total
Foo Tests     |    3     1      4
  Animals     |    2            2
  Arrays      |    1     1      2
ERROR: Some tests did not pass: 3 passed, 1 failed, 0 errored, 0 broken.
 in finish at test.jl:362

他にも色んなマクロがある

大体一緒か判定する

@test a≈b

≈は\approxと打った後にtabで表示される。

以下、エラーコードつき。

めっちゃ小さい数値誤差を許容して等しいかどうか判定

julia> @test_approx_eq 1. 0.999999999
ERROR: assertion failed: |1.0 - 0.999999999| < 2.220446049250313e-12
  1.0 = 1.0
  0.999999999 = 0.999999999
 in test_approx_eq at test.jl:75
 in test_approx_eq at test.jl:80

e-12なら通常使用なら問題なさそうかな?

許容誤差を設定して判定

 @test_approx_eq_eps 1. 0.999 1e-3
ERROR: assertion failed: |1.0 - 0.999| <= 0.001
  1.0 = 1.0
  0.999 = 0.999
  difference = 0.0010000000000000009 > 0.001
 in error at error.jl:22
 in test_approx_eq at test.jl:68

こんな書き方もあったりする。

julia> ≈(1, 0.999, atol=0.001)
true

julia> ≈(1, 0.999, atol=0.0001)
false

感想

Pythonでデコレータ書いたりするより遥かに簡単で良い。

Windows Subsystem for Linux + Python + Jupyter + Julia

Windows Subsystem for Linux (WSL)で開発環境を構築する

Windows10 Fall Creators Updateにて、WSLが正式版となりました。

以下ではWSLの有効化は事前に行っているものとします。


WSLでは、Linuxが仮想環境ではなくサブシステムとしてWindows上で動く。

細かいことはわからないが、提供されていないカーネルを必要とするソフトウェアはWSL上では動かないらしい。

Linux互換環境といったところか。

Bashシェルやapt、gccコンパイラ、gitといったものは普通に動くので個人的には十分だ。

コンパイルして生成された実行ファイルはOSを跨ぐと当然動かないので、linux環境に統一したいというのが、今回WSL上に環境を構築する理由である。

大抵のスパコンや小規模計算機サーバなどはOSにlinuxを採用しているのでメリットは多い。

WSL上にPython仮想環境を構築する

WSL上にデフォルトのPythonが入っているので、WSL自体を壊してしまわないように仮想環境にAnacondaを使ってPythonを導入する。

pyenvのインストール

直接Anacondaを入れても良いが要らないパッケージを入れたくないので、pyenv経由で入れると良い。

$ sudo aptitude install git
$ git clone https://github.com/yyuu/pyenv ~/.pyenv
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(pyenv init -)"' >> ~/.bashrc
$ source ~/.bashrc

*gitが入っている人は1行目はいらない。

Anacondaのインストール

pyenvから入れる。

$ pyenv install --list

いろいろ表示されるが、anaconda~~~ってやつの最新版を探す。

自分の場合はanaconda3-5.0.1が最新だった。

$ pyenv install anaconda3-5.0.1
$ pyenv global anaconda3-5.0.1
$ pyenv rehash

これでAnacondaのインストールは完了。

GUIのインストール

WSLにはGUIがないので、ipythonは動いてもmatplotlibが動かない。

これでは不便なのでX11 GUIを導入する。

ココから以下の二つをダウンロード&インストールする。

  • Xming-fonts-7-7-0-10-setup.exe
  • Xming-6-9-0-31-setup.exe

インストール後、Xmingを起動すると、windowsのタスクバーにXmingが現れるのでカーソルを合わせると

Xming server:0.0

と出ることを確認。こいつをdisplayの出力先に指定してやる。

$ echo 'export DISPLAY=localhost:0.0' >> ~/.bashrc
$ source ~/.bashrc

これでGUIの設定ができた。

matplotlibの導入

以上で大方準備は完了しているが、このままだとmatplotlibのインストールがうまくいかない。 また、jupyterのインストールにも失敗した(確か)。

これらの問題を避けるためにWSLで必要なパッケージをインストールしておく必要がある。

$ sudo aptitude install libqtgui4
$ sudo add-apt-repository ppa:aseering/wsl
$ sudo aptitude update
$ sudo aptitude install libzmq3
$ conda install -c jzuhone zeromq=4.1.dev0

これで動くようになったはず。

あとはconda installするだけ。

$ conda install matplotlib jupyter

numpyはmkl対応のものがデフォルトになっている。

エラーを吐く場合はmklを使わないOpenBLASのものを使うようにする。

$ conda install nomkl
$ conda update --all

Juliaのインストール

WSLでは、Juliaのインストール自体はUbuntuと同じで簡単にできる。

$ sudo add-apt-repository ppa:staticfloat/juliareleases
$ sudo add-apt-repository ppa:staticfloat/julia-deps
$ sudo apt-get update
$ sudo apt-get install julia

JupyterがインストールされていればIJuliaも簡単に導入可能

$ julia
> Pkg.add("IJulia")

まとめ

WSLにPythonの開発環境をpyenvを経由してAnacondaで構築した。

Jupyterの導入に便乗する形でJuliaもインストールした

Google Driveで文献管理 Paperpileが凄い

研究者を悩ませる文献管理

研究者にとって、増え続ける論文は仕事の効率を悪くする。

  • ほしい文献がどこに行ったか覚えていない
  • supporting informationどこよ
  • ファイルがダブっている
  • てか読んだっけ?

なんてことは日常茶飯事で困っていた(情報整理とか豆なことは苦手)。

そこで文献管理ソフトを使うわけだが、日本では以下が有名どころのようだ。

文献管理ソフトの例

  • EndNote
  • ReadCube
  • Zotero
  • Mendeley
  • Papers (macのみ)

ただ、どれも容量に制限があったり、結構高いお金がかかったりとパッとしない。

求めることは

  • オンラインストレージに文献保存
  • クラウドでの文献管理環境
  • メモ的なものが書けて、かつ簡単に確認できる

こんなのないかなーとずっと思っていたら、あった。

Paperpile

Paperpileの特徴

  • 文献はGoogle Driveに保存
  • ブラウザからワンクリックでインポート&pdfダウンロード
  • メモが簡単&閲覧も簡単
  • Google Docsにcitationができる。
  • academic use(要学校のアドレス)なら家でも文献ダウンロードできる??(気がするだけ?)
  • ブラウザベースなので引用元を簡単に表示できる。

まぁとにかく凄い。

管理させるだけなら最強では?

残念な点

  • wordプラグインは開発中らしい(フォーラムによると優先度低め)
  • PCからでないと使えない。

タブレット版はベータテスト中らしいが、いつ正式版がでるのか不明。

ただ、Google DriveにあるpdfはGoogle Driveに追加できるMetaPDFでコメントをペタペタしながら読めたりするので別にいいかも。

日本語で紹介・解説している人を見たことがないので参考になれば。

os.walkでエラーが出た

pythonの話題。

なお環境はAnacondaで構築して、python3.5となっている。

普段使っていたスクリプトがファイル読み込みでエラーをはいたのでその原因を調べた。

pandasとかいう便利なやつ

データ分析する人なら御用達のpandas。

エクセルファイルを簡単に読み込める凄いやつ。

こいつで複数ファイルをループして読み込みまくろうとしたらことが起きた。

こいつのバージョンが問題なのではと色々調べたが、結局問題はもっと根本的なところにあった。

なんだかglobとかos.walkが怪しい…

細かい説明はすっ飛ばして結論を言うと、excelとかのofficeソフトって._XXXXXXって感じの隠しファイルを生成していて、Ubuntuはもれなく条件にヒットしたファイル名を拾ってしまう。

windowsではこれを自動で無視するらしくglobだろうがos.walkだろうが問題にならない。

この._XXXファイルが読めないよ!!ってエラーをはいていたのだった。

ありがた迷惑である。

.(ドット)で始まるファイルを除けばいい

ということで隠しファイルを除くサンプルスクリプトを書いた。

import os
parentPath = 探したいディレクトリのパス

for root, dirs, fnames in os.walk(parentPath):
    for fname in fnames:
        if not fname.startswith("."):
            print(fname)

わかってしまえば簡単だった。

Ubuntuをアップデートしたらネットに繋がらなくなった

いつもの調子でsudo update!!PC

すると突然、DNSエラーが出てネットに繋がらなくなった。

同じ症状で困っている人もいると思うので記録しておく(調べれば一瞬で解決だけど)。

DNSサーバーって?

雑な言い方をすると、google、yahooなどの名前からIPアドレスを教えてくれるサーバー。

PCはIPアドレスがわからないと、googleやyahooやその他のPCなどに接続できない。

でもIPアドレスを毎回打ち込むのも、覚えるのも大変。

ニックネームだけ覚えて、ユーザーとしては実際のIPアドレスは隠蔽したい。

そんな面倒くさい部分を管理してくれているのがDNSサーバー。

なんで突然繋がらなくなった?

細かいところはわからないが、DNSサーバーの指定だか何かが勝手に書き換わってしまうらしい。

なんだそれ。

書き換えられないようにハードコードして解決

/etc/resolvconf/resolv.conf.d/head

最終行に

nameserver 8.8.8.8

と追記。

再起動すればネット復活。

まとめ

勉強になりました。

UbuntuでOneDriveを使いたい

Ubuntuで直感的にOneDriveを使いたい。

rcloneとかいう便利なソフトがあるらしい。

GUIもあるから設定してみた。

そんなお話。

rcloneってなに

Linux使いならよーくご存じだと思われるrsyncクラウドバージョン。

それがrclone

色々なクラウドストレージに対応しているようだ。

インストール

まずはインストールする

snapとかいうパッケージ管理マネージャ的な何かをaptでインストールしておく

sudo apt install snapd

snapでインストール

sudo snap install rclone --classic

アップデートしたい時

sudo snap refresh rclone --classic

rcloneを設定する

rclone config

interactiveに設定できる。

一問一答形式なので困ることもない。

No remotes found - make a new one
n) New remote
s) Set configuration password
n/s> n
name> remote
Type of storage to configure.
Choose a number from below, or type in your own value
 1 / Amazon Drive
   \ "amazon cloud drive"
 2 / Amazon S3 (also Dreamhost, Ceph)
   \ "s3"
 3 / Backblaze B2
   \ "b2"
 4 / Dropbox
   \ "dropbox"
 5 / Google Cloud Storage (this is not Google Drive)
   \ "google cloud storage"
 6 / Google Drive
   \ "drive"
 7 / Hubic
   \ "hubic"
 8 / Local Disk
   \ "local"
 9 / Microsoft OneDrive
   \ "onedrive"
10 / Openstack Swift (Rackspace Cloud Files, Memset Memstore, OVH)
   \ "swift"
11 / Yandex Disk
   \ "yandex"
Storage> 9
Microsoft App Client Id - leave blank normally.
client_id> 
Microsoft App Client Secret - leave blank normally.
client_secret> 
Remote config
Use auto config?
 * Say Y if not sure
 * Say N if you are working on a remote or headless machine
y) Yes
n) No
y/n> y
If your browser doesn't open automatically go to the following link: http://XXXXXXXXXXX/auth
Log in and authorize rclone for access
Waiting for code...
Got code
--------------------
[remote]
client_id = 
client_secret = 
token = {"access_token":"XXXXXX"}
--------------------
y) Yes this is OK
e) Edit this remote
d) Delete this remote
y/e/d> y

上記のコマンドたちについて少し説明。

ここは空欄で良いです(この後自動設定で、OneDriveのページヘ行き認証を行うため)

Microsoft App Client Id - leave blank normally.
client_id> 
Microsoft App Client Secret - leave blank normally.
client_secret> 

もし、自動でブラウザが立ち上がらない場合、以下の部分に書かれているurlヘ飛ぶ。

If your browser doesn't open automatically go to the following link: http://XXXXXXXXXXX/auth

OneDriveの認証画面が現れるので、承認する。

最後に

e) Edit existing remote
n) New remote
d) Delete remote
r) Rename remote
c) Copy remote
s) Set configuration password
q) Quit config
e/n/d/r/c/s/q> 

と聞かれるので、qを入力して終了。

このままでもCUIでコマンドを叩けば使えるが、rsyncのdeleteオプションが付いている状態でファイルのやり取りがされるらしく…

クラウド上のファイル全削除なんて事故が頻繁に起こるらしい。

ましてやコマンドなんてしばらく使わなければ忘れるもの。

そこで、ファイル全削除なうえ復元不可…なんて惨劇を回避するためにGUIを導入します。

RcloneBrowserの導入

rcloneがインストールされて、設定が終わっていることが前提です。

インストールする

sudo add-apt-repository ppa:mmozeiko/rclone-browser
sudo apt-get update
sudo apt install rclone-browser

これだけでインストールができるらしい…が、私の環境ではなぜかパッケージのダウンロードの段階で404 not found。

メンテナンス中とかだったのだろうか…。

仕方ないのでRcloneBrowaer公式からdebをダウンロードして直接入れた。

ダウンロードしてきたフォルダに移動して以下のようにコマンドを入力。

sudo dpkg -i rclone-browser_1.2_amd64.deb 

準備は整った。

実行する。

rclone-browser

こんなwindowが立ち上がったら成功。

f:id:hotoke-X:20170903014007p:plain

rcloneの設定が終わっていないとポップアップがでてきて、rcloneの設定をさせられる。

出てきたウィンドウに、rclone locationと.rclone.confのpathを入力すれば導入完了。

rcloneの場所がわからなければ

which rclone

で調べられる。

.rclone.confの場所は人によって違うかもしれないが、

/home/yourname/.rclone.conf

あるいは、Ubuntuなら

/home/yourname/.config/rclone/rclone.conf

となっている…と思う。

まとめ

Ubuntuからwebブラウザを経由せずにOneDriveにアクセスできるようになった!

マウント機能もあるらしいがexperimentalなので触らないでおく。

ちゃんと使えるようになったらwindowsmacと遜色なくOneDriveが使えるようになるかも?