v-crn Code Log

主に備忘録

Windews に Powerline 環境を構築する

f:id:v-crn:20201019004759p:plain

基本的には以下の記事を参考に環境構築を進めていきます。

[WSL2] Win10 で zsh+prezto を使って Powerline 環境を作る - Qiita

WSL2 の導入

WSL2 導入| Win アップデートから WSL2 を既定にするまでのスクショ - Qiita

  • 更新ファイルのサイズが大きいことに注意

コピー&ペーストができるようにする

PowerShell の起動中のアイコンを右クリックし、さらに「Windows Powershell」を右クリックして「プロパティ」を選択し、下記の設定を有効にする

  • Ctrl キーショートカットを有効にする
  • 行の折り返し選択を有効にする

Ubuntu の導入

インストールしたディストリビューションの確認

PowerShell から wsl コマンドでインストールしたディストリビューションを確認します。 VERSION が 2 と表示されている通り、インストールした Debian は WSL2 で実行されています。

PowerShell

wsl --list --verbose

WSL2 の方を(既定)にしたい

PowerShell

wslconfig /setdefault <distribution name>
# 例) wslconfig /setdefault Ubuntu-20.04

brew の導入

The Missing Package Manager for macOS (or Linux) — Homebrew

Homebrew on Linux — Homebrew Documentation

公式に従って次のコマンドを実行して linuxbrew をインストールしようと試みた。

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

しかし、途中で以下のようなエラーメッセージを受け取る。

==> Tapping homebrew/core
Cloning into '/home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-core'...
remote: Enumerating objects: 16, done.
remote: Counting objects: 100% (16/16), done.
remote: Compressing objects: 100% (14/14), done.
error: RPC failed; curl 56 GnuTLS recv error (-54): Error in the pull function.
fatal: the remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed
Error: Failure while executing; `git clone https://github.com/Homebrew/linuxbrew-core /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-core` exited with 128.
Error: Failure while executing; `/home/linuxbrew/.linuxbrew/bin/brew tap homebrew/core` exited with 1.
Failed during: /home/linuxbrew/.linuxbrew/bin/brew update --force

解決策の模索

結論としては「PC シャットダウン & 起動」で解決した。 以下、試行錯誤の過程を一応残しておく。


依存ツールのインストール

sudo apt-get install build-essential curl file git

Not worked.

ubuntu - git error: RPC failed; curl 56 GnuTLS - Stack Overflow

  • sudo apt install gnutls-bin: not worked
  • git config --global http.postBuffer 1048576000: not worked
  • git clone git@github.com:Homebrew/linuxbrew-core.git /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-core: not worked
  • git clone https://github.com/Homebrew/linuxbrew-core /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-core --depth=1: worked!

どうやら --depth=1 を付けてログのデータを小さくすれば良いらしい。でも、どうやって?

その後に再度インストールコマンドを実行すると、別の箇所で同様のエラーが出た。

 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
==> Downloading and installing Homebrew...
remote: Enumerating objects: 17, done.
remote: Counting objects: 100% (17/17), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 17 (delta 14), reused 16 (delta 14), pack-reused 0
Unpacking objects: 100% (17/17), 2.12 KiB | 723.00 KiB/s, done.
From https://github.com/Homebrew/brew
   747223e27..a39aae887  master     -> origin/master
HEAD is now at a39aae887 Merge pull request #8496 from reitermarkus/debug-git
error: RPC failed; curl 56 GnuTLS recv error (-54): Error in the pull function.
fatal: the remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed
Error: Fetching /home/linuxbrew/.linuxbrew/Homebrew/Library/Taps/homebrew/homebrew-core failed!
Failed during: /home/linuxbrew/.linuxbrew/bin/brew update --force

模索


PC シャットダウン & 起動

Workd!!!

ただし、Warning: /home/linuxbrew/.linuxbrew/bin is not in your PATH. とパスが通ってないという警告文が表示されたのでその下の Next Step に従います。

==> Next steps:
- Run `brew help` to get started
- Further documentation:
    https://docs.brew.sh
- Install the Homebrew dependencies if you have sudo access:
    sudo apt-get install build-essential
    See https://docs.brew.sh/linux for more information
- Add Homebrew to your PATH in /home/v-crn/.profile:
    echo 'eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)' >> /home/v-crn/.profile
    eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
- We recommend that you install GCC:
    brew install gcc

つまりは次の 2 行を実行するだけでパスが通ります。

echo 'eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)' >> /home/v-crn/.profile
eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)

最後に brew コマンドを実行して機能するか確認です。

zsh の導入

brew install zsh

インストールが完了したら、zsh をデフォルトのシェルに変更します。

# パスの確認
which zsh | sudo tee -a /etc/shells
# デフォルトシェルを zsh に設定
chsh -s /home/linuxbrew/.linuxbrew/bin/zsh

perl についての推奨設定

==> perl
By default non-brewed cpan modules are installed to the Cellar. If you wish
for your modules to persist across updates we recommend using `local::lib`.

You can set that up like this:
  PERL_MM_OPT="INSTALL_BASE=$HOME/perl5" cpan local::lib
  echo 'eval "$(perl -I$HOME/perl5/lib/perl5 -Mlocal::lib=$HOME/perl5)"' >> ~/.profile

とりあえず推奨設定に従います。

Zinit の導入

zdharma/zinit: Ultra-flexible and fast Zsh plugin manager with clean fpath, reports, completion management, Turbo, annexes, services, packages.

sh -c "$(curl -fsSL https://raw.githubusercontent.com/zdharma/zinit/master/doc/install.sh)"

.zshrc を Sample Usage に従って設定します。

### Added by Zinit's installer
if [[ ! -f $HOME/.zinit/bin/zinit.zsh ]]; then
    print -P "%F{33}▓▒░ %F{220}Installing %F{33}DHARMA%F{220} Initiative Plugin Manager (%F{33}zdharma/zinit%F{220})…%f"
    command mkdir -p "$HOME/.zinit" && command chmod g-rwX "$HOME/.zinit"
    command git clone https://github.com/zdharma/zinit "$HOME/.zinit/bin" && \
        print -P "%F{33}▓▒░ %F{34}Installation successful.%f%b" || \
        print -P "%F{160}▓▒░ The clone has failed.%f%b"
fi

source "$HOME/.zinit/bin/zinit.zsh"
autoload -Uz _zinit
(( ${+_comps} )) && _comps[zinit]=_zinit

# Load a few important annexes, without Turbo
# (this is currently required for annexes)
zinit light-mode for \
    zinit-zsh/z-a-rust \
    zinit-zsh/z-a-as-monitor \
    zinit-zsh/z-a-patch-dl \
    zinit-zsh/z-a-bin-gem-node

### End of Zinit's installer chunk


# Two regular plugins loaded without investigating.
zinit light zsh-users/zsh-autosuggestions
zinit light zdharma/fast-syntax-highlighting

# Plugin history-search-multi-word loaded with investigating.
zinit load zdharma/history-search-multi-word

# Load the pure theme, with zsh-async library that's bundled with it.
zinit ice pick"async.zsh" src"pure.zsh"
zinit light sindresorhus/pure

# A glance at the new for-syntax – load all of the above
# plugins with a single command. For more information see:
# https://zdharma.org/zinit/wiki/For-Syntax/
zinit for \
    light-mode  zsh-users/zsh-autosuggestions \
    light-mode  zdharma/fast-syntax-highlighting \
                zdharma/history-search-multi-word \
    light-mode pick"async.zsh" src"pure.zsh" \
                sindresorhus/pure

# Binary release in archive, from GitHub-releases page.
# After automatic unpacking it provides program "fzf".
zinit ice from"gh-r" as"program"
zinit load junegunn/fzf-bin

# One other binary release, it needs renaming from `docker-compose-Linux-x86_64`.
# This is done by ice-mod `mv'{from} -> {to}'. There are multiple packages per
# single version, for OS X, Linux and Windows – so ice-mod `bpick' is used to
# select Linux package – in this case this is actually not needed, Zinit will
# grep operating system name and architecture automatically when there's no `bpick'.
zinit ice from"gh-r" as"program" mv"docker* -> docker-compose" bpick"*linux*"
zinit load docker/compose

# Vim repository on GitHub – a typical source code that needs compilation – Zinit
# can manage it for you if you like, run `./configure` and other `make`, etc. stuff.
# Ice-mod `pick` selects a binary program to add to $PATH. You could also install the
# package under the path $ZPFX, see: http://zdharma.org/zinit/wiki/Compiling-programs
zinit ice as"program" atclone"rm -f src/auto/config.cache; ./configure" \
    atpull"%atclone" make pick"src/vim"
zinit light vim/vim

# Scripts that are built at install (there's single default make target, "install",
# and it constructs scripts by `cat'ing a few files). The make'' ice could also be:
# `make"install PREFIX=$ZPFX"`, if "install" wouldn't be the only, default target.
zinit ice as"program" pick"$ZPFX/bin/git-*" make"PREFIX=$ZPFX"
zinit light tj/git-extras

# Handle completions without loading any plugin, see "clist" command.
# This one is to be ran just once, in interactive session.
# zinit creinstall %HOME/my_completions

# For GNU ls (the binaries can be gls, gdircolors, e.g. on OS X when installing the
# coreutils package from Homebrew; you can also use https://github.com/ogham/exa)
zinit ice atclone"dircolors -b LS_COLORS > c.zsh" atpull'%atclone' pick"c.zsh" nocompile'!'
zinit light trapd00r/LS_COLORS

# make'!...' -> run make before atclone & atpull
zinit ice as"program" make'!' atclone'./direnv hook zsh > zhook.zsh' atpull'%atclone' src"zhook.zsh"
zinit light direnv/direnv

.zshrc の変更内容を反映

source ~/.zinit/bin/zinit.zsh

VS CodeUbuntuzsh を利用する

Visual Studio Code拡張機能「Remote – WSL」を使うと簡単に VS Code の統合ターミナルで zsh が使えるようになる。

  1. Remote – WSL をインストール
  2. VS Code 左下の「><」アイコンをクリック
  3. 上部にメニューが表示されるので、「Remote-WSL: New Window」をクリック
  4. 新しいウィンドウで Visual Studio Code が起動する。左下には「WSL: Ubuntu」などと表示されているはず
  5. Ctrl + J で統合ターミナルを開くと、 WSL 上で起動中の Ubuntu にアクセスされる

統合ターミナルのデフォルトシェルを wsl に設定する

VS Code の setting.json に次の行を追加する。

"terminal.integrated.shell.windows": "C:\\WINDOWS\\System32\\wsl.exe"

外部記憶装置の中で環境構築する場合

PC 内臓の C ドライブではなく、外付け HDD などの中で作業環境を構築する場合、そのままではアクセス権限が制限されているため、WSL でのファイルの書き込み操作の際、頻繁に Permission denied されることになった。

例:

  • pipenv install を実行すると Permission denied でできない
  • git clone に失敗する

解決するには、ドライブのマウント時に metadata オプションというものを付ける必要がある。

WSL はデフォルトで C ドライブを /mnt/c にマウントするが、現在のマウントオプションを mount コマンドで確認してみよう。

$ mount
...(中略)
C:\ on /mnt/c type 9p (rw,noatime,dirsync,aname=drvfs;path=C:\;uid=1000;gid=1000;symlinkroot=/mnt/,mmap,access=client,msize=65536,trans=fd,rfd=8,wfd=8)
E:\ on /mnt/e type 9p (rw,noatime,dirsync,aname=drvfs;path=E:\;uid=1000;gid=1000;symlinkroot=/mnt/,mmap,access=client,msize=65536,trans=fd,rfd=8,wfd=8)

たとえば E ドライブのマウントオプションを変更するには次の2行を実行する。

sudo umount /mnt/e
sudo mount -t drvfs E: /mnt/e -o metadata

これで外部記憶装置でもパーミッションを扱うことができるようになっているはず。 mount コマンドで状態を確認すると metadata が追加されているのがわかる。

E: on /mnt/e type 9p (rw,relatime,dirsync,aname=drvfs;path=E:;metadata;symlinkroot=/mnt/,mmap,access=client,msize=65536,trans=fd,rfd=3,wfd=3)

WSL のファイルシステム

Windows Subsystem for Linux (WSL) には、VolFs と DrvFs の 2 つのファイルシステムがある。

VolFs

WSL 内部にインストールされたディストリビューション(= OS としての Linux)を管理するファイルシステム

DrvFs

WSL 上でマウントされた外部領域を管理するファイルシステム

WSL でマウントしたファイルシステムでもパーミッションを扱えるようにする - らくがきちょう

Google Colaboratory を使うときはパッケージのバージョンに注意

f:id:v-crn:20191230030002p:plain

Google Colaboratory とローカル環境で同じPythonコードを走らせているのに挙動が異なる場合がある。その原因はパッケージのバージョンの違いかもよ、というお話。

たとえば、 imblearn.under_sampling.RandomUnderSampler を使った次のコードをローカルのPython環境で実行した場合:

from imblearn.under_sampling import RandomUnderSampler
rus = RandomUnderSampler(
            sampling_strategy='auto', random_state=1)
X_r, y_r = rus.fit_sample(X_prp, y_prp)
type(X_r)
# pandas.core.frame.DataFrame

結果は pandas.core.frame.DataFrame が返ってくる。 一方、 Google Colaboratory で同じコードを実行した場合、 numpy.ndarray が返り値となる。

それぞれのパッケージのバージョンを調べてみる。

import imblearn
imblearn.__version__

バージョン:

  • Local: '0.6.1'
  • Google Colaboratory: '0.4.3'

Google Colaboratory の方で古いバージョンを使用していた。 古いパッケージのアップデートを行ってみよう。

# !pip install --upgrade imblearn # これでは駄目。imbalanced-learnを対象にすべき
!pip install -U imbalanced-learn

Collecting imbalanced-learn Downloading https://files.pythonhosted.org/packages/eb/aa/>eba717a14df36f0b6f000ebfaf24c3189cd7987130f66cc3513efead8c2a/imbalanced_learn-0.6.1-py3-none-any.whl (162kB) |████████████████████████████████| 163kB 7.8MB/s Requirement already satisfied, skipping upgrade: joblib>=0.11 in /usr/local/lib/python3.6/dist-packages (from >imbalanced-learn) (0.14.1) Requirement already satisfied, skipping upgrade: scipy>=0.17 in /usr/local/lib/python3.6/dist-packages (from >imbalanced-learn) (1.3.3) Requirement already satisfied, skipping upgrade: numpy>=1.11 in /usr/local/lib/python3.6/dist-packages (from >imbalanced-learn) (1.17.4) Collecting scikit-learn>=0.22 Downloading https://files.pythonhosted.org/packages/d1/48/>e9fa9e252abcd1447eff6f9257636af31758a6e46fd5ce5d3c879f6907cb/scikit_learn-0.22.1-cp36-cp36m-manylinux1_x86_64.whl >(7.0MB) |████████████████████████████████| 7.1MB 12.9MB/s Installing collected packages: scikit-learn, imbalanced-learn Found existing installation: scikit-learn 0.21.3 Uninstalling scikit-learn-0.21.3: Successfully uninstalled scikit-learn-0.21.3 Found existing installation: imbalanced-learn 0.4.3 Uninstalling imbalanced-learn-0.4.3: Successfully uninstalled imbalanced-learn-0.4.3 Successfully installed imbalanced-learn-0.6.1 scikit-learn-0.22.1

アップデート後に先程 ndarray を返してきたコードを実行すると、期待する結果である pandas.core.frame.DataFrame が返ってきた。

めでたしめでたし。

まあ、今回のエラーはGCに限った話じゃないんだけども、インストールされているパッケージのバージョンが違うことで発生するエラーって気付くのに時間がかかるきらいがある。

今後とも環境起因のエラーに注意しよう。

Google Colaboratory でカスタムモジュールをインポートする

手順

1. Google Drive を Mount

from google.colab import drive
drive.mount('/content/drive')

2. sys.path.append() でパスを通してインポート

例として次のようなファイル構成になっているとする。

  • My Drive
    • Colab Notebooks
      • ML
        • workspace
          • my_module
            • __init__.py
            • my_utils.py
            • my_toolbox
              • __init__.py
              • visualizer.py

※「My Drive」が Google Drive のルートディレクト

このファイル構成で カスタムモジュール「my_module」を import するには次のように sys.path.append()モジュールの親ディレクトまでのパスをシステムに伝える必要がある。

import sys
ROOT_PATH = 'drive/My Drive/Colab Notebooks/ML/workspace/'
sys.path.append(ROOT_PATH)

import my_module

これで ModuleNotFoundError: No module named 'my_module' のようなエラーが出なければおけまる。

モジュール my_module の中のライブラリ my_utils やさらにその中のメンバーを使いたければたとえば次のように書く。

from my_module import my_utils
from my_toolbox.visualizer import hoge

visualizer.py

def hoge():
    print('hoge!')

モジュールの変更を反映する

Google Drive を再度マウントする必要がある。 Google Colaboratory のメニュータブから「Factory reset runtime」を選択し、ランタイムをリセットする。 そしていつものようにマウントするためのコードを実行すれば良い。

from google.colab import drive
drive.mount('/content/drive')

認証コードを入力してマウントが完了すれば、変更が反映されているはずだ。

ここで注意したいのは、単なる再起動 (Restart) では drive.mount('/content/drive') を実行しても Google Drive が再読み込みされないことである。その場合、認証コードを求められることなく以前の状態のドライブが適用されてしまう。

その他、強制マウントや importlib.reload を試してみたが駄目だった。

駄目な例1:強制マウント

drive.mount('/content/drive', force_remount=True)

駄目な例2:importlib.reload

import importlib
importlib.reload(module_name)

参考

TensorFlow 2.0.0へのアップデートで出くわしたエラー:AttributeError: module 'tensorflow' has no attribute 'placeholder'

前提

  • TensorFlow 2.0.0

エラー内容

TensorFlow 1.4.0で書かれたコード

g = tf.Graph()
with g.as_default():
    x = tf.placeholder(dtype=tf.float32,
                       shape=(None), name='x')
    w = tf.Variable(2.0, name='weight')
    b = tf.Variable(0.7, name='bias')

    z = w*x + b
    init = tf.global_variables_initializer()

を実行すると次のエラーが出た.

AttributeError: module 'tensorflow' has no attribute 'placeholder'

原因はバージョンアップに伴う変更の影響だった.

解決策

エラーの原因となっているメソッドの前に tensorflow.compat.v1 をつけることで解決した.(もちろん as tf でimportしているならtf.compat.v1

g = tf.Graph()
with g.as_default():
    x = tf.compat.v1.placeholder(dtype=tf.float32,
                       shape=(None), name='x')
    w = tf.Variable(2.0, name='weight')
    b = tf.Variable(0.7, name='bias')

    z = w*x + b
    init = tf.compat.v1.global_variables_initializer()

VS CodeのPythonエクステンションを使ったJupterNotebookは通常のJupyterNotebookより遅い

要点

VS Code拡張機能Python』を導入すると、VS Code上で通常のJupyterNotebookと同様にIPythonファイルを編集し、実行することができるようになります。

しかし、いざそれを使ってみると普段より明らかに処理に時間がかかっているように思えたので、今回それを検証してみました。

結論としては、VS Code上で実行した場合の方が圧倒的に遅いということがわかりました。

実行環境

  • macOS Mojave 10.14.6
  • Python 3.7.5
  • pipenv 2018.11.26
  • Jupyter
    • jupyter 1.0.0
    • jupyter-client 5.3.4
    • jupyter-console 6.0.0
    • jupyter-contrib-core 0.3.3
    • jupyter-contrib-nbextensions 0.5.1
    • jupyter-core 4.6.1
    • jupyter-highlight-selected-word 0.2.0
    • jupyter-latex-envs 1.4.6
    • jupyter-nbextensions-configurator 0.4.1
    • jupytext 1.3.0

検証コード

%%
import pandas as pd
import numpy as np
from pandas import DataFrame
from sklearn.datasets import load_boston
import matplotlib.pyplot as plt
import seaborn as sns

boston = load_boston()
df = DataFrame(X, columns = boston.feature_names)
df['PRICE'] = boston.target

%%

%%time
plt.figure(facecolor='w')
pd.plotting.scatter_matrix(df, figsize=(20,20))
filename = 'scatter-matrix.png'
plt.savefig(filename, dpi=100, bbox_inches="tight", pad_inches=0.1)
plt.show()

結果

VS Code上で実行した場合の方が3倍ほど時間が掛かる結果が得られました。

Case1: JupyterNotebook

CPU times: user 20.8 s, sys: 337 ms, total: 21.1 s Wall time: 19.9 s

Case2: JupyterNotebook with Python extention of VS Code

CPU times: user 56.2 s, sys: 1.12 s, total: 57.3 s Wall time: 1min 5s

IPython上でGIFを表示する

前提

ルートディレクトリに表示したいGIFファイルがある場合を想定します。

!ls
sample_data  sin_curve.gif

ちなみに上の「sin_curve.gif」を生成するコードはこんな感じ。

%%
!pip install animatplot

%%
"""
Introduction to animatplot
https://animatplot.readthedocs.io/en/latest/tutorial/getting_started..html#Basic-Animation
"""

import numpy as np
from matplotlib import pyplot as plt
import animatplot as amp


def main():
    xs = np.linspace(0, 1, 50)
    ts = np.linspace(0, 1, 20)
    Xs = np.asarray([xs] * len(ts))
    Ys = [np.sin(2 * np.pi * (xs + t)) for t in ts]
    """
    # you can also write
    Xs, Ts = np.meshgrid(xs, ts)
    Ys = np.sin(2 * np.pi * (Xs + Ts))
    """
    block = amp.blocks.Line(Xs, Ys)
    anim = amp.Animation([block])
    anim.save_gif("sin_curve")
    plt.show()


if __name__ == '__main__':
    main()

GIFを表示するコード

以下のコードでGIFを表示させることができる。

from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
from IPython import display
from pathlib import Path

gifPath = Path("sin_curve.gif")

with open(gifPath,'rb') as f:
  display.Image(data=f.read(), format='png')

Path("")の引数に対象のGIFファイルのPathを入れてれればおけまる。

参考

elegant way to display gif file in notebook? · Issue #10045 · ipython/ipython

Google Colaboratoryのスクラッチコードセル

Google Colaboratoryにおいて!ls -adf -hなどのちょっとした確認のためのコマンドを実行したいとき、クラッチコードセルが便利。

以下のショートカットキーでスクラッチコードセルが用意される。

Mac

Cmd + alt + N

Windows

Ctrl + alt + N