allenlu2007

A great WordPress.com site

小米手機刷機

by allenlu2007

這是一個測試

乾電池省錢兼環保秘訣

by allenlu2007

電池常見的困擾是到底有沒有電,還是裝置壞了。2020 我買了兩個東西非常有用。

  • 三用電表: 主要用來量電壓,特別是電池電壓 (選 20V 檔位)。讓我了解不同裝置的操作電壓。

  • USB 充電磨砂機:幫我修理很多裝置生鏽造成接觸不良,而誤以為電池沒電。我買了下圖裝置,救了很多電器,非常有用。

不同電池電壓

AA/AAA/AAAA 電池的額定電壓是 1.5V.

  • 不同電池的初始電壓(新電池的電壓)都會高於 1.5V. 差不多都是 1.6+V. 差別是總電量。一般鹼性電池號稱總電量比較大,也比較貴。
  • 隨著使用時間增加,電壓電壓下降,最終低於裝置的最低工作電壓而無法使用。拋棄損失錢和製造環保問題。
  • 決定使用時間的是裝置最低工作電壓,不是電池的總電量!

裝置單電池最低工作電壓

  • 不同裝置最低工作電壓差距很大!
  • 舉個例子,同樣是電動給皂機。美國的給皂機(which brand?)可以工作在 1.3V (單個電池), 小米給皂機的就要工作在 1.5V (單個電池). 所以小米給皂機非常耗費電池。
  • 羅技的藍芽無線滑鼠可以工作在 1.36V! 一個電池可以撐半年以上。

這裡列出我用過的裝置單電池最低工作電壓。同時分為 A, B, C 三級,越低越優。

  • A 級:1.35V or lower (超優)
  • B 級:1.38V (合理)
  • C 級:1.42V or above (差)

如果各位有測量裝置的最低工作電壓,請告訴我加入這個表。省錢兼環保!

廠牌 產品型號 電池 failed電壓 級別
小米給皂機 AA 1.42V C
美國給皂機 AA
羅技藍芽滑鼠 M720 AA 1.36V B
日立冷氣遙控 RF07T7 AAA 1.38V B

省錢和環保要訣

電池二次使用

  • C 的電池不用丟,可以給 B or A 級裝置使用。例如小米給皂機換下來的電池可以給羅技藍芽滑鼠使用。

除鏽兼療癒

  • 乾電池其實還是有電解液,放久會漏出腐蝕電極,形成銅鏽或鋁鏽造成接觸不良。此時換電池沒有用,只是浪費錢。
  • 我找到一個 USB 充電的磨砂機,可以除鏽。看到壞掉的裝置重新能用,非常療癒。

Deep Learning Machine on Ubuntu LTS 16.04/20.04 with GTX 1080

by allenlu2019

本文聚焦在 Ubuntu 16.04 LTS with GTX1080 GPU deep learning 軟體設定。

2021/3/28 加上 Ubuntu 20.04 LTS 的軟體設定在最後。

Reference: 

[1] tflearn: http://tflearn.org/examples/

[2] https://standbymesss.blogspot.tw/2016/09/ubuntu-1404-caffe-cuda-75-opencv-31.html -> good reference

[bootable USB stick]

[3] “Create a bootable USB stick on Ubuntu

[4] “Create a bootable USB stick on Windows (Rufus)”

 

Step -1: Install Ubuntu LTS 16.04

Why Choose 16.04?  Tensorflow/CUDA/Android Studio trade-off

* Use USB booting to install Ubuntu 16.04

If host is windows, use Rufus [4].  If host is Ubuntu, see [3].

* Choose Ubuntu 16.04 desktop version. 

=> Check the update and 3rd party during the installation 

=> use others option and choose mount point / and format the partition

After successful installing Ubuntu 16.04

* Setup -> software update —> additional driver —> GTX 1080 —> choose Nvidia driver xxx to install Nvidia driver instead of using Xorg driver.

 這步似乎可以省略。之後 install CUDA10 會自動用 nvidia 最新的  driver.

$ sudo apt-get update

$ sudo apt-get upgrade 

 

 

Step -0.5: Install Matlab

Reference: Linux MATLAB 2018a installation

$ sudo mkdir /mnt/matlab

$ sudo mount -o loop R2018a_glnxa64_dvd1.iso /mnt/matlab

$ cd /mnt/

$ sudo /mnt/matlab/install 

等到安裝到 60% 會提示插入第二張 CD, 執行:

$ sudo mount -o loop R2018a_glnxa64_dvd2.iso /mnt/matlab

之後就 follow readme.txt 的 instruction.

Matlab 此時會使用 GTX 1080.

 

 

Step 0: Install emacs, git, and enable desktop sharing (vnc)

* sudo apt install emacs

* sudo apt install git

* vnc 可以參考下文。==> change to the following reference using ubuntu default desktop sharing!

How to Remote Access to Ubuntu 16.04 from Windows

=> use team viewer is better!!!

 

 

* Change locale 去除星期的中文字 

ps. edit /etc/default/locale to change the date format from lzh_TW -> en_US.UTF-8

 

Step 1: Install Ubuntu (LTS 16.04) Nvidia driver

Reference: 

1.2. ls /usr/localls   : CUDA

1.3. http://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html:cudnn

 

 

Step 2: Install Nvidia CUDA and cuDNN

Reference:

* CUDA 8.0 -> CUDA 10.1 (2019/3/1) -> CUDA 10.0 (3/8)

CUDA10.1 is too new to be compatible with tensor flow1.13!

Use CUDA10.0 instead

  1. sudo dpkg -i cuda-repo-ubuntu1604_8.0.61-1_amd64.deb
  2. sudo apt-get update
  3. sudo apt-get install cuda
  4. sudo dpkg -i cuda-repo-ubuntu1604-8-0-local-cublas-performance-update_8.0.61-1_amd64.deb 

$nvcc —version (may need to do   $sudo apt install nvidia-cuds-toolkit

$nvidia-smi

NewImage

Setup environment variables

export CUDA_HOME=/usr/local/cuda-8.0 
export LD_LIBRARY_PATH=${CUDA_HOME}/lib64 
 
PATH=${CUDA_HOME}/bin:${PATH} 
export PATH

  

* cuDNN: 6.0 -> 7.5 (2019/3/1)

  • Navigate to your <cudnnpath> directory containing cuDNN Debian file.
  • Install the runtime library, for example:
    sudo dpkg -i libcudnn7_7.0.2.43-1+cuda9.0_amd64.deb
  • Install the developer library, for example:
    sudo dpkg -i libcudnn7-dev_7.0.2.43-1+cuda9.0_amd64.deb
  • Install the code samples and the cuDNN Library User Guide, for example:
    sudo dpkg -i libcudnn7-doc_7.0.2.43-1+cuda9.0_amd64.deb

注意在 install cuDNN 後,依照 Nvidia cuDNN installation guide (reference 3) compile mnistCUDNN example.

遇到以下錯誤。

 

Can not use cuDNN on context None: cannot compile with cuDNN. We got this error: In file included from /usr/local/cuda-8.0/include/channel_descriptor.h:62:0, from /usr/local/cuda-8.0/include/cuda_runtime.h:90, from /usr/include/cudnn.h:64, from /tmp/try_flags_F2eFMF.c:4: /usr/local/cuda-8.0/include/cuda_runtime_api.h:1628:101: error: use of enum 『cudaDeviceP2PAttr' without previous declaration extern __host__ __cudart_builtin__ cudaError_t CUDARTAPI cudaDeviceGetP2PAttribute(int *value, enum cudaDeviceP2PAttr attr, int srcDevice, int dstDevice); ^

參考 https://github.com/Theano/Theano/issues/5856 解決這個問題。

Open the file:
/usr/include/cudnn.h

And try change the line:
#include “driver_types.h”

to:
#include <driver_types.h>

-------------------------------- 

在 2.3.1 installing from a Tar File.

Copy the following files into the CUDA Toolkit directory.

$ sudo cp cuda/include/cudnn.h /usr/local/cuda/include

$ sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64

$ sudo chmod a+r /usr/local/cuda/include/cudnn.h /usr/local/cuda/lib64/libcudnn*

不過用 2.3.2 installing from a Debian File (as I did).  在以上目錄 (/usr/local/cuda/include and lib) 卻找不到 cudnn or libcudnn files.

反而是在 /usr/include/x86_64-linux-gnu/include and lib, why?

NewImage

 

Step 3: Install Anaconda python, OpenCV, and Caffe and Caffe2

https://standbymesss.blogspot.tw/2016/09/ubuntu-1404-caffe-cuda-75-opencv-31.html

$ sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobuf-compiler
$ sudo apt-get install --no-install-recommends libboost-all-dev
$ sudo apt-get install libgflags-dev libgoogle-glog-dev liblmdb-dev
Install Atlas
 sudo apt-get install libatlas-base-dev

Step 3.1 Install Anaconda Python

Download anaconda2, use python 2.7.13 for caffe compatibility

$ bash Anaconda2-4.0.0-Linux-x86_64.sh

Download anaconda3, use python 3.7 but create 3.6 for tensorflow.

Step 3.2 Install OpenCV (2018/12/1 => 請參考後文)

參考 https://standbymesss.blogspot.tw/2016/09/ubuntu-1404-caffe-cuda-75-opencv-31.html

$ sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
$ unzip opencv-3.3.0.zip
$ cd  opencv-3.1.0/ $ mkdir release $ cd release $ cmake -DBUILD_TIFF=ON  -DENABLE_AVX=ON -DWITH_OPENGL=ON -DWITH_OPENCL=ON -DWITH_IPP=ON -DWITH_TBB=ON -DWITH_EIGEN=ON -DWITH_V4L=ON  -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=$(python -c "import sys; print(sys.prefix)")-DPYTHON_EXECUTABLE=$(which python)-DPYTHON_INCLUDE_DIR=$(python -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())")-DPYTHON_PACKAGES_PATH=$(python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")..
$ make -j8

test opencv

a. run python and do “import cv2″

b. using ./python/python demo.py

我遇到問題是 

GLib-GIO-Message:Using the 'memory'GSettings backend.

export GIO_EXTRA_MODULES=/usr/lib/x86_64-linux-gnu/gio/modules/

 

Step 3.2 Install caffe

git download caffe.

cd caffe directory.

$ cd python

$ for req in $(cat requirements.txt);do pip install $req;done

$ cd ..

$ cp Makefile.config.example Makefile.config

Modify Makefile.config based on the reference.

$make all -j8

$make test -j8

all OK

$make runtest -j8

encounter library libhdf5_hl_so.8 problem!!

Add ${ANACONDA2}/lib path to LD_LIBRARY_PATH to solve this problem.

NewImage

 

pycaffe

make python

 

Step 3.3 Install caffe2

# for Ubuntu 16.04
sudo apt-get install -y --no-install-recommends libgflags-dev

 

# for both Ubuntu 14.04 and 16.04
sudo apt-get install -y --no-install-recommends \
      libgtest-dev \
      libiomp-dev \
      libleveldb-dev \
      liblmdb-dev \
      libopencv-dev \
      libopenmpi-dev \
      libsnappy-dev \
      openmpi-bin \
      openmpi-doc \
      python-pydot
sudo pip install \
      flask \
      future \
      graphviz \
      hypothesis \
      jupyter \
      matplotlib \
      pydot python-nvd3 \
      pyyaml \
      requests \
      scikit-image \
      scipy \
      setuptools \
      six \
      tornado

 git clone –recursive https://github.com/caffe2/caffe2.git && cd caffe2

make &&cd build && sudo make install

python -c ‘from caffe2.python import core’ 2>/dev/null &&echo“Success”||echo“Failure”

 

python -m caffe2.python.operator_test.relu_op_test

 

 

 

Step 4: Install TensorFlow

https://blog.csdn.net/hgdwdtt/article/details/78633232

sudo apt-get install libcupti-dev

conda create -n tensorflow python=3.6

source activate tensorflow

 

 

Cuda-10.1 seems not supported by tensorflow-gpu.

Need to compile from source : difficult and not recommend

 

pip install —upgrade tensorflow-gpu

 Got the following error message!!

_mod = imp.load_module(‘_pywrap_tensorflow_internal’, fp, pathname, description)
File “/home/alu/anaconda3/envs/tensorflow/lib/python3.6/imp.py”, line 243, in load_module
return load_dynamic(name, filename, file)
File “/home/alu/anaconda3/envs/tensorflow/lib/python3.6/imp.py”, line 343, in load_dynamic
return _load(spec)
ImportError: libcublas.so.10.0: cannot open shared object file: No such file or directory

 

Solve this problem by installing cuda10.0.! 

 

 

Install Keras

Pip install keras

  

Install PytTorch

conda install pytorch torchvision cudatoolkit=10.0 -c pytorch

 

 

Step 5: Install MXNET

pip install mxnet-cu80==0.11.0

主要是用來 run mtcnn for face detection.

 

 

 

 

Step 5: install tflearn

pip install tflearn or condo install tflearn?

 

Step 6: install caffe/caffe2? to run faster R-CNN 

Reference:  

  • 2. caffe Ubuntu 16.04 or 15.10 Installation Guide
  • 需要 compile from source code.  可能要先用 GCP without CPU 走過一次。
  • 另外 caffe 最好是用 python 2.7.
  • > conda create -n y27 python=2.7 anaconda
  • pip install –ignore-installed —upgrade 
    https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.3.0-cp27-none-linux_x86_64.whl 

$ sudo mkdir /mnt/matlab$ sudo mount -o loop R2018a_glnxa64_dvd1.iso /mnt/matlab$ cd /mnt/$ sudo ./mnt/matlab/install

 

Ubuntu 20.04 LTS

Reference

[1] Ubuntu 20.04 CUDA 11.1 cuDNN 8.0.4 install

[2] Create a bootable USB stick on Windows

基本設定

UntitledImage

Process

Install Ubuntu 20.04 LTS
1.     Create USB bootable drive using Rufus (windows) using the DataTraveler USB drive (32GB), [2]

2.    遵循上面 link 的指示,選擇 Ubuntu 20.04 LTS desktop iso 如下。

UntitledImage

3.Boot from USB and do the installation.

Install CUDA (11.1) and CuDNN (8.1.1)

Referece
[1] https://jianjiesun.medium.com/ubuntu-20-04-cuda-11-1-cudnn-8-0-4-install-62b7fe24941d.   Errors for copy cudnn!!!  Use the following!!!

Or

[2] https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html

實際和 [1] 有幾點不同:

1.    Driver installation 很難搞。最後成功把 nvidia 官網download 455 driver installed.  但忘記如何搞定。 Do “$nvidia-smi -l”   to check the driver installation.

2.    在 install CUDA11.1,  記得 bypass install driver (x  blank).   Do “$make all”; in the $NVIDIA_CUDA-11.1_Sample directory to check CUDA installation.

3.    Install cudnn [1] and [2]

Method1:
直接 include and lib. 但是 path 如下:

$ sudo cp cuda/include/cudnn*.h /usr/local/cuda/include

$ sudo cp -p cuda/lib64/libcudnn* /usr/local/cuda/lib64

$ sudo chmod a+r /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn*

 

Method 2:
Use deb dpkg to install (i) libcudnn; (ii) dev; (iii) sample code;

$ sudo
dpkg -i libcu sudo dpkg -i libcudnn8-dev_8.x.x.x-1+cudax.x_amd64.deb

$ sudo dpkg -i libcudnn8-dev_8.x.x.x-1+cudax.x_amd64.deb

$ sudo dpkg -i libcudnn8-samples_8.x.x.x-1+cudax.x_amd64.deb

   

Method2 seems to be easier, especially for sample code. 不過我先用 method1,就沒有用 method2。

 

4.    Verify Install cudnn [2]

Copy the cuDNN samples to a writable path.

$cp -r /usr/src/cudnn_samples_v8/ $HOME

Go to the writable path.

$ cd  $HOME/cudnn_samples_v8/mnistCUDNN

Compile the mnistCUDNN sample.

$sudo apt-get install libfreeimage3 libfreeimage-dev

$make clean && make

Run the mnistCUDNN sample.

$ ./mnistCUDNN

If cuDNN is properly installed and running on your Linux system, you will see a message similar to the following:

Test passed!

 

為了 check cudnn install, 我從 sda6 copy /usr/src/cudnn_sample code to verify.

 

Install Anaconda, create virtual environment, 安裝pytorch and常見套件
1.    Download anaconda and “$ bash
Anaconda3-2020.11-Linux-x86_64.sh” to install anaconda

2.    Create a virtual environment using conda with python 3.6

$ conda create –name torch36 python=3.6

$ conda activate torch36

3.    把 source activate torch36 加入 .bashrc, 重開 terminal to install pytorch.  到 pytorch 官網選擇 ubuntu, cuda=11.1, …

$ conda install pytorch torchvision
torchaudio cudatoolkit=11.1 -c pytorch -c conda-forge

4.    
$ conda install matplotlib,pandas, jupyter, jupterlab… 安裝常用的套件。我產生一個 torch36.yml.  只要 $ conda env create -f torch36.yml

 

Install other software 常用的 software 如 emacs, git, kdiff3, teamviewer, dropbox.

Emacs:   $sudo apt install emacs

Git:  $ sudo apt install git

Kdiff3: $ sudo apt install kdiff3

Teamviewer:

$ sudo apt update

$ sudo apt install gdebi-core wget

$ wget https://download.teamviewer.com/download/linux/teamviewer_amd64.deb

$ sudo apt install ./teamviewer_amd64.deb

$ teamviewer  => run teamviewer

Dropbox:  直接在 Application search dropbox
(not caje dropbox) and install  

 

Install huggingFace transformer
可以用 pip or conda, https://github.com/huggingface/transformers

Pip:
$ pip install transformers

Conda:
$ conda install -c huggingface transformers

我用 conda to install huggingface
transformers.

從 Portainer 了解 Docker 運作

by allenlu2007

虛擬化無處不在。1998 VMware 成立標誌 virtual machine (VM) 正式進入商業化。可以說 VM enable 之後的 cloud 服務 例如 Amazon/AWS, Microsoft/Azure, Google/GCP. VM 讓有限的 servers 分身成 virtual machines 服務數百或數千倍的使用者,儘量 exploit multiple user 的 statistical multiplexing gain. 同時藉著 virtual machine configuration 提供差異化的服務和收費。

VM 當然不只是用於 cloud 服務, 也可以用於 edge machine or device. 其實 VMware 的初衷是用於 edge or terminal device, 畢竟當時還沒有 cloud 服務. 不過在一台 computer install 多個 VMs 似乎只是少數 geeks or nerds 的嗜好,並非一般人的需要。

倒是一個新的趨勢是跨平台的應用需要類似 "virtual machine" on edge machine or device. 舉個例子,在 Windows/Mac/Linux 的平台可以 run NAS/BT/Wordpress 服務, 或是 AI framework and application. 我們需要跨系統平台 (Windows/Mac/Linux) App 執行不同的服務. 這些 App 大多是 linux-base. 但 linux 本身也是極端 fragmented, 不同的 distribution (Ubuntu/CentOS/Redhat/Debian/…) 以及不同的版本。因此類似 “application virtual machine" 可以自由運行在不同平台就非常方便 deploy service.

Virtual machine 一個主要問題是太佔系統資源,需要完整的 Guest OS, Bins/Libs, 如上圖右。一台 computer 可能只能運行兩三個 virtual machine. Docker 因此應運而生如上圖左。Docker 上的 container 類似 VM, 但輕薄很多,只有必要的 Bins/Libs. 下圖的卡通生動的描述:鯨魚就是 Docker, 一個 docker 可以有很多的貨櫃 (container), 每一個 container 可以視為是 light weight virtual machine. 一個 docker 可以運行多個,甚至十數個 light weight container of services. 此外,一部 computer 也可以運行多個 docker. 但一般只運行一個 docker 管理多個 containers.

Virtual machines 和 containers 都是在同一個 host computer 分享相同的資源, e.g. CPU, GPU, Memory, etc. Docker and container 通常用於一般 服務, 因為 containers 之間的隔離性和保密性比 virtual machine 差。Virtual machine 對於需要高度保密服務,例如 payment, copyright, 生物特徵仍然有必要。例如手機一般會用 TEE (Trusted Execution Environment) on Hypervisor 處理 payment 或是 finger print 或是 face ID 的資訊。 TEE 可以視為一種 VM (light weight on light OS).

VM vs. docker container 有點像 process vs. thread in a multi-task OS. Process 之間都是隔離和獨立。 Thread 之間可以是合作關係甚至分享資源。

Portainer for Docker Management

本文聚集在 docker. 我們跳脫一般從抽象的 command line docker 入手,直接從 portainer dashboard 介紹 docker 的運行。

Portainer 本身就是一個 container, 具有以下的特性:

  • 輕量級(Image 少於 30M)
  • 可以用於 Docker 監控和構建,提供 Docker s環境的詳細信息
  • 漂亮的Dashboard,可在界面管理 Container、Image、Network、Volume、Config
  • 內置的操作模板
  • 支持Docker-Swarm 集群監視

先假設 docker 和 portainer 已經安裝好,例如使用 OpenMediaVault for NAS solution.

Step 1: 第一次啟動 portainer 需要設定 Username and Password 如下:

Step 2: 如果是在 docker 的 host 安裝 portainer (in this case), 選擇 local docker.

Step 3: 此時顯示 local docker 的 summary information. 包含 (1) stack; (3) containers; (3) volumes; (3) images.

Step 4: 點擊任一項目 (stack/container/volume/image) 進入 Dashboard (Endpoint summary), 就是下圖左 panel 第一項,右邊內容和上圖一樣。
我們逐一解釋 panel 的項目,藉此了解 docker 的運作。

Dashboard -> Container

選擇左邊 panel 的 container. 這是 docker 核心功能。這裡看到有 3 個 containers. 從 Container Name 可以粗略判斷提供什麼服務。例如中間 container 就是 portainer 本身,提供 docker 管理服務。其他兩個是我之前執行的 wordpress 和 qbittorrent 兩個 containers 提供 blog 和 BT 服務。

Status: 可以 start/stop/kill/… 這個 container (service).

Image: 代表這個 container 是由該 image 創造出來的。一個 image 可以創造出多個不同的 containers. 另外 image 是 Read-Only 無法改變內部的設置,例如 library, module, etc. 只有在創建 container, image 會被包覆在一層 "think R/W layer" 之下。通過這層 layer 才可以改變 container 內部的設置。

Image 和 container 的關係,相當於與 OOP 中 class and object 的關係。

Stack: Optional. 後面再討論。
Ports: 相反是 container 開放給外部的 service 或是 access. 注意有兩個 port number, 一個對應 container 內部的 port number, 另一個對應外部 access container 的 port number, 一般相同,但不需要一樣。
Created and Ownership 很直觀不用說明。

我們後面用實例討論如何 Add container.

Dashboard -> Image

選擇左邊 panel 的 image. 先看右下半 Images 部分,代表 docker 所有的 images. Containers 就是從 images 創造出來,所以 image created 日期一定早於 container crated 日期。 Image 一般是從 Registry pull 來的,就是右上半 Pull image 部分。最普遍的 registry 是 DockerHub? 可以到 DockerHub (project 之於 github 類似 image 之於 DockerHub) search images https://hub.docker.com. 常用的 image 包含各類的 linux distributions 以及各種 service or database. Image 可以被 remove/import/export/…

Dashboard -> Volumes [@ithomeDay21]

Volume 是 docker 存放 data 的地方。選擇左邊 panel 的 volume.
其中有 3 個 volume, 從 Name 就可以判斷中間的 volume 是 portainer 存放 data 的 directory. Mounting point 是對應 host 的絕對路徑。

點擊 portainer_data volume 可以得到更明確的資訊:前面的部分都一樣。最後有對應的 Container Name.

What and Why Volume in Docker

By default 所有在 container 中建立的檔案都儲存在 container thin R/W layer 上,這表示:

  1. 當container不再執行時,資料無法被留存下來;當另一個 process 需要,也很難將資料由container取出。
  2. container R/W layer 和執行container的 host 是緊密耦合的,無法輕易地搬移資料。
  3. 寫入container R/W layer 需要儲存驅動器 (storage driver) 來管理檔案系統 (filesystem)。儲存驅動器使用 Linux 核心提供了統一 (union) 的檔案系統。和使用直接寫進主機檔案系統的資料卷宗 (data volume) 比起來,這個額外的抽象化降低了效能。

因此必須有其他的機制,將 container 中的檔案留存在 host 上,Docker 有兩種作法:volume 和 bind mount. 另外在 Linux 作業系統上的 Docker 還可使用 tmpfs mount (暫存)。這三種方式的差異可用下圖表示。

這三者的差異:

  1. Volume 存放在主機檔案系統中由 Docker 管理的地方,在 Linux 作業系統是 /var/lib/docker/volumes/ 此路徑。非 Docker 的 process 不應該修改檔案系統中的這一部分。要在 Docker 中留存資料,volumes 是最好的方法。
  2. Bind mount 可存放在主機檔案系統中的任何地方,非 Docker process或 Docker 容器可隨時修改。
  3. tmpfs mount 只存放在主機的記憶體中,不會寫入主機的檔案系統。

Volume 是 Docker 最推薦存放 persisting data 的機制,使用 Volume 有下列優點

  • Volumes are easier to back up or migrate than bind mounts.
  • You can manage volumes using Docker CLI commands or the Docker API.
  • Volumes work on both Linux and Windows containers.
  • Volumes can be more safely shared among multiple containers.
  • Volume drivers allow you to store volumes on remote hosts or cloud providers, to encrypt the contents of volumes, or to add other functionality.

Dashboard -> Stacks

Stack 不是傳統資料結構的 stack,而是 “stack" 不同的 images 構成完整的 container 可以提供完整的 service. 要建立一個可提供應用程式完整執行環境的 Container image,要先從一個 Base Image (例如 Ubuntu OS) 開始疊起,一層層將不同 Stack 的 image 疊加上去,最後組合成一個應用程式所需Container 執行環境的 image, 如下圖。

一個Stack就是一層Container image

實例操作

舉例來說,假設一個網頁執行環境需要有OS、Apache網站伺服器、MySQL資料庫、Ruby執行環境等不同的Stack。

最常用的基礎映象檔就是ubuntu映象檔,這是用來建立Container的根目錄架構,若採用了不同的OS映象檔,就會變成是那個OS的目錄架構。

第一個動作就是先 pull the ubuntu 的基礎 image: 只要在命令列輸入sudo docker pull ubuntu,預設pull指令都是存取Docker Hub服務。這個指令會從Docker Hub上下載名稱為ubuntu的 image 到本機端。

接著,要將新的一層Stack加入ubuntu基礎映象檔中,例如Apache,得先用Docker執行(Docker run指令)這個基礎 image,來建立這個 image 的Container,然後在Container中安裝Apache,安裝完成後,再將Container打包成另一個新的 image。

第二層繼續反覆這樣的程序,這時候就是直接從ubuntu-Apache所建立的 image 開始安裝下一層的MySQL程式,同樣也是先執行ubuntu image,再執行MySQL安裝程序。

說來複雜,實際執行過程,執行映象檔和安裝Apache是一行指令,命令Docker從ubuntu映象檔來建立新的Container同時在這個Container內執行Apache安裝指令。

當Apache安裝完成後,Container的壽命也跟著結束了,除非是Daemon式的背景程式,那麼這個Container才會一直存活。就算只是在Container裡面執行一個ls(列出目錄架構)的指令,如sudo docker run ubuntu ls -1。Container也是在ls–l指令結束後也同時關閉了。一行指令就建立了一次Container,也關閉了這個Container。

Docker for Deep Learning and Android Studio

by allenlu2007

Reference

[1] Dennis TS, Medium, “使用Docker來建置Deep Learning環境”.

[2] 蝈蝈, 知乎, “Docker,救你于「深度学习环境配置」的苦海”.

[3] twtrubiks, github, https://github.com/twtrubiks/docker-tutorial

[4] Docker, “Dcoker Desktop for Mac

 

過去都是使用anaconda+tensorflow+keras+pytorch 來開發Deep Learning,但時間久了會發現直接安裝的cuda與cudnn的更新相當麻煩,久了也難以管理,因此學習使用Docker來建立Deep Learning環境,大部分的步驟都與官網的說明相同,這篇文章就是建置過程的一個紀錄。

使用工具

  1. Docker
  2. nvidia-docker
  3. Deepo

作業系統

ubuntu 16.04

UntitledImage

 

Docker 概念

先了解一下 Docker 中的幾個名詞,分別為

Image

映像檔,可以把它想成是以前我們在玩 VM 的 Guest OS( 安裝在虛擬機上的作業系統 )。

Image 是唯讀( R\O )

Container

容器,利用映像檔( Image )所創造出來的,一個 Image 可以創造出多個不同的 Container,

Container 也可以被啟動、開始、停止、刪除,並且互相分離。

Container 在啟動的時候會建立一層在最外(上)層並且是讀寫模式( R\W )。

這張圖解釋了 Image 是唯讀( R\O )以及 Container 是讀寫模式( R\W ) 的關係

UntitledImage

Image 是一个个配置好的环境。 container 是image的具体实例。 image 和 container 的关系,相当于与 class and object 的關係。

Registry

可以把它想成類似 GitHub,裡面存放了非常多的 Image ,可在 Docker Hub 中查看。

 

安裝 Docker 

參考 https://docs.docker.com/install/linux/docker-ce/ubuntu/

$ sudo apt-get update

$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add –

 

$ sudo add-apt-repository \
“deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable”

$ sudo apt-get update

$ sudo apt-get install docker-ce docker-ce-cli containerd.io

 

To verify:

$ sudo docker run hello-world

 

安裝 nvidia-docker 

一般來說,若只是要使用虛擬環境,只要安裝完Docker就好了,但若是要開發Deep Learning應用,就必須使用到GPU,而nvidia-docker就是docker的一個包裝,他可以輕易的讓你的虛擬環境使用GPU。安裝程序也是參照官網。

加入金鑰
$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \
$ sudo apt-key add –

2. 加入 repository

# Add the package repositories
$ 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-container-toolkit
$ sudo systemctl restart docker

此時 docker = nvidia-docker, check by 

$ sudo docker –version

$ sudo nvidia-docker –version

All the same:

Docker version 19.03.7, build 7141c199a2

 

6. 用CUDA image來作測試

#### Test nvidia-smi with the latest official CUDA image
$ sudo docker run –gpus all nvidia/cuda:10.0-base nvidia-smi

 

安裝 Deepo

Deepo 是一個含有許多Deep Learning Framework的docker image,使用這個image,可以讓我們快速的建置一個虛擬環境。

If use old version (10.0), if 10.1 version ignoring the :py36-cu100

$ sudo docker pull ufoym/deepo:py36-cu100

Install jupyter

$ sudo docker pull ufoym/deepo:all-jupyter-py36-cu100

Test the nvidia-smi in deepo

$ sudo docker run –gpus all –rm ufoym/deepo:py36-cu100 nvidia-smi  ## —rm means remove container after exit

 

如何用 Docker

Create a bash of the nvidia/deepo docker

$ sudo docker run –gpus all -it ufoym/deepo:py36-cu100 bash 

$ ctl-d  # to quit the bash

 

Create a bash of the nvidia/deepo docker 並 mount host directory to docker (-v)

$ sudo docker run –gpus all -it -v /host/data:/data -v /hsot/config:/config ufoym/deepo:py36-cu100 bash 

 

檢查 Deepo Framework Version

Create a bash of the nvidia/deepo docker and check the framework is installed and version

$ python

>>> import tensorflow
>>> import sonnet (AttributeError: module ‘tensorflow’ has no attribute ‘GraphKeys’)
>>> import torch
>>> import keras (no need for tensorflow2)
>>> import mxnet
>>> import cntk
>>> import chainer
>>> import lasagne
>>> import caffe
>>> import caffe2

Use pip list to check the framework version

$ pip list

mxnet-cu100 1.5.1.post0

tensorflow-estimator-2.0-preview 2.0.0  
tensorflow-probability 0.8.0
termcolor 1.1.0
tf-nightly-gpu-2.0-preview 2.0.0.dev20191002  (tensorflow 2.0)
Theano 1.0.4+unknown

torch 1.3.0  (pytorch 1.3)
torch-nightly 1.2.0.dev20190805 (why nightly 1.2.0?)
torchvision 0.5.0a0+1e857d9

Keras 2.3.1
Keras-Applications 1.0.8
Keras-Preprocessing 1.1.0

mxnet-cu100 1.5.1.post0

mxnet-cu100 1.5.1.post0

Lasagne 0.2.dev1

$ caffe —version  

caffe version 1.0.0

$ darknet

$ th (for torch 7) => deprecated, no use.

 

Deepo Problem (py36, cuda10.0)

It seems to have lots of problems.

1. Pytorch: 

Issue: File “/usr/local/lib/python3.6/dist-packages/torchvision/models/inception.py”, line 168, in Inception3
@torch.jit.unused
AttributeError: module ‘torch.jit’ has no attribute ‘unused’

2. Tensorflow (2.0)

Issue: File “mnist.py”, line 15, in from tensorflow.examples.tutorials.mnist import input_data ModuleNotFoundError: No module named ‘tensorflow.examples.tutorials’

Ans: https://blog.csdn.net/qq_43060552/article/details/103189040?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

 

Docker Cheat Sheet and GUI

Check docker version

$ sudo docker –version
Docker version 19.03.7, build 7141c199a2

Check docker image

$ sudo docker images

REPOSITORY    TAG         IMAGE ID     CREATED     SIZE
ufoym/deepo      latest        69b30aa9ad32 5 weeks ago 12.8GB
nvidia/cuda         latest       9e47e9dfcb9a 3 months ago 2.83GB
nvidia/cuda       10.0-base  841d44dd4b3c 3 months ago 110MB
nvidia/cuda       10.1-base  3b55548ae91f 3 months ago 106MB
ufoym/deepo py36-cu100  394b64d11e28 4 months ago 10.9GB
ufoym/deepo all-jupyter-py36-cu100 cf60a305ba7b 6 months ago 10.9GB
hello-world    latest             fce289e99eb9 14 months ago 1.84kB

建立 image (類似 git)

$ sudo docker create -it –name busybox busybox

or use docker pull

$ sudo docker pull ufoym/deepo:all-jupyter-py36-cu100

刪除 Image

$ docker rmi [OPTIONS] IMAGE [IMAGE…]

查看目前運行的 container

$ docker ps
查看目前全部的 container( 包含停止狀態的 container )

$ docker ps -a

新建並啟動 Container (docker run)

docker run [-it] some-image 创建某个镜像的容器。注意,同一个镜像可以通过这种方式创建任意多个container. 加上-it之后,可以创建之后,马上进入交互模式。

$ docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG…]

如何查询命令参数: docker可以看docker客户端有那些基本命令; 对应每一条命令,想看看具体是做什么的,可以在后面加一个 –help查看具体用法,例如对于run命令: docker run –help

$ docker run –gpus all nvidia/cuda:10.0-base nvidia-smi

$ docker run –gpus all -it ufoym/deepo:py36-cu100 bash   ## -it means interactive; —rm means quit container after exit

$ docker ps -a   ## list all containers

$ docker rm container-id     ## docker rmi image

退出 container

ctl-d or exit to quit container.  ctl-q-p exit but container is running.

 

Volume

接下來要介紹 Volume,Volume 是 Docker 最推薦存放 persisting data( 數據 )的機制,

使用 Volume 有下列優點

Volumes are easier to back up or migrate than bind mounts.
You can manage volumes using Docker CLI commands or the Docker API.
Volumes work on both Linux and Windows containers.
Volumes can be more safely shared among multiple containers.
Volume drivers allow you to store volumes on remote hosts or cloud providers, to encrypt the contents of volumes, or to add other functionality.
A new volume’s contents can be pre-populated by a container.
在 container 的可寫層中,使用 volume 是一個比較好的選擇,因為他不會增加 container 的容量,

volume 的內容存在於 container 之外。

UntitledImage

Network

建議大家花點時間研究 docker 中的 network,會蠻有幫助的 😃

查看目前 docker 的網路清單

docker network ls [OPTIONS]
詳細可參考 https://docs.docker.com/engine/userguide/networking/

docker 中的網路主要有三種 Bridge、Host、None,預設皆為 Bridge 模式。

 

管理 Docker GUI 的工具 (portainer, ref[3])

$ sudo docker volume create portainer_data

$ docker run –name=portainer -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

reference: https://github.com/twtrubiks/docker-tutorial#volume

 

Portainer Example

$ sudo docker run -it ufoym/deepo:all-jupyter-py36-cu100 bash

2 containers:  ufoym/deepo…..-cu100; and portainer

UntitledImage

2 images:  ufoym/deepo….-cu100; and portaner:latest

UntitledImage

Since no —rm, after ctl-d, container becomes:

UntitledImage

image is the same.

After I remove the stopped container and do

$ sudo docker run -it —rm ufoym/deepo:all-jupyter-py36-cu100 bash

same as before, after ctl-d container becomes:

UntitledImage

 

Docker jupyter notebook 服务

1. create a container for remote visit

$ sudo nvidia-docker run -it -p 7777:8888 –ipc=host -v /home/alu/Documents/gby:/gby –name gby-notebook ufoym/deepo:all-jupyter-py36-cu100

Container and image.

UntitledImage

UntitledImage

2. Start jupyter notebook after creating a container

$ jupyter notebook –no-browser –ip=0.0.0.0 –allow-root –NotebookApp.token= –notebook-dir=’/gby’

 

3. Local host do:

http://192.168.1.224:7777

 

 

Docker and Portainer for Mac

Install docker

Step1: get docker.dmg from https://hub.docker.com/editions/community/docker-ce-desktop-mac/

Step2: run docker.dmg and the status bar shows: 

UntitledImage

Step3: open a terminal and run: docker version => 

(tf) Allende-MBP:cheers2019 allenlu$ docker version
Client: Docker Engine – Community
Version: 19.03.8
API version: 1.40
Go version: go1.12.17
Git commit: afacb8b
Built: Wed Mar 11 01:21:11 2020
OS/Arch: darwin/amd64
Experimental: false

Server: Docker Engine – Community
Engine:
Version: 19.03.8
API version: 1.40 (minimum version 1.12)
Go version: go1.12.17
Git commit: afacb8b
Built: Wed Mar 11 01:29:16 2020
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: v1.2.13
GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429
runc:
Version: 1.0.0-rc10
GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd
docker-init:
Version: 0.18.0
GitCommit: fec3683

Step4: Run: docker run hello-world to verify that docker is pulling images and running.

(tf) Allende-MBP:cheers2019 allenlu$ docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the “hello-world” image from the Docker Hub. (amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/

For more examples and ideas, visit:
https://docs.docker.com/get-started/

 

Install portainer

Install portainer 的方式的之前一樣。 portainer 就是一個 image.

$ docker volume create portainer_data

$ docker container run -d \

-p 9000:9000 \

-v /var/run/docker.sock:/var/run/docker.sock \

portainer/portainer

Use http://localhost:9000/ to do the portainer

 

 

 

 

增進工程師效率 Python Script Debugging Tools

by allenlu2007

先說結論,我強烈推薦 VS Code.

IDE Python Debugging

The most famous python IDEs integrating coding, lint, execution and debugging are PyCharm and VS Code.

PyCharm 是專門為 python 開發。有免費以及付費的版本。我自己使用的經驗是 too heavy, 比較適合專業 python projects and professionals.

VS Code

我非常喜歡用另一個免費(開源?) IDE, VS Code (Visual Studio Code) for python script coding and debugging. VS Code 是 Microsoft 提供的免費軟體。不但是跨Windows/MacOS/Linux 平台,同時支持多種 programming language, 包含 Python, Javascript, Julia, etc. VS Code 有許多外部插件, 可以擴充 VS Code 的功能,包含多種 programming language 的支持。下圖就是和 python/julia 相關的基本插件:Python (linting, debugging), Code Runner (run code), Autopep8 (formatter).

另外 VS Code native 整合 git (revision control and remote repository), 支持 virtual environments: virtualenv and conda. 對於測試不同 python versions 和 packages 很方便。

VS Code 非常適合 debug 輕量級 scripting and fast prototyping.

Command Line Python Debugging

最常見的 debugging 方法就是 print(variable). 主要的優點是不需要額外的工具或設定。 兩個缺點:(1) 切換 debugging (enable printing) and non-debugging (disable printing) 很麻煩。 (2) Print 比較難定位 function and context, 特別有多個 python files.

除了 IDE debugging 和 print debugging 兩個極端,是否有介於之間的 debugging 方法? 答案是肯定的。這裏介紹兩種工具:PySnooper and Logging.

PySnooper

PySnooper 號稱是 Poor man's python debugger. [@rachumPySnooper2020], [@jackPythonDiaoShiShenQiZhiPySnooper2019], [@cvPythonGaoBiePrint2019] Github 開源的 PySnooper,允許和print執行相同的操作,只需向感興趣的函數添加一個裝飾器行,而不是小心地創建正確的列印行。將會得到函數的詳細日誌,包括運行了哪些行、何時運行、以及何時更改了局部變量。

Logging

很多參考文章,此處不贅述。
[@unknownPythonLogging2012] and [@leiReplaceYour2014]

Reference

增進工程師效率 DataFrames: Load CSV and Plot in Python/Julia

by allenlu2007

Python DataFrame

Create DataFrame

  • Direct input

  • Use dict: Method 1: 一筆一筆加入。

import pandas as pd
dict1 = {'Name': 'Allen' , 'Sex': 'male', 'Age': 33}
dict2 = {'Name': 'Alice' , 'Sex': 'female', 'Age': 22}
dict3 = {'Name': 'Bob' , 'Sex': 'male', 'Age': 11}
data = [dict1, dict2, dict3]
df = pd.DataFrame(data)

>>> df
   Age   Name     Sex
0   33  Allen    male
1   22  Alice  female
2   11    Bob    male

Method 2: 一次加入所有資料。

import pandas as pd
name = ['Allen', 'Alice', 'Bob']
sex = ['male', 'female', 'male']
age = [33, 22, 11]
all_dict = {
    "Name": name,
    "Sex": sex,
    "Age": age
}
df = pd.DataFrame(all_dict)

>>> df
    Name     Sex  Age
0  Allen    male   33
1  Alice  female   22
2    Bob    male   11
  • Read csv
import pandas as pd
df = pd.read_csv('xxx.csv')

Basic Viewing Command

  • df.head(2) or df.tail(2)
  • df.shape
  • df.info()
  • df[0:2] or df['Name'][0:2] or df[['Name', 'Age']][0:2]
  • df.count() to count row number or to add condition.
>>> df.head(2)
   Age   Name     Sex
0   33  Allen    male
1   22  Alice  female
>>> df.tail(2)
   Age   Name     Sex
1   22  Alice  female
2   11    Bob    male
>>> df.shape
(3, 3)
>>> df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3 entries, 0 to 2
Data columns (total 3 columns):
Age     3 non-null int64
Name    3 non-null object
Sex     3 non-null object
dtypes: int64(1), object(2)
memory usage: 152.0+ bytes
>>> df[0:2]
   Age   Name     Sex
0   33  Allen    male
1   22  Alice  female
>>> df['Name'][0:2]
0    Allen
1    Alice
Name: Name, dtype: object
>>> df[['Name','Age']][0:2]
    Name  Age
0  Allen   33
1  Alice   22
>>> df.count()
Age     3
Name    3
Sex     3
dtype: int64
>>> df[df['Layer'] == 'Conv2d'].count()

Basic Data Manipulation

可以參考 [@ithomeDi142016]

  • add/delete
  • sort
  • indexing

Create sub-dataFrame with row on condition and column on values

# select rows by conditions
dfPlot = df[df['Layer']=='Conv2d']
dfPlot.reset_index(inplace = True)

# select columns by name
dfPlot = dfPlot[['Layer', 'ChI', 'ChO']

Python Plot

Python plot 使用標準 matplotlib.pyplot.

import matplotlib.pyplot as plt

def dfPlot(df):

    dfPlot = df[df['Layer'] == 'Conv2d']
    dfPlot = dfPlot[['Layer', 'ChI', 'IFmapX', 'IFmapY', 'ChO', 'OFmapX',
                     'OFmapY', 'ParamW', 'MAC', 'MAC2W', 'MAC2IF', 'MAC2OF']]
    dfPlot.reset_index(inplace=True, drop=True)

    logger.debug("dfPlot size = \n%s" % (dfPlot.count()))
    logger.debug("dfPlot = \n%s" % (dfPlot))

    plt.style.use("ggplot")
    plt.figure()
    #plt.plot(dfPlot.index, dfPlot['ParamW'])
    plt.plot(dfPlot.index, dfPlot['MAC2W'])
    plt.plot(dfPlot.index, dfPlot['MAC2IF'])
    plt.plot(dfPlot.index, dfPlot['MAC2OF'])
    plt.xlabel('layer')
    plt.ylabel('loss')
    plt.show()

更方便是直接用 pandas.DataFrame.plot function. 實際的例子如下。要加上 plt.show() 出圖。使用 Jupyter notebook 可以忽略 plt.show().

import tensorflow
import keras
import pandas as pd
import numpy as np
import math
import random
import matplotlib.pyplot as plt

# #Generate a sin wave with no noise
# First, I create a function that generates sin wave with/without noise. Using this function, I will generate a sin wave with no noise. As this sin wave is completely deterministic, I should be able to create a model that can do prefect prediction the next value of sin wave given the previous values of sin waves!
# 
# Here I generate period-10 sin wave, repeating itself 500 times, and plot the first few cycles.

def noisy_sin(steps_per_cycle = 50,
              number_of_cycles = 500,
              random_factor = 0.4):
    '''
    random_factor    : amont of noise in sign wave. 0 = no noise
    number_of_cycles : The number of steps required for one cycle
    
    Return : 
    pd.DataFrame() with column sin_t containing the generated sin wave 
    '''
    random.seed(0)
    df = pd.DataFrame(np.arange(steps_per_cycle * number_of_cycles + 1), columns=["t"])
    df["sin_t"] = df.t.apply(lambda x: math.sin(x * (2 * math.pi / steps_per_cycle)+ random.uniform(-1.0, +1.0) * random_factor))
    df["sin_t_clean"] = df.t.apply(lambda x: math.sin(x * (2 * math.pi / steps_per_cycle)))
    print("create period-{} sin wave with {} cycles".format(steps_per_cycle,number_of_cycles))
    print("In total, the sin wave time series length is {}".format(steps_per_cycle*number_of_cycles+1))
    return(df)

steps_per_cycle = 10
df = noisy_sin(steps_per_cycle=steps_per_cycle,
              random_factor = 0)

n_plot = 8
df[["sin_t"]].head(steps_per_cycle * n_plot).plot(
      title="Generated first {} cycles".format(n_plot),
      figsize=(15,3))
plt.show()

Reference

iThome, Tony. 2016. “[第 14 天] 常用屬性或方法(3)Data Frame.” iT
邦幫忙::一起幫忙解決難題,拯救 IT 人的一天. 2016.
https://ithelp.ithome.com.tw/articles/10185922.

增進工程師效率 – Use loggin instead of print to debug in Python

by allenlu2007

TBA

Reference

iCoding – We Coding …: http://icodingtw.blogspot.com/2012/08/logging.html

[Python] logging 教學: https://stackoverflow.max-everyday.com/2017/10/python-logging/

替换你的print(logging模块超简明指南): https://www.zlovezl.cn/articles/replacing-print-simple-introduction-to-logging/

 

 

Debug method in Python

 

1. IDE:

VS Code, PyCharm

 

2. Command line base

Poor man’s debugging tool: peeping variable

Logging package

平行公理和微分幾何平行移動(Parallel Transport)

by allenlu2007

垂直和平行都是幾何最重要的基石。

  • 垂直的局部性質很直接,兩直線相交,夾角為 90 為垂直。一般人隨手可以畫出垂直相交線,即使在曲面也不例外。垂直的微分定義是兩直線切向量內積為 0.
  • 平行的概念看似直接,兩直線永不相交。在歐幾里德平面幾何很容易想像。兩個問題:(A) 這樣平行直線唯一嗎?或一定存在嗎? (B)平行是否有局部的微分定義
  • (A) 的回應就是平行公理;(B)的回應就是平行移動 (parallel transport).

歐幾里得平面幾何五大公理。最後一個公理就是平行公理:一條直線線外一點只能做出唯一平行直線

俄國數學家羅巴切夫斯基 (Lobachevsky) 一輩子想要其他公理證明平行公理或者用更直觀的公理取代平行公理都未能成功。後來用反證法:一條直線外一點一定會有兩條或兩條以上的平行直線,試圖找出矛盾。但卻發現邏輯自洽。因而開創非歐幾何學。我們現在知道這其實對應雙曲面幾何如下。這是一個馬鞍面,立起來就是一個雙曲面。雙曲面上的"直線“線外一點可以找到無數 diverged “直線”,和原來的“直線”永不相交,因此可以有無數條平行線。

黎曼則另闢蹊徑開拓黎曼幾何學。對應(橢圓)球面幾何。球面上所有的“直線”都是 中心在球心的封閉大圓。因此所有的“直線”都相交。平行公理變成一條直線外一點沒有任何平行直線。常見的誤區是球面的緯線是平行線。緯線除了赤道是“直線”,其他的緯線都是球面上的“曲線”,不能視為平行直線!

下圖很好的總結三種幾何學。

曲面幾何和曲率

曲面幾何可以定義曲率。曲率乍看之下是把一個曲面放在更高維空間(外)顯出的性質。

例如上圖是把二維的曲面放在(嵌入)三維的歐氏空間,可以明顯看出不同的曲面。同時可以定量的描述這個曲面的曲率。例如球面的曲率非常直觀和球的半徑相反。越小的球,曲率越大。但球面曲率是一個整體的性質,還是每一點(和其鄰近點)的性質?曲率是和半徑成反比,還是和半徑平方成反比?

先回顧二維歐氏平面上的一維曲線。很明顯曲線上每一點(和其鄰近點)都可以定義“線曲率” \kappa 是相切圓(不是拋物線!)半徑的倒數,i.e. \kappa = 1/r . 當然可以根據相切圓是在曲線的上方或是下方定義 \kappa 是正或是負。\kappa 明顯和泰勒展開的二階導數成正比1。直線的二階導數為 0, 曲率為 0.

再回到二維曲面,曲面上每一點都有無限條曲面上的曲線相交於這一點。每一條曲線都有本身的“線曲率”,可以是正或負。高斯曲率定義二維曲面每一點的“曲面曲率” R 是相交該點所有曲線(更正確應該是 geodesics)最大的線曲率乘最小的線曲率(含正負號), i.e. R = \kappa_1 \kappa_2 ; \kappa_1 是最大線曲率;\kappa_2 是最小線曲率。

以完美球面為例,每一點所有相交曲線的線曲率都一樣。都是大圓(圓心即是球心)半徑的倒數。所以球面每一點的高斯曲率 R = \kappa_1 \kappa_2 = 1/r^2 . 這符合直覺。

如果是非完美球面,例如橢圓球面半徑為 (a, b, c) , 曲面每一點的高斯曲率都不同,還是可以找到對應的 \kappa_1 \,, \kappa_2 . (完美或非完美)球面上同一點 \kappa_1 \,, \kappa_2 一定同正或同負,所以球面幾何每一點的高斯曲率永遠為正

再考慮雙曲面幾何。每一點相交曲線的”線曲率“必定有正有負,\kappa_1 > 0 \,, \kappa_2 < 0 . 所以雙曲面幾何每一點的高斯曲率永遠為負

外顯和內稟曲率

So far so good!
檢查高斯曲率在平面和圓柱面的曲率。平面是 trivial case, 所有 \kappa=0 . 圓柱面就很有意思,x,y 軸切面是圓形,半徑為 d; z 軸切面是(兩條)直線。帶入高斯曲率,\kappa_1 = 1/d \,,\, \kappa_2=0 , R = \kappa_1 \kappa_2 = 0 . 也就是圓柱面每一點的高斯曲率為 0, 和平面一模一樣!

顯然這不直觀。直觀上會認為圓柱面和平面不同,具有曲率,至少在 x,y 方向有曲率。為什麼高斯會定義高斯曲率為 \kappa_1 \kappa_2 而非 (\kappa_1 + \kappa_2)/2 ? (事實上,每一點的平均曲率定義為 mean curvature = (\kappa_1 + \kappa_2)/2 )。

圓柱面是一個很好的例子,說明外顯曲率和內稟曲率的不同

  • 外顯曲率(extrinsic curvature)就是把曲面放在更高維的歐氏空間,從更高維歐氏空間測量和定義的曲率。
  • 內稟曲率(intrinsic curvature)就是在(比嵌入歐氏空間低維)曲面本身測量和定義的曲率。更接地氣的說法,就是在曲面上的生物,可以測量和定義的曲率。
  • 舉例而言,上圖二維歐氏空間上的一維曲線,對於生活在曲線上一隻只會前進和後退(無限小)的蚯蚓,它能測量每一段曲線的長度,但是否能測量曲線上每一點的(內稟)曲率?直觀上顯然不能。唯一的機會是封閉曲線。如果蚯蚓往一個方向前進,最後回到同一點,代表這是一條曲線。假設曲線是圓形,甚至可以算出整條曲線的平均直徑,以及整條線平均曲率。實務上沒有用途:(1)大多數的曲線都是開放而非封閉曲線。(2)即使是封閉曲線,很少是圓形,算出平均半徑,或是平均曲率沒有意義。注意曲率是每一點局部的特性。除非是完美圓形或球形,一條曲線的平均曲率沒有太大意義。上文的 mean curvature 是每一點相交曲線的平均曲率,是有意義。
  • 簡單而言,一維曲線的“線曲率” \kappa 是嵌入在二維或是更高維歐氏空間,所以“線曲率”是外顯曲率。
  • 再看二維曲面,上文由“線曲率”所定義的高斯曲率 R = \kappa_1\kappa_2 或是 mean curvature = (\kappa_1+\kappa_2)/2 應該也是外顯曲率。NO!
  • 結果很意外。高斯曲率是內稟曲率,mean curvature 是外顯曲率。
  • 對於二維曲面上的一隻螞蟻,不用線曲率,它能測量每一點的曲率嗎?能!見下文。具體的方法是在每一點畫一個圓(或三角形),測量圓的圓周率(或是三角形內角和)。就可以得到該點的高斯曲率 R , 結果剛好等於最大和最小線曲率的乘積 R = \kappa_1\kappa_2 . 高斯自己似乎也覺得不可思議,稱為"絕妙定理“[@wikiTheoremaEgregium2019] 如下。
  • Gaussian curvature can be determined entirely by measuring angles, distances and their rates on a surface, without reference to the particular manner in which the surface is embedded in the ambient 3-dimensional Euclidean space. In other words, the Gaussian curvature of a surface does not change if one bends the surface without stretching it. Thus the Gaussian curvature is an intrinsic invariant of a surface.
  • 所以平面和圓柱面的高斯曲率是相同的。一隻曲面上的螞蟻無法分辨(locally)是一個平面或是圓柱面。因為圓柱面展開是一個平面。但是 mean curvature 兩者不同。因為 mean curvature 是外顯曲率。
  • 兩個曲面如果每一點高斯曲率相同,則為 isometric. 反之,無法 global isometric, 最多是 local isometric. 球面和平面無法等距 mapping. 只要看地圖就知道。赤道部分比例可以很準,但是兩極比例差很大。
  • 三維空間如何定義“內稟“曲率?因為很難直觀想像三維彎曲空間嵌入一個四維空間。三維彎曲空間包含三個 basis (x, y, z), 每一點(和鄰近點形成的空間)可以分解成 xy, yz, xz 三組曲面,各自有高斯曲率。所以曲率是一個三維 vector. Feymann lecture said there are 6 values to fully describe curvature.
  • 圓周率不是很好的曲面特徵,因為不是定值。Use N-dimension unit volume instead. S(r) = dV(r)/dr or dV(r) = S(r) dr (Gray and Vanhecke 1979).

曲面幾何的其他特徵

除了平行公理可以用來分類不同的曲面,是否有其他更直觀的特徵分類?
Yes! 可以用三角形內角和是否大於,等於,或小於 180^o \,(or \,\pi) 如下圖。

另外一個特徵是圓周率。在平面幾何任意圓的周長除以直徑永遠等於\pi .
但在曲面則會小於或大於\pi .

以上特徵(三角形內角和,圓周率)不只是定性的描述,都和高斯曲率有定量的關係。更重要的是這是曲面內稟的特性!就是在曲面的生物,就可以測量到高斯曲率。

下表總結三種幾何學:

Geometry Sphere 球面 Plane 平面/柱面 Hyperbolic 雙曲面
Creator Riemann Euclid Lobachevsky
平行公理平行線 0 1 \ge 2
三角內角和 >\pi \pi <\pi
圓周率 <\pi \pi >\pi
高斯曲率 > 0 0 < 0

上表的平行線,三角內角和,圓周率都是 global (全域) 特性。但是高斯曲率卻是 local (局部) 特性。如何連結 global and local?

  • 圓周率 Bertrand–Diguet–Puiseux theorem (Wifi 2019a). 是否有積分形式?
    K = \lim_{r\to0^+} 3  \frac{2\pi r - C(r)}{\pi r^3}  = \lim_{r\to0^+} 12 \frac{\pi r^2 - A(r)}{\pi r^4}

  • 三角形內角和 (Gauss-Bonnet theorem (Wiki 2019a)
    \sum_{i=1}^3 \theta_i = \pi + \iint K dA \quad\text{or}\quad K = \lim_{A\to0^+}\frac{\sum^3 \theta_i - \pi}{A}

  • A good article to integrate everything including Laplacian using unit volume (Gray and Vanhecke 1979).

  • 一個明顯的問題是平行公理是 global 的特性(直線永不相交),是否有直接對應局部曲率的公式? Yes,平行移動 parallel transport 就是平行的微分定義!! 和曲面微分幾何有非常深層的連結。

  • 反向問題:既然可以用三角內角和以及圓周率極限定義曲率,還需要用平行定義取率嗎? Absolutely Yes, 平行觀念和座標 grid line and local basis vector 定義吻合(local basis vector = grid line 的切線),可以直接融入純量場,向量場,張量場的微分運算。 相反三角內角和或圓周率基於極限的定義在各種微分幾何的運算並不實際。

(Keng 2018) 剛好和我想的一致,平行公理和 parallel transport.

Parallel Transport (平行移動) 的定義

(Wiki 2019a) 微分幾何對平行移動的定義:
平行移動是將流形上的幾何特性沿著光滑曲線移動的一種方法。如果流形上有一個 affine connnection(covariant derivative),那麼 affine connection 保證我們可以將流形上的向量沿著曲線移動使得它們關於這個 connection 保持「平行」。

在某種意義上說,關於 connection 的平行移動提供了將流形的局部幾何沿著曲線移動的方法:即「連接」了鄰近點的幾何。有許多種平行移動的概念,但其中一種方式等同於提供了一個 connection。事實上,通常的 connection 是平行移動的無窮小類比。反之,平行移動是 connection 的局部實現。

因為平行移動給出了 connection 的一種局部實現,它也提供了曲率的一種局部實現(holonomy)。Ambrose-Singer 定理明確了曲率與 holonomy 的關係。
\frac{D}{dx}\frac{D}{dy}V - \frac{D}{dy}\frac{D}{dx}V = R(\frac{\partial \sigma}{\partial x},\frac{\partial \sigma}{\partial y})V \quad\text{where R is curvature tensor}

簡言之,平行移動基本是一種 local connection, 以及實現 curvature 的方式。
問題是:平行移動和平行公理有什麼關係?

平行公理和 Parallel Transport 和 geodesic 三角形內角和

平行公理:一條直線和線外一點平行直線的關係。
什麼是直線?最直觀的定義就是最短路徑,在非平面的“直線”看起來並不直。
數學的表示是: \min \int ds . 使用變分法的 Euler-Lagrange equation 可以得到 Geodesics (測地線或地直線)。平面幾何的 geodesic 就是直線,推廣到微分幾何如下:

  • 一條 Geodesics (地直線)上所有點的切向量(以及和切線固定夾角的向量)都互相平行(如下圖三條地直線,都是球面上的大圓)。
  • Geodesic (地直線)線外一點和其最短距離的路徑也是 geodesic, 並且垂直夾角。
  • 其實是否直角不重要。如果不是直角但仍是 geodesic,parallel transport 就會轉該夾角。沿著同一條 geodesic 的 parallel transport 和 geodesic 的夾角不變。
  • How to prove? 如果 geodesic 構成的三角形內角和為 180, parallel transport 的夾角為 0. 大於 180, parallel transport 會產生正夾角。小於 180, parallel transport 產生負夾角。

平面和曲面幾何的 Parallel Transport (Holonomy)

平面幾何:平行移動先定義 Geodesic A, 接著線外一點 P, 可以找到一條 Geodesic B 垂直於 A at T. 再來根據平行公理,只有一條平行線 Geodesic C 平行於 A, 且垂直於 B. 因為 A 和 C 是平行線,永不相交。為了讓 parallel transport 形成封閉迴路 (holonomy), 可以在 A 上找一點 Q, 並且做垂直線到 C, 稱為 geodesic D.
此時從 A_P 的切線,一路到 A_Q 都是 parallel transport. 和 A_P 經由 B \to C \to D \to A_P 的 parallel transport vector 會是平行。也就是夾角為 0!這是一個 trivial case. 沿著長方形兩邊是切向量,兩邊是垂直向量的 holonomy, 在 close loop 的夾角為 0.

柱面幾何:直接剖面切開就是平面。parallel transport 和平面一樣。如果沿著三角形 holonomy, 因為內角和為 180, 回到起點的 parallel transport 夾角為 0. Gauss curvature 為 0.

錐面幾何:圓錐面如下圖(a)的曲率?圓錐面可以展開成平面缺角圓形如下圖(b). 除了 A 點之外任何點的曲率為 0. 因為錐面上一個 close loop, 如果不包含 A, parallel transport 夾角為 0. 因此曲率為 0.

如果包含 A 的圓,parallel transport 夾角 = \alpha , 面積 = (\pi-\alpha/2) a^2 , A 的曲率趨近無窮大。
R_A = \lim_{a\to 0}\frac{2\alpha}{a^2(2\pi-\alpha)}\to\infty

另一個問題,上圖球面非大圓 R 的 parallel transport 夾角? 常見的回答是 0. 錯誤的答案!正確的答案是用圓錐面和球面的切線為 R,再展開如上圖 b.

球面幾何:平行移動先定義 geodesic A (上圖左邊弧線), 赤道的 geodesic B 垂直於 A at T. 由平行定理我們知道球面幾何不存在和 A 平行(不相交)的 geodesic. 我們只能選擇和 B 垂直的 geodesic C, given we know A 和 C 會相交於 Q 點(其實在北極)。
此時從 A_T 的切線,一路到 A_Q 都是 parallel transport. 另一路是A_T 經由 B \to C \to A_Q 的 C 的切線(也是 parallel transport) 一定有一個夾角 \alpha . 球面幾何的三個內角和 =90+90+\alpha>180 . 這個夾角和 parallel transport 所包含的面積有關。
如果只是在局部做一個封閉迴路(holonomy),局部看起來就像歐氏空間。Parallel transport 的 holonomy 夾角為 0. Use Gauss curvature
R = angle / area \quad \text{where}\quad area = 4\pi r^2 /2 * \alpha /{2 \pi} = {\alpha r^2}
R= \frac{1}{r^2} \quad \text{independent of }\alpha

雙曲線幾何:直接考慮鞍面的三角形,內角和小於 180. parallel transport 為負夾角。

平行移動的數學表示

Parallel Transport \vec{V} 沿著一條線(不需要直線 or geodesic) \vec{r}(\lambda) 的局部變化為 \vec{0} , \lambda 是參數 normalized to 弧長,所以和座標系無關。

Parallel transport 更數學而且和座標系無關的定義:\vec{V} \vec{r}(\lambda) 切線 \vec{u} 的方向導數(微分)為 \vec{0} . (注意向量場的所有 basis 方向的導數是張量,某個特定方向, \vec{u} , 的導數是向量,也就是“affine connection". 在曲面空間稱為 Levi-Civita connection.)

\nabla_{\vec{u}} \vec{V} = \vec{u}\cdot\nabla\vec{V} = \vec{0} \quad \text{where}\quad \vec{u} = \frac{d\vec{r}}{d\lambda}

一個類比:如果不是一個向量 \vec{V} , 而是一個純量 \phi 滿足下式。(注意純量場的所有 basis 方向的導數是向量,稱為梯度 gradient. 某個特定方向, \vec{u} , 的導數是純量。)\vec{r} 就是等高線或等位線。

\nabla_{\vec{u}} \phi = \vec{u}\cdot\nabla\phi = 0 \quad \text{where}\quad \vec{u} = \frac{d\vec{r}}{d\lambda}

平行移動和等高線的數學公式雖然非常類似。問題的形式 (formulation) 卻不同。
平行移動是給定一條任意線 \vec{r}(\lambda) (open or close) 以及一點 P 的 vector \vec{V}(P) , 用 (1) 找出沿線所有點平行移動的 \vec{V} .
等高線是給定一個純量場 \phi 以及任一點 P , 用 (2) 找出通過 P 的等位線 \vec{r}(\lambda) (open or close).

張量分析用於幾何

張量(tensor) 最重要的特性就是座標系無關,可用於平面或曲面。張量分為三類:

  1. Basis vector invariant: 純量 也就是 0 階張量。
  2. Basis vector contra-variant. 為什麼 contra-variant? 因為 basis vector scale up, 張量分量會 scale down. 一階張量是 vector (n維), 二階張量 (nxn維), 三階張量(nxnxn維),依此類推。e.g. Einstein curvature tensor 是四階張量(4x4x4x4)維。 Ricci curvature tensor 是二階張量 (4×4)維。
  3. Basis vector co-variant. 也稱為 one-form. 像是 gradient, \nabla , basis vector scale up, dual basis vector scale down, 張量分量也會 scale up. 其他特性和一般張量一樣。

其他的張量運算下面展開。

先用歐氏空間的方向導數為例:

在卡氏座標系(笛卡爾直角座標系):\{\mathbf{e_1,\,e_2}\} , global constant orthonormal basis vectors.
曲線和切向量:
\vec{u} = \frac{d\vec{r}}{d\lambda} = u_1\mathbf{e_1} + u_2\mathbf{e_2}

注意:千萬不要用 [u_1, u_2] 表示法,只有在卡氏座標系可用。對於非直角或非歐氏空間一定要如上公式帶上 local basis vectors!!

先考慮 gradient operator, \nabla . 在卡氏座標系:

\nabla = \frac{\partial}{\partial e_1} \mathbf{e_1} +  \frac{\partial}{\partial e_2} \mathbf{e_2}

一個純量場(0階張量)的梯度, \nabla \phi , 是一個向量。更準確的說是一個一階張量
一個一維量場的梯度, \nabla \vec{V} , 是一個二階張量。以此類推。

純量場的方向導數,基本上是純量場的梯度 (gradient) 和方向向量的內積。

\nabla_{\vec{u}}\phi = \vec{u}\cdot\nabla\phi = (u_1\mathbf{e_1} + u_2\mathbf{e_2}) \cdot (\frac{\partial \phi}{\partial e_1}\mathbf{e_1}+\frac{\partial \phi}{\partial e_2}\mathbf{e_2})\\ = u_1 \frac{\partial \phi}{\partial e_1} + u_2 \frac{\partial \phi}{\partial e_2} \quad\text{where}\quad\mathbf{e_i}\cdot \mathbf{e_j}=\delta_{ij} \quad(1)\,\text{!wrong for non-Euclidean!}

\nabla_{\vec{u}}\phi =  \vec{u}\cdot\nabla\phi = 0 代表 \vec{u} 和梯度 \nabla \phi 垂直。因此 \vec{u} 形成 \phi 的等位線。

(1) 只能用於卡氏座標系。接下來幾個重點:1.座標系無關;2.推廣到曲面;3.簡化公式
現在引入 covariant/contravariant basis and tensor, 和愛因斯坦 summation notation.

Basis vectors \{\mathbf{e_1,\,e_2}\} , 配合 contra-variant 分量。
Dual basis vectors \{\mathbf{e^1,\,e^2}\} , 配合 co-variant 分量。

\mathbf{e_i}\cdot\mathbf{e^j}=\mathbf{e^i}\cdot\mathbf{e_j}=\delta_i^j=\delta_j^i \qquad(2)

注意 \mathbf{e_i}\cdot \mathbf{e_j}\ne\delta_{ij} , 有兩個原因。如果 \mathbf{e_i} 放大兩倍,\mathbf{e_i}\cdot \mathbf{e_i}=4 , 就是座標系無法 scale. 另外非直角座標系,\mathbf{e_1}\cdot \mathbf{e_2}\ne 0 , 就是座標系無法非直角。正確的結論如下,可以用於非歐非直角座標系。g_{ij} 是二階張量 (metric tensor) 的分量。
\mathbf{e_i}\cdot\mathbf{e_j}=g_{ij} \qquad \mathbf{e^i}\cdot\mathbf{e^j}=g^{ij} \qquad(3)

對於歐氏空間非直角座標系,(1) 可以修改為:
\nabla_{\vec{u}}\phi = \vec{u}\cdot\nabla\phi = (u^1\mathbf{e_1} + u^2\mathbf{e_2}) \cdot (\frac{\partial \phi}{\partial e_1}\mathbf{e^1}+\frac{\partial \phi}{\partial e_2}\mathbf{e^2})\\ = u^1 \frac{\partial \phi}{\partial e_1} + u^2 \frac{\partial \phi}{\partial e_2} =  \quad\text{where}\quad\mathbf{e^i}\cdot \mathbf{e_j}=\delta^i_j \qquad(4)

使用愛因斯坦 notation 重寫 (4)
\nabla_{\vec{u}}\phi = \vec{u}\cdot\nabla\phi = u^i\mathbf{e_i} \cdot\partial_j \phi \mathbf{e^j} = u^i \partial_i \phi\qquad(5)

曲面空間的方向導數:

曲面空間的純量場方向導數和 (5) 完全相同。因為純量場是 basis invariant.

但是曲面空間的向量場是 basis covariant or contravariant, 所以曲面的向量場的方向導數會比歐氏空間複雜的多。

曲面空間向量場 \vec{V} 的方向 \vec{u} 導數

  • 似乎可視每個分量為純量場,求每個純量場的方向導數。Wrong! 原因是 basis vector 在非歐空間不是 constant vector, 甚至歐氏空間的極座標也不是 constant vector. 因此 basis vector 的微分會產生新的 component! (Christopher symbol, or connection).
  • 向量場的梯度是二階張量,直接求梯度太複雜。比較好的作法是分解方向導數的“方向向量”為 basis vector linear combination, 最後再結合為真正方向導數。

$latex \vec{V} = V^1 \mathbf{e_1} + V^2 \mathbf{e_2}
= V^{\alpha} \mathbf{e_\alpha} \\
\vec{u} = u^1 \mathbf{e_1} + u^2 \mathbf{e_2} $

$latex \nabla_{\vec{u}}\vec{V} = \vec{u}\cdot\nabla\vec{V}
= (u^1 \mathbf{e_1} + u^2 \mathbf{e_2})\cdot\nabla\vec{V} \\
\nabla_{e_\beta}\vec{V}=\mathbf{e_\beta} \cdot\nabla\vec{V}
= \mathbf{e_\beta} \cdot\nabla (V^\alpha \mathbf{e_\alpha})
= \mathbf{e_\beta} \cdot \frac{\partial(V^\alpha \mathbf{e_\alpha})}{\partial e_i} \mathbf{e^i} \\
= \frac{\partial(V^\alpha \mathbf{e_\alpha})}{\partial e_\beta}
= \frac{\partial V^\alpha}{\partial e_\beta}\mathbf{e_\alpha} +
V^\alpha \frac{\partial \mathbf{e_\alpha}}{\partial e_\beta}
= \frac{\partial V^\alpha}{\partial e_\beta}\mathbf{e_\alpha} +
V^\alpha \Gamma^k_{\alpha\beta}\mathbf{e_k} \\
= \frac{\partial V^\alpha}{\partial e_\beta}\mathbf{e_\alpha} +
V^i \Gamma^{\alpha}_{i\beta}\mathbf{e_\alpha}
= (\frac{\partial V^\alpha}{\partial e_\beta} +
V^i \Gamma^{\alpha}_{i\beta})\mathbf{e_\alpha} $

此處利用 Christopher symbol 以及 \alpha\to i \,,\, k\to\alpha
$latex \frac{\partial \mathbf{e_\alpha}}{\partial e_\beta} =
\Gamma^k_{\alpha\beta}\mathbf{e_k} $
如果是歐氏空間且直角座標系,Christopher symbol \Gamma^a_{bc}=0
如果是歐氏空間但極座標系,因為每一點的 local basis vector 方向都不同,Christopher symbol 不為 0, 一共有 2x2x2=8 個 components [@cyrilChristoffelSymbol2016].

\Gamma_{i j}^{r}=\left(\begin{array}{cc}{\Gamma^r_{\theta\theta}=-r} & {0} \\ {0} & {0}\end{array}\right) \qquad \Gamma_{i j}^{\theta}=\left(\begin{array}{cc}{0} & {\frac{1}{r}} \\ {\frac{1}{r}} & {0}\end{array}\right)

愛因斯坦 notation and convention: 向量場的梯度微分是二階張量(樓上加樓下)。
\nabla_{e_\beta}\vec{V}= \nabla_\beta V^\alpha  = \partial_\beta V^\alpha+\Gamma^{\alpha}_{i\beta} V^i = \partial_\mu V^\nu+\Gamma^{\nu}_{\lambda\mu} V^\lambda

最後 $latex \nabla_{\vec{u}}\vec{V} = \vec{u}\cdot\nabla\vec{V}
= (u^1 \mathbf{e_1} + u^2 \mathbf{e_2})\cdot\nabla\vec{V}\\
= u^\beta (\frac{\partial V^\alpha}{\partial e_\beta} +
V^i \Gamma^{\alpha}_{i\beta})\mathbf{e_\alpha}
= (u^i \frac{\partial V^k}{\partial e_i} +
u^i V^j \Gamma^{k}_{ij})\mathbf{e_k}
= (u^i {\partial_i V^k} +
u^i V^j \Gamma^{k}_{ij})\mathbf{e_k} $

愛因斯坦 notation and convention: 向量場的方向導數是一階張量(樓上)。
\nabla_{\vec{u}}\vec{V} = u^i {\partial_i V^k} + u^i V^j \Gamma^{k}_{ij}

整理愛因斯坦 notation 的原則:

  • \vec{u}=u^i\mathbf{e_i}=u^i , 只有一個樓上 index,代表一階張量 contra-variant.
  • \nabla\phi = \partial_i \phi \mathbf{e^i} = \partial_i \phi , 只有一個樓下 index,代表一階張量 co-variant (one-form).
  • \vec{u}\cdot\nabla\phi = u^i \partial_i \phi , 張量和 1-form 張量內積結合,同一個 index i 樓上樓下抵銷,變成 0 階張量(純量)。
  • 張量微分(gradient) 階數+1\nabla (0 階張量)得到一階 one form 張量;\nabla (一階張量)得到二階張量;以此類推。\nabla_\beta V^\alpha  = \partial_\mu V^\nu+\Gamma^{\nu}_{\lambda\mu} V^\lambda 是二階(樓上加樓下)tensor.
  • 張量和 one-form 張量內積 階數-1,index 樓上樓下抵銷。
  • 張量場的方向導數是先微分張量(+1)場再和方向向量內積(-1),階數不變,e.g. 純量場方向導數是純量。向量場的方向導數是一階張量:\nabla_{\vec{u}}\vec{V} = u^i {\partial_i V^k} + u^i V^j \Gamma^{k}_{ij} 是一階(樓上) 張量。
  • 因為張量場的方向導數階數不變。因此可以重覆這個運算。最常見是二次方向導數(沿不同的方向,如 basis vectors)。除了在平面歐氏座標系以外,一般是不能交換。\nabla_{\vec{w}}\nabla_{\vec{u}}\vec{V} \ne \nabla_{\vec{u}}\nabla_{\vec{w}}\vec{V} . 事實上,\nabla_{\vec{w}}\nabla_{\vec{u}}\vec{V} - \nabla_{\vec{u}}\nabla_{\vec{w}}\vec{V} = R\vec{V} ? (TBC)

回到曲線的方向導數=絕對導數(Absolute Derivative:等高線,地直線,平行移動)

曲線和切向量回顧:
\vec{u} = \frac{d\vec{r}}{d\lambda} = u_1\mathbf{e_1} + u_2\mathbf{e_2}
純量場的線方向導數
\nabla_{\vec{u}}\phi(\vec{r}) = \frac{d\vec{r}}{d\lambda}\cdot\nabla\phi(\vec{r}) = \frac{d\phi(\vec{r})}{d\lambda}

其實這就是著名的 gradient theorem, 或是線積分基本定理推廣到曲面。重點是曲面線積分是路徑無關!或是封閉迴路線積分為 0. 但在向量場不是如此。
$latex \int_p^q \nabla_{\vec{u}}\phi(\vec{r}) d\lambda
= \int_p^q \nabla\phi(\vec{r})\cdot d\vec{r} = \phi(q) – \phi(p) $

以純量場為例

Let \phi(\vec{r}) = |\vec{r}|^2 座標系無關:
射線運動卡氏座標系:
\phi = x^2 + y^2 and \nabla \phi = 2x \mathbf{e_x} + 2y \mathbf{e_y}
\vec{r} = c_0\lambda\mathbf{e_x} + c_1\lambda\mathbf{e_y} , where c_0^2+c_1^2=1
\frac{d\vec{r}}{d\lambda} = c_0\mathbf{e_x} + c_1\mathbf{e_y}

\nabla_{\vec{u}}\phi(\vec{r}) = \frac{d\vec{r}}{d\lambda}\cdot\nabla\phi(\vec{r}) = 2x c_0 + 2y c_1= 2\lambda c_0^2 + 2\lambda c_1^2 = 2\lambda

\phi(\vec{r}) = \phi(\lambda) = c_0^2 \lambda^2 + c_1^2 \lambda^2 = \lambda^2
\frac{d\phi(\vec{r})}{d\lambda} = 2\lambda

射線運動極座標系:
\phi = r^2 and \nabla \phi = 2r \mathbf{e_r}
\vec{r}= \lambda \mathbf{e^r} + \theta_o \mathbf{e^\theta}
\frac{d\vec{r}}{d\lambda} = \mathbf{e_r}

\nabla_{\vec{u}}\phi(\vec{r}) = \frac{d\vec{r}}{d\lambda}\cdot\nabla\phi(\vec{r}) = 2r = 2\lambda

\phi(\vec{r}) = \phi(\lambda) = \lambda^2
\frac{d\phi(\vec{r})}{d\lambda} = 2\lambda

以向量場為例

向量場的線方向導數,稱為絕對導數(absolute derivative)
$latex \nabla_{\vec{u}}\vec{V}(\vec{r}) = \frac{d\vec{r}}{d\lambda}\cdot\nabla\vec{V}(\vec{r}) \\
= u^i {\partial_i V^k} + u^i V^j \Gamma^{k}_{ij}
= \frac{d V^k}{d\lambda} + \frac{d x^i}{d\lambda} V^j \Gamma^{k}_{ij} $

Parallel transport

\vec{u} = \frac{d\vec{r}}{d\lambda} or u^k = \frac{dx^k}{d\lambda} , parallel transport 就是向量場 \vec{V} 沿 \vec{r} 方向導數為 \vec{0} ,上式變成:
\frac{d V^k}{d\lambda} + \frac{dx^i}{d\lambda} V^j \Gamma^{k}_{ij}=0

積分形式: V^k(q) - V^k(p) = -\int_p^q V^j\Gamma^{k}_{ij}{dx^i} . 注意 p 點和 q 點的 basis vectors 不一定相同。即使 V^k(p) \ne V^k(q) 也不代表 \vec{V}(p) \ne \vec{V}(q) . 下面極坐標例子可以看出。
另一個重點是 V^k(q) 有很多 dx^i 可以到達,結果不一定相等!(path dependent)

卡氏座標系:\Gamma=0 , V^k = c^k , constant as expected.
極座標系:k =\{r \,, \theta \} ; ds^2 = dr^2 + r^2 d\theta^2 .

|\mathbf{e^r}| = \frac{\partial s}{\partial r} =1
|\mathbf{e^\theta}| = \frac{\partial s}{\partial \theta} =r

\vec{x} = x^r \mathbf{e^r} + x^\theta \mathbf{e^{\theta}}
\frac{d V^r}{d\lambda} + \frac{dx^i}{d\lambda} V^j \Gamma^{r}_{ij} = \frac{d V^r}{d\lambda}-\frac{dx^\theta}{d\lambda}V^\theta x^r= 0

\frac{d V^\theta}{d\lambda} + \frac{dx^i}{d\lambda} V^j \Gamma^{\theta}_{ij} = \frac{d V^\theta}{d\lambda} + \frac{dx^r}{d\lambda} \frac{V^\theta}{x^r} + \frac{dx^\theta}{d\lambda} \frac{V^r}{x^r} = 0

Example 1: 射線運動 (起點在r=1上)
Let x^r = \lambda+1\,,\, x^\theta = c . \vec{V}(\lambda=0) = r_o \mathbf{e^r} + \theta_o \mathbf{e^\theta}
\frac{d V^r}{d\lambda} = 0

\frac{d V^\theta}{d\lambda} + \frac{V^\theta}{\lambda+1} = 0

V^r = r_o \,,\, V^\theta = \frac{\theta_0}{\lambda+1} = \frac{\theta_0}{x^r} \text{ Yes, scale down the basis vector } e^\theta

Example 2: 圓周運動
Let x^r = 1\,,\, x^\theta = \lambda . 弧長等於夾角! \vec{V}(\lambda=0) = r_o \mathbf{e^r}
\frac{d V^r}{d\lambda}-V^\theta = 0

\frac{d V^\theta}{d\lambda} + V^r = 0

V^r = r_o\cos\lambda \,,\, V^\theta = -r_o\sin\lambda as expected below.

平行移動和曲率的關係

Geodesics 是 parallel transport 的特例

\vec{V} = \vec{u} = \frac{d\vec{r}}{d\lambda} or V^k = u^k = \frac{dx^k}{d\lambda} , 上式變成:
\nabla_{\vec{u}}\vec{u}(\vec{r}) = 0

\frac{d^2 x^k}{d\lambda^2} + \Gamma^{k}_{ij}\frac{dx^i}{d\lambda} \frac{dx^j}{d\lambda}=0

Reference

Gray, A., and L. Vanhecke. 1979. “Riemannian Geometry as Determined by
the Volumes of Small Geodesic Balls.” Acta Mathematica 142: 157–98.
https://doi.org/10.1007/BF02395060.

Keng, Brian. 2018. “Hyperbolic Geometry and Poincaré Embeddings.”
Bounded Rationality. June 17, 2018.
http://bjlkeng.github.io/posts/hyperbolic-geometry-and-poincare-embeddings/.

Wiki. 2019a. “Gaussian Curvature.” Wikipedia.
https://en.wikipedia.org/w/index.php?title=Gaussian_curvature&oldid=910677726.

———. 2019b. “Parallel Transport.” Wikipedia.
https://en.wikipedia.org/w/index.php?title=Parallel_transport&oldid=911069387.

———. 2019c. “Theorema Egregium.” Wikipedia.
https://en.wikipedia.org/w/index.php?title=Theorema_Egregium&oldid=895212511.


  1. \kappa = \frac{y''}{(1+y'^2)^{3/2}}  

相對論和張量分析 – Coordinate Covariant, Contravariant, Invariant (座標系協變,逆變,不變)

by allenlu2007

黎曼微分幾何是廣義相對論的數學基礎。張量分析是黎曼微分幾何的必備數學工具。

  • 黎曼幾何是彎曲幾何(curved geometry),不同於歐式平直幾何(straight geometry)。
  • 黎曼幾何研究內稟(intrinsic)的特性以及嵌入(embedded)歐式幾何的特性。例如 2D Swiss Roll 的內稟幾何特性和一張平紙無異 (i.e. intrinsic curvature = 0), 但是 embedded 在高維(3D)歐式空間卻有曲率。

由於相對論的影響,不同(運動)觀察者所量測的物理定律 (e.g. least action principle) 都要一樣。這剛好對應幾何不同座標系“不變性”。不變的 scalar 可以使用 invariant. 不變的 vector/tensor, 因為分量仍然和座標系相關,我們用 covariant 表述。

觀察者和座標系容易混淆的重點:

  1. 不同(運動)觀察者對應幾何不同座標系. 不要執著一個是動態,一個是靜態。這裏所說的幾何座標系都包含時間軸 (t -axis), 從下到上代表過去到未來。任何運動都可以用一條靜態的世界線(worldline) 表示。

  2. 一條 wordline 是相對於一個觀察者(座標系)。例如 A 觀察到一個靜止物體 S,在 A 的(直角)座標系 S 的位置就是一條垂直的 world line. B 是一個相對 A 定速 v 移動的觀察者。B 要如何得到 S 的 world line?

    有兩個方法:

    (i) B 創造自己的(直角)座標系以及 S 的 world line. 顯然在 B 的直角座標系 S world line 是一條斜線。斜率是 -v (assuming v \ll c ). 兩個不同的直角座標系 for S 運動,對應 A 和 B 觀察者 (observer oriented)。這不是我們所要的。如果有無窮多觀察者(等速或等加速觀察者)就需要無窮多直角座標系以及無窮多的 world lines for the same S 的運動。
    我們關心 S 的運動 (object oriented) 一次看到 A 和 B 座標系的詮釋,見 (ii). 這對廣義相對論研究時空內稟幾何特性很重要。

    (ii) 在 A 的直角座標系 (grid line) 重劃 B 的(非直角)座標系 (grid line)。同一條垂直的 world line, 在 A 座標系 grid line 是靜止;但在 B 座標系 grid line 則是運動。

  3. 下圖是一個例子。A 觀察者是直角座標系 (x, t) , 網格線 (grid line) 是正方形。但對 B 觀察者(相對速度為 v )對應座標系 (x', t') , 網格線是平行四邊形。此處是用 Lorentz 變換,所以 t'=0,1,2 格線是斜線。如果是 Galilean 變換t'=0,1,2 會是水平線。對於 A 的靜止物體 S, 其 world line 就是 x=0 垂直線。對 B 座標系 (x',t') 而言,x=0 垂直線 world line 對應一個後退的運動。

  4. 注意這種重劃座標系網格並不限於相對速度固定的觀察者。原則上適用任何運動觀察者。假設觀察者 C 是相對于 A 有固定等加速度。也可以定義 (x'', t'') 網格線。下圖是 Lorentz 變換 C 的座標系。 x''=const 變成雙曲線。t''=const 變成聚集在 x''=-1 的投射線 (假設光速=1). 網格線變成更奇怪的四邊形。注意在 Lorentz transform 所有速度無法超越光速。觀察者 C 無法持續加速超越光速。 Galilean 變換 C 的座標系則不同。x''=const 變成拋物線。t''=const 還是水平線。

回到物理和幾何的對照:

  • 運動的物體 \iff 幾何的一條世界線 C (不是面或其他形狀)
  • 不同慣性運動或是非慣性運動觀察者 \iff 幾何的不同座標系以及網格
  • 狹義相對論:物理定律在不同慣性座標系不變 (scalar:invariant; vector/tensor:covariant)
  • 廣義相對論:物理定律考慮等效原理在不同座標系不變
  • 物理定律 \iff 幾何不變量 (如何對應 scalar: invariant; tensor: covariant)

    • 微分幾何的 1st fundmental form ds^2 = c^2 dt^2-dx^2-dy^2-dz^2 = c^2 dt'^2-dx'^2-dy'^2-dz'^2 幾何量是微分弧長 coordinate invariant 對應物理的 Lorentz transform. 如果少了 c^2 dt^2 就是 (-1)*Galilean transform.

    • 注意微分幾何的 1st fundamental form 可以推廣到 curved space or coordinate. 這裏使用愛因斯坦 summation notation. ds^2 = g_{\alpha\beta}{dx^\alpha}{dx^\beta}

    • 牛頓第二定律: \vec{F} = m\vec{a} \, 在 Galilean transform 不變。因為是 vector, vector components 在不同座標系不同,稱為 covariant. 對應的幾何不變量是“curvature vector". 但在 Lorentz transform, \vec{F} \,and\, \vec{a} 甚至不是 4-vector/tensor, 連 covariant 也不是。如何得到符合 Lorentz tranform 4-vector/tensor 的力學定律呢?下面描述。

    • 最小作用力原理 (Least action principle) 是比牛頓運動定律更基本的定理。分析力學首先找到 Lagrangian L (單位是能量),differential action dS = L dt (單位是能量*時間,大自然兩者都要省)。Total action 就是空間兩點 (p_1, p_2) 和時間兩點 (t_1, t_2) 路徑積分。最小作用原理用變分法找到最小 S 的路徑。 S = \int_{t_1}^{t_2} L dt

    • 舉一個例子:古典力學 Lagrangian of free particle (no potential field) in Cartesian and polar coordinate. [@ActionPhysics2019]

      $latex L =\frac{1}{2} m v^2=\frac{1}{2} m (\dot{x}^2 + \dot{y}^2)
      \quad L =\frac{1}{2} m (\dot{r}^2 + r^2 \dot{\varphi}^2) $

    • 最小作用原理推廣到 4D 時空 for two events (x_1, x_2, x_3, x_4) and (x'_1, x'_2, x'_3, x'_4) . 因為時間 t 已經變成 x_1 , 需要用 dummy variable \lambda . 上述的 S 公式完全適用。

    • 但在相對論力學 4D 時空的 Lagrangian of free particle (no potential field). [@RelativisticLagrangian2019] L = -\frac{m_o c^2}{c} \sqrt{g_{\alpha\beta}\frac{dx^\alpha} {d\lambda}\frac{dx^\beta}{d\lambda}} = -\frac{m_o c^2}{c} \frac{ds}{d\lambda} \\ \approx m_o c^2 + \frac{1}{2} m_o v^2! \quad \text{assuming } v \ll c g_{\alpha\beta} 沒有單位。根號的單位是速度,和光速 c 單位抵銷。m_o c^2 的單位是能量。所以 L 的單位在 4D 時空仍然是能量。\lambda 只是 dummy variable (時間單位)。ds 是 1st fundmental form 的根號,或是微分弧長。滿足 Lorentz transform invariant. In a word, L 對應幾何量是弧速。 S = \int L d\lambda = \int -\frac{m_o c^2}{c} \sqrt{g_{\alpha\beta}\frac{dx^\alpha} {d\lambda}\frac{dx^\beta}{d\lambda}} d\lambda  重點是 S (action) 對應的是 4D 時空兩點之間的總弧長 (with a proportional constant). 最小作用原理對應幾何量是兩點之間最短距離的弧線,稱為 geodesic (測地線或地直線) which is coordinate invariant. [@cyrilGeodesicEquation2018] 也就是說,不同慣性運動的觀察者的最小作用原理都是一樣。但如何推廣到非慣性觀察者?

UTM. 2018. “Proper Time, Coordinate Systems, Lorentz Transformations | Internet Encyclopedia of Philosophy.” 2018. https://www.iep.utm.edu/proper-t/.

Coordinate Invariant, Covariant, Contravariant

Coordinate invariant 基本是 scalar quantity or field, 例如 ds , geodesic, scalar curvature, etc.

Contravariance 基本是 vector/tensor, 例如 curvature tensor, …. 什麼是 contravariant? (A^x e_x) base vector (e_x) 變大,component (A^x) 變小。所以是 contra-variance.

Covariance 也是 vector/tensor, 為什麼是 covariance? 一個例子是 gradient of scalar field. (\frac{\partial f}{\partial x} e^x, \frac{\partial f}{\partial y} e^y, \frac{\partial f}{\partial z} e^z) , base vector e^x 越大, component 也越大。

Covariance and Contra-variance of Vector/Tensor

歐式空間(或是 tangent space on manifold)

如何在座標系表達一個向量 \vec{v} ?
選擇一組 basis vectors (假設不正交). 然後分解成 basis vectors 的平行分量 (下圖右 typo v_x \to v^x \,\,and\,\, v_y \to v^y )。
\vec{v} = v^x \mathbf{e_x}+v^y \mathbf{e_y}
我們稱 v^x and v^y contra-variance, 因為 v^x \,,v^y \mathbf{e_x} \,,\mathbf{e_y} 反比的關係。
問題是如何用數學式計算 v^x and v^y ? (見下文)
如果是在直角座標系如下,可以看出 contra-variant!

v^x = \frac{\vec{v} \cdot e_x}{\lVert\mathbf{e_x}\rVert^2} \quad  v^y = \frac{\vec{v} \cdot e_y}{\lVert\mathbf{e_y}\rVert^2}

顯然在非直角座標系是錯的!正確的數學表述在後面。

此時稱 \mathbf{e_x} \,,\mathbf{e_y} (tangent) basis vectors 可以使用 Einstein summation notation:
\vec{v} = v^x \mathbf{e_x}+v^y \mathbf{e_y}= v^i \mathbf{e_i}\quad \text{or } v^i \text{ in short}

下一個問題,是否還有其他方法表示一個向量?Yes!
我們可以用垂直投影分量表示一個向量 (下圖左, v_x = \vec{v} \cdot e_x \,\, v_y = \vec{v} \cdot e_y ).
我們稱 v_x and v_y covariance, 因為 v_x \,,v_y \mathbf{e_x} \,,\mathbf{e_y} 正比的關係。
\vec{v} = v_x \mathbf{e^x}+v_y \mathbf{e^y}= v_i \mathbf{e^i} \quad \text{or } v_i \text{ in short}

問題是如何找到對應的 (cotangent) basis vector e^x and e^y ?

為了滿足 v_x = \vec{v} \cdot e_x v_y = \vec{v} \cdot e_y ,可以得出 e^i e_j = \delta^i_j !
也就是說 e^x \perp e_y \,, e^y \perp e_x . 同時 normalize e^x e_x = e^y e_y = 1 . 也就是反矩陣關係!

注意 e^x \nparallel e_x \,, e^y \nparallel e_y 除非 e_x \,, e_y 是直角座標系。

此時可以用新的 (cotangent) basis vector 表示:
\vec{v} = v_x \mathbf{e^x}+v_y \mathbf{e^y}= v_i \mathbf{e^i} = v^i \mathbf{e_i}

v_x = \vec{v} \cdot e_x \quad v_y = \vec{v} \cdot e_y \quad or \quad v_i = \vec{v} \cdot e_i

v^x = \vec{v} \cdot e^x \quad v^y = \vec{v} \cdot e^y \quad or \quad v^i = \vec{v} \cdot e^i

因為 e^i e_i 是反比。e_i 越大,e^i 越小,v^i 就愈小,稱為 contra-variance. 但是 v_i 卻是愈大,和 e_i 正比,稱為 covariance.

Inner Product Using Einstein Notation
\vec{u} \cdot \vec{v} = u^i \mathbf{e_i} v_j \mathbf{e^j} = u^i v_j \delta^i_j = u^i v_i = u_i v^i \\ = u^i \mathbf{e_i} v^j \mathbf{e_j} = u^i v^j g_{ij} = u_i v_j g^{ij}

Scalar field is invariant.
Vector/tensor field is contravariant.
Gradient of scalar field is a vector field, which is co-variant.

https://www.quora.com/What-are-%E2%80%9Ccovariant%E2%80%9D-and-%E2%80%9Ccontravariant%E2%80%9D-vectors-as-intuitive-representations

為了直觀了解 curved coordinate and space, 用以下的順序理解:直角座標系\to 斜角座標系 \to 歐式空間極座標系 (curved coordinate) \to 球面座標系 (curved space)

  1. orthonormal 座標系
    e^1 = (1, 0) \,\,  e^2= (0, 1)
    e_1 = (1, 0) \,\,  e_2= (0, 1)

  2. scaled 座標系
    e^1 = (a, 0) \,\,  e^2= (0, b)
    e_1 = (\frac{1}{a}, 0) \,\,  e_2= (0, \frac{1}{b})

  3. Non-orthogonal 座標系
    e^1 = (a, 0) \,\,  e^2= (d, b)
    e_1 = (\frac{1}{a}, \frac{-d}{ab}) \,\,  e_2= (0, \frac{1}{b})

  4. Polar 座標系 (r,\theta) \to (dr, r d\theta)
    e^1 = (a, 0) \,\,  e^2= (0, b)
    e_1 = (\frac{1}{a}, 0) \,\,  e_2= (0, \frac{1}{b})

三維空間
推廣上述二維的垂直觀念到三維空間。
e^1 的方向是由 e_2 \,, e_3 所形成平面的法線 (normal) 決定,i.e. e^1 e_2 = e^1 e_3 = 0 .

e^1 的大小是由 e_1 決定,i.e. e^1 e_1 = 1

同理 e^i 的方向是是由 e_j \,, e_k 所形成平面的法線 (normal) 決定。e^i e_j = \delta^i_j

推廣到 n 維空間:
Tangent basis: e1, e2, …, en, C(n,1)=n
Reciprocal basis: e1.,… C(n, n-1) = n

Curved Space or Coordinate System
Basis Vector (e_1, e_2, ...)
Reciprocal Basis Vector (e^1, e^2, ...)
e_i e_j = g_{ij} metric tensor g matrix
e^i e^j = g^{ij} inverse metric tensor, 真的是 inverse g matrix.
e^i = g^{ij} e_j \quad\quad e^i e_k = g^{ij}e_j e_k = g^{ij}g_{jk} = \delta^i_j

Covariant Derivative of Scalar Field and Vector Field

Covariant derivative 是 directional derivative 的推廣。同樣用以下的順序理解:直角座標系\to 斜角座標系 \to 歐式空間極座標系 (curved coordinate) \to 球面座標系 (curved space)

  1. Scalar field: f(x, y) on orthonormal 座標系
    e^1 = (1, 0) \,\,  e^2= (0, 1)
    e_1 = (1, 0) \,\,  e_2= (0, 1)
    \nabla f = \frac{\partial f}{\partial x} e^x + \frac{\partial f}{\partial y} e^y

  2. Scalar field: f(x, y) on scaled 座標系
    e^1 = (a, 0) \,\,  e^2= (0, b)
    e_1 = (\frac{1}{a}, 0) \,\,  e_2= (0, \frac{1}{b})
    \nabla f = \frac{\partial f}{\partial x} e^x + \frac{\partial f}{\partial y} e^y

  3. Scalar field: f(r, \theta) on 極座標系
    e_i\cdot e_j = g_{ij} , e^i\cdot e^j = g^{ij} , e_i\cdot e^j = \delta_{ij} .
    e_i = g_{ij} e^j , e^i = g^{ij} e_j
    ds^2 = dr^2 + r^2 d\theta^2 = g_{ij}dx^idx^j
    g_{ij}=\left(\begin{array}{cc}{g_{rr}=1} & {g_{r\theta}=0} \\ {g_{\theta r}=0} & {g_{\theta\theta}=r^2}\end{array}\right) \,\, g^{ij}=\left(\begin{array}{cc}{g^{rr}=1} & {g^{r\theta}=0} \\ {g^{\theta r}=0} & {g^{\theta\theta}=\frac{1}{r^2}}\end{array}\right)
    \det(g_{ij})=|g|= r^2 , \det(g^{ij})=|g|^{-1}=1/r^2
    $latex \nabla f(r,\theta) = \frac{\partial f}{\partial r} e^r + \frac{\partial f}{\partial \theta} e^\theta \quad\text{(1- form, covariant)}\\
    = \frac{\partial f}{\partial r} e_r + \frac{1}{r^2}\frac{\partial f}{\partial \theta} e_\theta \qquad\text{(contra-variant)} $

    另外常見的表示法是 Euclidean metric, normalized form, |g|=1 :
    \nabla f(r,\theta) = \frac{\partial f}{\partial r} \hat{e}_r + \frac{1}{r}\frac{\partial f}{\partial \theta} \hat{e}_\theta

一個純量場(0階張量)的梯度, \nabla \phi , 是一個向量。更準確的說是一個一階張量(1-form)。在求方向導數或是散度都很方便。
一個一維量場的梯度, \nabla \phi , 是一個二階張量(index 在樓上和樓下)。以此類推。

重新回到物理和幾何的對照

  1. (三維空間 + 一維時間): 滿足 Galilean tranform. F = ma , 最小作用原理~?。
  2. 四維時空:滿足 Lorentz tranform. 最小作用原理 \iff Geodesic.
  3. (n-維空間 + 一維時間):多粒子運動。constrain 變為 manifold. Tangent space (contra-variant basis): Lagrangian mechanics. Cotangent space (co-variant basis): Hamiltonian mechanics. How to expand this?

Reference

Wiki. 2019. “Covariance and Contravariance of Vectors.” In Wikipedia.
https://en.wikipedia.org/w/index.php?title=Covariance\_and\_contravariance\_of\_vectors&oldid=904269873

“Action (Physics).” 2019. Wikipedia.
https://en.wikipedia.org/w/index.php?title=Action_(physics)&oldid=904671703

Cyril. 2018. “Geodesic Equation from the Principle of Least Action.” September 18, 2018.
http://einsteinrelativelyeasy.com/index.php/general-relativity/97-geodesic-equation-from-the-principle-of-least-action.

“Relativistic Lagrangian Mechanics.” 2019. Wikipedia.
https://en.wikipedia.org/w/index.php?title=Relativistic_Lagrangian_mechanics&oldid=884947845

Appendix

Example 1: 牛頓空間以及不同慣性運動觀察者

  • 3D 歐式空間 + 1D 時間 (空間時間各自獨立,互不影響)
  • 不同慣性觀察者:
    • x' = x - v t
    • t' = t \,\,;\,\, y' = y \,\,;\,\, z' = z
    • (x,y,z,t) 座標系。為了簡化在 2D plan,只考慮(x, t) . 垂直軸是 t 軸。
    • 靜止在原點的物體。它的 world line 是一條垂直線
  • 對應座標轉換:x' = constant grid line 變成斜線,斜率由速度決定
  • 物理定律不變 (invariant):F = m a = m \ddot{x} = m \ddot{x'}

Example 2: 狹義相對論慣性運動觀察者

  • 空間:4D 閔式幾何 (Minkovsky space-time 4D space)
  • 運動方程式:least action principle <-> geodesic
  • 不同慣性觀察者: y = x – v*t

Example 2: 廣義相對論