2018年8月28日 星期二

Windows 安裝 dlib

Windows 安裝 dlib


Dlib 是甚麼?

BJ4,不然你會甚麼來這裡?  :)

安裝 Dlib : A Hard Way


理論上安裝  dlib  就是

pip install dlib

但是,在 Windows 上你應該會看到這個訊息:


我想,在 windows 上看到這個 cmake XXX 的錯誤,應該是人生裡面幾件最令人厭煩的事情之一,在前一台筆電上,這件事花了小弟不少青春跟電費,你要下載一大包東西、等待、龐雜的錯誤訊息 ....

安裝 Dlib : 有甚麼比站在巨人的肩膀上更爽快?

這個頁面應該會救了你  : https://pypi.org/simple/dlib/



好處不及遍數:

  1. 都好了,下載而已
  2. pypi 官方認證,比較安全,下載一些木馬回來也不見得比較輕鬆
  3. 省下很多時間喝茶打屁看FB
趕快動手作:

  1. 抓回來放在目錄裡 (我是下載 dlib-19.8.1-cp36-cp36m-win_amd64.whl)
  2. pip install dlib-19.8.1-cp36-cp36m-win_amd64.whl
  3. 搞定
  4. 玩耍去 ...

2018年8月11日 星期六

Tensorflow 的卷積層 tf.nn.conv2d() 用法

Tensorflow 的 tf.nn.conv2d() 用法


參數

tf.nn.conv2d( input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None)

Input 輸入資料(如一張圖片)

Input 的型態被設定為一個 4D 的 tensor,這四個維度設定跟 data_format 這個參數有關,
如果 data_format 設成 "NHWC"(預設值), 則四個維度的順序為:

[ Batch size(有多少張圖),  Height(圖高幾個像素), Width(圖寬幾個像素), Channels (有幾個頻道 如 R-G-B 就為 3 個, 單色圖片就為 1) ]

若設成 "NCHW" ,就變成
[ Batch size, Channels, Height, Width ]

# tensor 宣告可以像這樣 
x = tf.placeholder(tf.float32, shape=[1, 5, 5, 1])

輸入的資料可以像這樣

import numpy as np 
import tensorflow as tf 

x_in = np.array([
     [
         [[2], [1], [2], [0], [1]],
         [[1], [3], [2], [2], [3]],
         [[1], [1], [3], [3], [0]],
         [[2], [2], [0], [1], [1]],
         [[0], [0], [3], [1], [2]],
     ]
])

print(x_in.shape) # 形狀就是(1, 5, 5, 1)


Filter 過濾器 (有時稱 kernel )

圖一:Convolution 卷積示意

過濾器的本質就如圖示,I 是輸入的圖片,K即是過濾器。
過濾器之格式為:

[ Height (過濾器高) x Width (過濾器寬) x Input Channels (輸入幾個 channels - 是被 input 所決定的) x Output Channels (輸出幾個 channels - 如圖是 1) ]

特別說明一下,input channel 是被上一層的 channels 數所決定的,而 output channel 則是看下一層接住這個 convolution layer 的 input 會有多少。有興趣更深入的,這裡有進一步講解。

Strides 步進

進行 convolution 計算時,一步要前進多少。由於有四個面向 (即 data_format 所定義的 (NHWC 或 NCHW),所以這個值是一個 1D 的 tensor,但是有四個值,就照 data_format 所定義的順序,一次要跳多少。最常用的就是直接定義為 [1, 1, 1, 1]。

Padding 填充

選擇有兩種,'SAME' or 'VALID',這兩種演算法有人用底下這個圖,我覺得最容易一目了然。以一個例子來說:

  • Input width = 13
  • Filter width = 6
  • Stride = 5 


VALID就是當 filter 不斷滑過去計算,剩下的就丟掉 (drop)。SAME就是過程中不足的,自動補 0 進去。 更簡單來說,如果就整個 input 寬度的邊界來說,會跨過去的(當然要補值)就是 SAME,不會跨過去的就是 VALID。

Data_format 資料格式

前面一直在介紹的,有兩種資料排列方式,NHWC 與 NCHW,預設是 NHWC。
N : 圖形批次 batch size
H : 圖形高度 image height
W: 圖形寬度 image width
C: 頻道數,前面解釋過,RGB圖為三個、單色圖為一個,如果非圖形則看自己要連結的下一層輸入數

Use_cudnn_on_gpu GPU加速

是一個布林值 ( True 或 False ),是否要使用 Nvidia 的類神經網路庫 cudnn 來作 GPU 加速。

範例

import numpy as np 
import tensorflow as tf 

x_in = np.array([
     [ 
         [[1], [2], [3], [4], [5]], 
         [[5], [4], [3], [2], [1]], 
         [[1], [3], [5], [7], [9]], 
         [[2], [4], [6], [8], [10]], 
         [[1], [0], [1], [0], [1]], 
     ] 
]) 

# 設 out_channels==1 
kernel = np.array([ 
     [ 
         [[1]],[[2]] ], [ [[3]],[[4]] 
     ],
])

x = tf.placeholder(tf.float32, shape=[1, 5, 5, 1])
k = tf.constant(kernel, dtype=tf.float32)
conv = tf.nn.conv2d(x, k, strides=[1, 1, 1, 1], padding='VALID')

with tf.Session() as sess:
     result = sess.run(conv, feed_dict={x: x_in})
     print(result.shape, result)


參考

喜歡 "原廠" 英文函數說明的參考這裡

2018年7月29日 星期日

用 Putty 登入 AWS EC2 instance 的私鑰轉換


當用 AWS EC2 產生 Ubuntu (如 16.04 LTS) 的 instance 時,同時選擇使用新的 key 產生,並下載 .pem 的 key 檔。

首先需要了解 PuTTY本身不支持Amazon EC2生成的私鑰格式(.pem),需要使用 PuTTY 所附的工具 PuTTYgen 進行轉換。



進入 PuTTYgen 之後,選擇 Load,將從 AWS 下載的 .pem 檔載進來。



載入後,輸入 passphrase 兩次加強保護,之後選擇  Save private key,產生 PuTTY適用的 key 檔。



進入 PuTTY 除了一般須入的 host name / ip 以外,選擇 SSH --> Auth,將剛剛轉出來的 .ppk key 檔載入即可。

連結後,login account 為 ubuntu,密碼為剛剛所加強保護的 passphrase。

2018年7月24日 星期二

Windows 的 wget

Linux 上我們常用 wget, 那麼在 windows 上呢?

答案是一樣有東西可用! GNU 的  wget 事實上也有 support Windows (試 Windows 10)

站點
http://gnuwin32.sourceforge.net/packages/wget.htm

選 " Complete package, except sources"

或直接下載連結
https://sourceforge.net/projects/gnuwin32/?source=typ_redirect

安裝好,加完系統路徑,



重開 cmd.exe,就可以用了。



安裝優化 Tensorflow GPU相關功能 (Cuda)

問題: 出現 "Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2" 或其他未優化狀況,此為 tensorflow僅使用一般指令集,而未對目前平台新的指令集做優化。

解決方法:

1. 自己動手做

- Windows
https://software.intel.com/zh-cn/articles/tutorial-for-compiling-tensorflow-on-windows

人生苦短,沒有作。

2. 使用別人編譯好的包

- Linux

進去選相關的包
https://github.com/mind/wheels

在自己的虛擬環境
pip --no-cache-dir install https://github.com/mind/wheels/releases/download/{RELEASE}/{WHEEL}

- Windows

進去下載自己需要的包,到虛擬環境的目錄下
https://github.com/fo40225/tensorflow-windows-wheel


在自己的虛擬環境裡安裝
pip --no-cache-dir install 包的名字(如 tensorflow_gpu-1.9.0-cp36-cp36m-win_amd64.whl)


3. 試試看進 python 直譯器

import tensorflow as tf

- 錯誤排除

如出現 "ImportError: Could not find 'cudart64_92.dll'. TensorFlow requires that this DLL be installed in a directory that is named in your %PATH% environment variable. Download and install CUDA 9.2 from this URL: https://developer.nvidia.com/cuda-toolkit"

乖乖去裝一下 https://developer.nvidia.com/cuda-toolkit

- 錯誤排除

ImportError: Could not find 'cudnn64_7.dll'. TensorFlow requires that this DLL be installed in a directory that is named in your %PATH% environment variable. Note that installing cuDNN is a separate step from installing CUDA, and this DLL is often found in a different directory from the CUDA DLLs. You may install the necessary DLL by downloading cuDNN 7 from this URL: https://developer.nvidia.com/cudnn

乖乖去裝一下  https://developer.nvidia.com/cudnn

傳回來是一個壓縮檔
解壓縮到 (我在上面已經重裝了 cuda 9.2, 所以這邊也 copy 進 cuda 9.2 喔)
  1. Copy \cuda\bin\cudnn64_7.dll to C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.2\bin.
  2. Copy \cuda\ include\cudnn.h to C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.2\include.
  3. Copy \cuda\lib\x64\cudnn.lib to C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.2\lib\x64.
參考文章: https://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html


然後,就大功告成。


4. 運作看看


# 新建一個 graph. 
a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a') 
b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b') 
c = tf.matmul(a, b) 

# 新建session with log_device_placement 並設為 True. 
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True)) 

# 運行這個 op.
print(sess.run(c))

剛開始卡了一下,但還是跑完。

注意裡面已經開始使用 GPU了,如: 
MatMul: (MatMul): /job:localhost/replica:0/task:0/device:GPU:0 

終於成功了。

2018年7月12日 星期四

Python 3.6 自行安裝方式

Python 3.6 自行安裝方式(Ubuntu 16.04)

當 apt-get 無法安裝,版本太新、或要安裝特定版本時,可以採用以下安裝方式。

首先到 Python.org 的原始碼下載點 (https://www.python.org/ftp/python)
很多版本可供選擇,選擇一個自己要下載的版本,我這邊選擇了 3.6.6,點入將其檔案連結點複製起來。

右鍵選擇複製連結。

$ wget https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tar.xz
$ tar xJf Python-3.6.6.tar.xz
$ cd Python.3.6.6
$ ./configure
$ make
$ sudo make install


產生出來的執行檔名稱是 python3.6

Pip 發生無法 SSL 連線

如果遇到,pip 運作的時候,產生 "pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available." 之類的錯誤訊息。

則先安裝
$ sudo apt-get install build-essential checkinstall
$ sudo apt-get install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-de

再依照上述步驟重新安裝一次即可。

2017年6月3日 星期六

中本聰比特幣論文(下)

中本聰論文 比特幣:一個點對點的電子現金系統(Bitcoin: A Peer-to-Peer Electronic Cash System) (下)


譯者: Paul Chao的私房菜 趙尚威
1.文採意譯
2.圖取自 http://nakamotoinstitute.org/bitcoin
3.轉載譯文請註明出處,謝謝。



七、回收磁碟空間

當一個比特幣的最後交易紀錄已經被埋進夠多區塊裡面以後,之前的花費性交易紀錄就可以刪除以節省硬碟空間。為了讓這個不破壞區塊的哈希(hash)值,交易紀錄會用Merkle Tree來做哈希值,而且只有Merkle Tree的根值會被包含進區塊的哈希值中,舊的區塊可以把Merkle Tree的分支支解掉以壓縮空間,而中介性的哈希值不需要儲存。

沒有交易紀錄的區塊頭會是80 bytes, 如果我們假設每個區塊的產生是10分鐘,一年產生80 bytes * 6 * 24 * 365 = 4.2MB。依照2008年電腦系統銷售以2GB RAM為標配,摩爾定律預測當前的增幅是每年1.2GB,依此來看即使區塊頭必須被保留在記憶體裡,存儲都不應該是一個問題。

八、簡化付款驗證

在不運行完整網路節點的情況下來驗證付款是可能的。 用戶只需要保留在最長工作量證明的那一條鏈中所有區塊頭的副本,這個可以透過查詢比特幣網路上的節點直到確認這是最長條的鏈,以及取得已經加入時間戳記的區塊中連於交易的Merkle Tree的分支。他或許沒辦法自己檢查交易紀錄,但是透過鏈連到區塊鏈中的一處,他可以看到網路上某個節點接受了他的連結,而且在確認網路接受以後會持續有區塊加入。

因此,只要誠實的節點控制網路,驗證是可靠的,但是如果網路被攻擊者過度攻擊,還是會有漏洞。當網絡節點可以自己驗證交易的時候,這個簡化的方法可能會被攻擊者捏造的交易資料愚弄,而攻擊者可以繼續擴大攻擊整個網絡。防止這種情況的策略是在網路節點檢測到無效區塊時可以接收警報,提示用戶的軟件需要自己去下載完整的區塊以及遭警示的交易紀錄,以確認是否不一致。 頻繁收款的企業可能還是會想運行自己的節點以獲得更獨立的安全性以及更快的驗證。

九、組合和分割價值

雖然可以單獨一個一個來處理銅板,但為了每一分錢單獨去建立一筆交易是很不方便的。 為了讓價值可以被分割和合併,交易會包含多個輸入以及輸出。 輸入通常會是單筆從先前交易來的較大面額、或是多筆較小面額,但輸出最多是兩筆:一個用於付款,一個返回發送者返回更改(若有需要)。

值得一提的是,一筆交易取決於其他幾筆交易,而這些其他的幾筆交易又依賴更多其他的交易,這種扇出狀況(fan-out)在這裡不會是個問題。 因為我們從來沒有必要去提取一整個歷史交易紀錄的獨立副本。

十、隱私

傳統的銀行模式會對參與各方以及信任的第三方,保持信息存取的限制來實現一定程度的隱私,比特幣公開公布所有交易紀錄的必要性已經排除這種方法的可能,但透過把信息流打斷仍可以保持隱私:也就是讓保持公鑰匿名。公眾可以看到某人對某人發送金額,但沒有資訊能把這個交易跟任何人扯上關聯。這某種程度類似於證券交易,雖然交易時間和個別交易量被公開了,“紀錄磁帶”被公開了,但沒有告訴大家這些人到底是誰。

在這裡額外做個防火牆,每次交易都應該使用一組新的密鑰,使得擁有者的資訊不會曝光。某些連接仍不可避免會有多重輸入交易,必然表示這些輸入是由同一人擁有。這個風險在於如果所有者一個密鑰曝光,屬於這個人的其他交易也會隨著鏈接而曝光。

十一、計算

我們設想一個攻擊者試圖要快速產生另一條替代鏈,比誠實鏈的速度更快的場景。即便如此,它也不會讓系統開放到會任意變化,比如說憑空創造出價值來、或是攻擊者可以拿到不屬於自己的錢。節點是不會接受無效的交易成為真正付款,誠實的節點也永遠不會接受這樣包含這樣交易的區塊。攻擊者只可能改變自己發出的一筆交易來收回最近所花的錢。
誠實鏈和攻擊者鏈之間的競爭可以表徵為二項隨機漫步(Binomial Random Walk)。誠實的鏈條延伸了一個區塊,遞增1,增加了引導力,成為成功的事件、而攻擊者的鏈延伸了一個塊,減少了1,增加了差距,成為失敗的事件。
攻擊者從給定的差距可以趕上的機率,類似於賭徒破產問題(Gambler's Ruin problem)的機率。假設有一個無限信貸的賭徒從赤字開始,並且可以有無限次的嘗試去達成盈虧平衡。我們可以算出他有機會達到盈虧平衡的機率,也就是攻擊者的鏈可以追上誠實鏈的機率,如下[8]:
$$\large p = \small 誠實節點找到下一個區塊的機率$$ $$\large q = \small 攻擊者發現下一個區塊的機率$$ $$\large q_z = \small 攻擊者從後面的z個區塊追趕上來的機率$$ $$\large q_z = \begin{Bmatrix} 1 & \textit{if}\; p \leq q\\ (q/p)^z & \textit{if}\; p > q \end{Bmatrix}$$

若我們假設 p > q,機率是隨著攻擊者需要趕上的區塊數量增加而呈指數下降。對他來說,如果他不夠幸運,沒有早早開始的話,他的機會就會顯著地進一步變的更小。

我們現在要思考一個新交易的收件人到底需要等待多長時間才能夠確定發件人不能再更改交易。我們假設發件人就是攻擊者,他想讓收信人相信他已經付款了一段時間,一會兒之後轉過來把款轉回給自己。當發生這種情況時,收件人會被示警,但發件人會希望收件人發現的時候已經來不及了。

收件人產生一組新的密鑰對,並在簽章不久前才向發送者傳遞公鑰,這樣就可以防止發件人提前去準備一條區塊鏈,防止他幸運地遠在前面就開始進行偽造,然後執行交易那一刻能完成。一旦交易發送出去,不誠實的發件人開始在秘密兩條平行鏈上面工作,其中一條包含他的偽造版本。收件人一直等待,等到交易路已經被加到區塊裡了,並且z區塊已經被鏈接在後,他不知道攻擊者確切的進度,而是以為誠實區塊產生區塊本身就會有平均預期時間,而且假設攻擊者的潛在進度的期望值是呈帕松分佈(Poisson Distribution):

$$\large \lambda = z \frac qp$$ 為了取得攻擊者還能趕得上的機率,我們將每個進度的數量乘以帕松密度,亦即他從那一個點可以趕上的可能性:
$$\large \sum_{k=0}^{\infty} \frac{\lambda^k e^{-\lambda}}{k!} \cdot \begin{Bmatrix} (q/p)^{(z-k)} & \textit{if}\;k\leq z\\ 1 & \textit{if} \; k > z \end{Bmatrix}$$ 重新排列以避免加到分佈的無限尾部...
$$\large 1 - \sum_{k=0}^{z} \frac{\lambda^k e^{-\lambda}}{k!} \left ( 1-(q/p)^{(z-k)} \right )$$ 轉化成C的代碼:
#include 
double AttackerSuccessProbability(double q, int z)
{
 double p = 1.0 - q;
 double lambda = z * (q / p);
 double sum = 1.0;
 int i, k;
 for (k = 0; k <= z; k++)
 {
 double poisson = exp(-lambda);
 for (i = 1; i <= k; i++)
 poisson *= lambda / i;
 sum -= poisson * (1 - pow(q / p, z - k));
 }
 return sum;
}
執行產生一些結果之後,我們可以看到概率隨z呈指數下降。
q=0.1
z=0 P=1.0000000
z=1 P=0.2045873
z=2 P=0.0509779
z=3 P=0.0131722
z=4 P=0.0034552
z=5 P=0.0009137
z=6 P=0.0002428
z=7 P=0.0000647
z=8 P=0.0000173
z=9 P=0.0000046
z=10 P=0.0000012

q=0.3
z=0 P=1.0000000
z=5 P=0.1773523
z=10 P=0.0416605
z=15 P=0.0101008
z=20 P=0.0024804
z=25 P=0.0006132
z=30 P=0.0001522
z=35 P=0.0000379
z=40 P=0.0000095
z=45 P=0.0000024
z=50 P=0.0000006
當P小於0.1%的時候,結果為:
P < 0.001
q=0.10 z=5
q=0.15 z=8
q=0.20 z=11
q=0.25 z=15
q=0.30 z=24
q=0.35 z=41
q=0.40 z=89
q=0.45 z=340

十二、結論

我們提出了一個不依靠信任的電子交易系統。我們在一開始提出了現在一般的數位簽章的貨幣框架,這種框架提供強大的所有控制權,但卻沒有辦法防止雙重支出,不夠完整。為了解決這個問題,我們提出了使用工作量證明的點對點網路來記錄歷史性的公共交易,如果誠實節點掌握多數的計算能力,這種方式可以很快就讓攻擊者的計算攻擊成為不切實際。這個網路在它的非結構簡單性裡是很強韌的,節點可以立即一起執行,不需要大量的協調工作。節點不需要被識別,因為訊息是不會經過任何特定的點,只需盡最大努力(best effort)傳遞。節點可以任意離開或重新加入網路,加入時可以信任地接受工作量證明鏈,得到它們不在時所發生的資訊。他們根據CPU計算能力來投票,表達他們接受合法的區塊進行延伸區塊的動作,或是拒絕不合法的區塊、拒絕加入。所有需要的規則和獎勵措施都可以透過這種共識機制來實施。

參考書目

1. W. Dai, "b-money," http://www.weidai.com/bmoney.txt, 1998.
2. H. Massias, X.S. Avila, and J.-J. Quisquater, "Design of a secure timestamping service with minimal trust requirements," In 20th Symposium on Information Theory in the Benelux, May 1999.
3. S. Haber, W.S. Stornetta, "How to time-stamp a digital document," In Journal of Cryptology, vol 3, no 2, pages 99-111, 1991.
4. D. Bayer, S. Haber, W.S. Stornetta, "Improving the efficiency and reliability of digital time-stamping," In Sequences II: Methods in Communication, Security and Computer Science, pages 329-334, 1993.
5. S. Haber, W.S. Stornetta, "Secure names for bit-strings," In Proceedings of the 4th ACM Conference on Computer and Communications Security, pages 28-35, April 1997.
6. A. Back, "Hashcash - a denial of service counter-measure," http://www.hashcash.org/papers/hashcash.pdf, 2002.
7. R.C. Merkle, "Protocols for public key cryptosystems," In Proc. 1980 Symposium on Security and Privacy, IEEE Computer Society, pages 122-133, April 1980.
8. W. Feller, "An introduction to probability theory and its applications," 1957. ↩