DockerでUbuntu環境の作成

ubuntuの22.04 LTSが公開されているのでdockerで環境を作成しようと画策しました。 ↓の記事を参考に作成していったものの、詰まる箇所があったのでメモを残します。

qiita.com

# 仮想化するベースOS
FROM ubuntu:22.04
# 誰が作ったかは入れておきましょう
MAINTAINER satoharu

# 各環境変数を設定
ENV USER test
ENV HOME /home/${USER}
ENV SHELL /bin/bash

# 一般ユーザーアカウントを追加
RUN useradd -m ${USER}
# 一般ユーザーにsudo権限を付与
RUN gpasswd -a ${USER} sudo
# 一般ユーザーのパスワード設定
RUN echo "${USER}:test_pass" | chpasswd
# ログインシェルを指定
RUN sed -i.bak -e "s|${HOME}:|${HOME}:${SHELL}|g" /etc/passwd #←RUNが抜けている気がしたので追加

# 以降のRUN/CMDを実行するユーザー
USER ${USER}
# 以降の作業ディレクトリを指定
WORKDIR ${HOME}

上記で環境が作成され、docker環境に入れたもののsu - になるパスワードがわからない。。

ソースコードから日本語を検出して、一斉置換を行う。

ソースコードを提出する必要があり、調べたのでまとめます。

find ./ -name "*.py"| xargs -L1 sed -i -e "s/[ぁ-んァ-ヶヲ-゚一-龠]//g"

findで置換対象のファイルを検索し、xargsに渡してsedで日本語のひらがな・カタカナ・漢字を一斉に空白//に置換する。

Docker + CUDA

前回から引き続きDockerの記事です。

↓前回の記事 satoharu25.hatenablog.com

今回は、GPUマシン上でDocker環境を構築し、CUDAを設定する箇所まで行います。 ホストマシン上でのCUDAの設定までは終わっているものとします。 CUDAの設定については過去に記事にしているので、まだの方は設定してください。

satoharu25.hatenablog.com

主に + Dockerのインストール + nvidia-docker2のインストール を行います。

参考文献

docs.nvidia.com

Dockerのインストール

Ubuntu

curl https://get.docker.com | sh \
  && sudo systemctl --now enable docker

CentOS 8

sudo dnf install docker-ce -y
sudo systemctl --now enable docker

CentOS7

sudo yum install docker-ce -y
sudo systemctl --now enable docker

nvdia-docker2のインストール

Ubuntu

distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
   && curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - \
   && curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update
sudo apt-get install -y nvidia-docker2
sudo systemctl restart docker
sudo docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi

CentOS8

distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
   && curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | sudo tee /etc/yum.repos.d/nvidia-docker.repo
sudo dnf install -y nvidia-docker2
sudo systemctl restart docker
sudo docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi

CentO7

distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
   && curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | sudo tee /etc/yum.repos.d/nvidia-docker.repo
sudo systemctl restart docker
sudo docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi

動作確認

sudo docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi
satoharu@opt-cps2:~$sudo docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi
Wed Nov 17 06:20:49 2021       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 495.29.05    Driver Version: 495.29.05    CUDA Version: 11.5     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA GeForce ...  Off  | 00000000:01:00.0 Off |                  N/A |
| 29%   61C    P0    38W / 215W |      0MiB /  7982MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

以上です。

私はUbuntuが好き

DockerでUbuntuを立ち上げ、pyenv環境まで構築したい(願望)。

背景

M1 Macが発売されて以降、MacOSでのpyenvを用いたpythonの環境構築がめんどくさい。 いっそのこと、Ubuntu上を立ち上げてめんどくさいことなしで、armでのPython環境を構築すれば一気に解決(名案!)。

ホストマシン

MacBook Air 2020, M1, 16GB
OS: MacOS Big Sur 11.6
Docker version 20.10.6, build 370c289

Dockerfile

Ubuntuの20.04をOSとして環境構築する。私はUbuntuが好き。 どれほど好きかというと、今年研究室に来た新しいサーバー6台が全てubuntuになりました(単に先生がそうしてるだけかも)。 研究室に置いているゲーミングマシンもubuntu入れました。windowsにさよならバイバイ。 てかCent OSのプロジェクト終了するんだ。。

github.com

を参考に、

sudo apt-get update; sudo apt-get install make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

を実行する。apt-getはubuntu18.04のコマンドなので、20.04ではaptに書き換える.

FROM ubuntu:20.04
RUN mkdir -p usr/lib
RUN apt update -y
RUN apt install -y sudo
RUN apt install -y tzdata
RUN apt install -y build-essential

RUN sudo apt update; sudo apt install make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

# setting user
ARG USER_NAME
ARG GROUP_NAME
ARG UID
ARG GID
ARG PASSWORD

ENV HOME /home/$USER_NAME
ENV PYENV_ROOT $HOME/.pyenv
ENV PATH $PYENV_ROOT/bin:$PATH

# add sudo to user
RUN groupadd --gid ${GID} ${GROUP_NAME} && \
    useradd -m -s /bin/bash -u ${UID} --gid ${GID} -G sudo ${USER_NAME} && \
    echo ${USER_NAME}:${PASSWORD} | chpasswd && \
    echo "${USER_NAME}   ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

RUN git clone https://github.com/pyenv/pyenv.git ${HOME}/.pyenv
RUN echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.profile
RUN echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.profile
RUN echo 'eval "$(pyenv init --path)"' >> ~/.profile
RUN pyenv install -v 3.9.7


# switch root to user
USER ${USER_NAME}
WORKDIR /home/${USER_NAME}/

# copy local files into image
COPY --chown=${USER_NAME}:${USER_NAME} . .

次回、Docker + CUDAの使い方。

Python 3.10.0

日頃使用しているPythonがメジャーアップデートしました。

www.python.org

Major new features of the 3.10 series, compared to 3.9 Among the new major new features and changes so far:

PEP 623 -- Deprecate and prepare for the removal of the wstr member in PyUnicodeObject. PEP 604 -- Allow writing union types as X | Y PEP 612 -- Parameter Specification Variables PEP 626 -- Precise line numbers for debugging and other tools. PEP 618 -- Add Optional Length-Checking To zip. bpo-12782: Parenthesized context managers are now officially allowed. PEP 632 -- Deprecate distutils module. PEP 613 -- Explicit Type Aliases PEP 634 -- Structural Pattern Matching: Specification PEP 635 -- Structural Pattern Matching: Motivation and Rationale PEP 636 -- Structural Pattern Matching: Tutorial PEP 644 -- Require OpenSSL 1.1.1 or newer PEP 624 -- Remove Py_UNICODE encoder APIs PEP 597 -- Add optional EncodingWarning

個人的には、match文の追加を楽しみにしています。

qiita.com

平均クラスタ係数

平均<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%AF%A5%E9%A5%B9%A5%BF">クラスタ</a>係数G=(V,E)G=(V,E)について考える。

N=VN=|V|

M=EM=|E|


隣接行列

隣接行列AAの要素ai,ja_{i,j}は、ii番目のノードとjj番目のノードが隣接している場合、ai,j=1a_{i,j}=1、そうでない場合にはai,j=0a_{i,j}=0を取る行列である。

無向グラフの場合、枝(i,j),(j,i)E(i,j), (j,i)\in Eを区別しないので、隣接行列は対称行列となる。


  • ネットワークの性質を解析的に議論する際には、隣接行列が有用である。
  • 一方、数値的に解析する場合には、隣接していないノード対を表すゼロの数の割合が非常に高いため、現実のグラフを表現した際に、行列の成分全体の1%ほどしか非ゼロ成分が存在しない場合がある。このような非ゼロ成分の少ない行列を扱うために計算機のメモリを無駄にに消費してしまう。この場合は、行列のデータ構造を工夫するなどして効率よく計算していく必要がある。


ノードの次数

ii番目のノードに繋がっているエッジの本数をノードii次数といい、kik_iで表す。次数kik_iは隣接行列AAの要素ai,ja_{i,j}を用いて

ki=j=1Naijk_i = \sum_{j=1}^Na_{ij}

と表すことができる。例えば、単純グラフの場合はノード iiに隣接するノード数と次数が一致する。

  • 次数は、ネットワークが持つ情報を全て含む隣接行列をトレースアウトして得られる特徴量のなかで最も単純な量である。
  • ネットワーク構造を議論する際には、極めて重要となる基本的な量である。


代表的なグラフの次数に関する性質

  • 全ノードの次数がN1N-1であるネットワークは完全グラフである。
  • 全ての次数がkkであるネットワークがkk-正則グラフである。



握手の定理とは、グラフのノード全体の次数と枝の本数に関する関係式である。

i=1Nki=2M\sum_{i=1}^Nk_i=2M
2M=i,j=1Nai,j=TrA22M=\sum_{i,j=1}^Na_{i,j}={\rm Tr}A^2

この等式は、多重エッジや自己ループを含むようなグラフに対しても成立する。握手の定理から次の補題が従う。


[補題] 任意のネットワークにおいて奇数次数のノードは偶数個ある。

証明:

Sodd,SevenS_{odd}, S_{even}をそれぞれ次数が奇数, 偶数であるノードの集合とする。 SoddSeven=VS_{odd}\cup S_{even}=Vであるから、握手の定理より

2M=iSoddki+iSevenki2M=\sum_{i\in S_{odd}} k_i + \sum_{i \in S_{even}} k_i

左辺に注目すると、Mが整数であることから2Mは偶数である。一方、右辺に着目すると第二項は次数が偶数のノードの次数の和であるから、偶数である。よって上記の等式が成り立つためには、第一項が偶数である必要がある。今、第一項は次数が奇数のノードの和であるから、上記の等式が成り立つためには、総和の項数が偶数である必要がある。逆に、総和の項数が偶数であれば、上記の等式が成り立つ。

よって任意のネットワークにおいて、奇数次数のノードは偶数個あることがわかる。


グラフの平均次数

次数を全ノードで平均した平均次数k\langle k\rangleは、ネットワーク全体の大域的性質を表す量の1つである。全ノードの次数の平均値が平均次数なので

k=1Ni=1Nki=2MN\begin{align*} \langle k \rangle&=\frac{1}{N} \sum_{i=1}^Nk_i \\ &=\frac{2M}{N} \end{align*}

と表される。後半の式変更には握手の定理を用いた。


  • 全ての無向グラフにおいてkN1\langle k\rangle \leq N-1であり、等号成立条件は完全グラフの場合に限る。
  • k\langle k \rangleがNと同程度の大きさであるようなグラフは、エッジの密度が高い。
  • 逆に平均次数がNから小さいグラフはエッジの密度の低い疎なグラフであると言える。
  • 平均次数はグラフのエッジの「密度」を反映した量であると言える。


エッジ密度とクラスター係数

グラフ内のノードがどれほど密に繋がっているかは、グラフを特徴づける重要な要素である。

同じNN個のノードからなるネットワークでも、完全グラフと木とでは、エッジの密度に大きな違いがある。当然、完全グラフが最もエッジの密度が高く、逆に孤立したノード集合からなるグラフが最もエッジの密度が低い。このように今考えているグラフGGの枝の本数と、GGのノードから生成される完全グラフの枝数12N(N1)\frac{1}{2}N(N-1)に対する割合でグラフのエッジ密度ρ\rhoを定義する。ρ\rho

ρ=2MN(N1)=kN1\rho=\frac{2M}{N(N-1)}=\frac{\langle k \rangle}{N-1}

と表される。上記のエッジ密度の定義は、グラフ全体に対して定義されているが、同様にグラフの部分グラフに対しても同様に定義し、それを局所的エッジ密度と呼ぶこととする。

あるノードiill近傍部分グラフGi(l)G_i(l)を考える。ここで、ll近傍部分グラフとはノードiiからllホップで辿れるノードとエッジに関する部分グラフである。近傍部分グラフGi(l)G_i(l)のノード数と枝数をそれぞれni(l),mi(l)n_i(l), m_i(l)とすると、近接部分グラフの局所的エッジ密度ρi(l)\rho_i(l)

ρi(l)=2mi(l)ni(l)(ni(l)1)\rho_i(l)=\frac{2 m_i(l)}{n_i(l)(n_i(l)-1)}

と表される。この指標により、近接部分グラフがクリークであればそのエッジ密度が1であるので、近接部分グラフのクリーク性の程度を表しているものと考えられる。


局所的エッジ密度として、特に重要なのは、最も局所性の高いl=1l=1におけるρi(l=1)\rho_i(l=1)である。近接部分グラフGi(1)G_i(1)について、ノード数とエッジ数はそれぞれni(1)=ki,mi(1)=mi+kin_i(1)=k_i, m_i(1)=m_i+k_iとなる。ただし、mim_iは、ノードiiの隣接ノード間を結ぶエッジの数である。mim_iについて、ノードiiの近接部分グラフGi(1)G_i(1)がクリークであるとき、Gi(1)G_i(1)からノードiiが接続しているkik_i本のエッジを取り除いた部分グラフgig_iもクリークとなる。よって、ノードiiの周りのエッジの密度CiC_igig_iの枝数mim_iと点数kik_iを用いて次のように定義する。

Ci=2miki(ki1)C_i=\frac{2m_i}{k_i(k_i-1)}

CiC_iをノードiiクラスター係数と呼ぶ。クラスター係数はネットワーク科学において重要な役割を果たす。定義より、mim_iはノードiiを頂点とする三角形の個数と一致するので、クラスタ係数はノードiiを頂点とする三角形の割合とも捉えることができる。


各ノードのクラスタ係数の平均値を平均クラスタ係数といい、CCと表す。

C=1Ni=1NCiC=\frac{1}{N}\sum_{i=1}^NC_i

C=1C=1となる場合は、完全グラフの場合のみに限る。


  • クラスター係数は三角形(3次のサイクル)の数の割合である。
  • エッジ密度が00に近い場合でも平均クラスタ係数が11に近い値を取ることがある。
  • クラスター係数は無向グラフに対する特徴量であり、有向グラフには定義されない。
  • 上記のクラスタ係数は3次のサイクルの割合と定義されていたが、4次のバージョンも存在し、サイクル係数と呼ばれる。


※近接部分グラフの密度だけでは不十分なのか?


python のソースコードを自動整形してくれる

Black is the uncompromising Python code formatter. By using it, you agree to cede control over minutiae of hand-formatting. In return, Black gives you speed, determinism, and freedom from pycodestyle nagging about formatting. You will save time and mental energy for more important matters.

Blackened code looks the same regardless of the project you're reading. Formatting becomes transparent after a while and you can focus on the content instead.

Black makes code review faster by producing the smallest diffs possible.

Try it out now using the Black Playground. Watch the PyCon 2019 talk to learn more.

github.com