2018年2月28日 星期三

買新時鐘

昨天晚上去鳳山載二哥回來後, 將前天在寶雅買的平板衛生紙拿去退換貨, 因為我在全聯超市有買到抽取式的, 平板的不好用, 而且太大, 浴室的衛生紙盒放不下. 退了 136 元我就換購了 288 元的時鐘, 因為鄉下客廳的老鐘換新電池後走得飛快, 調過還是一樣, 可能機心有問題了.

這款時鐘好處是有附溫溼度計, 只是掛太高似乎看得不是很清楚.

爸說 228 早上想去義大探望高樹阿姨, 他坐客運到大樂後我再開車載他過去. 阿姨的女兒說, 明天要與醫生談氣切問題, 應該會接受醫生建議, 氣切後可能轉入呼吸治療病房, 因加護已近 40 天. 希望一切順利.

在等候加護病房開啟會面時, 坐在旁邊一位歐吉桑問爸是否是地磚廠師傅, 交談之下才知原來我要叫他姑丈, 是住在牛埔莊的姨婆的女婿, 他太太 (爸的表妹我要叫姑姑, 是位畫家) 得腦瘤開刀後也在加護病房.

回鄉下的路上問爸我才搞清楚, 原來祖母有四個親姊妹, 兩個嫁杉林, 其中一個排行最小, 生第一胎時難產走了, 所以我沒印象. 另一個長得最像祖母, 也是五姊妹最後走的. 還有一個嫁五隻寮莊, 就是她孫子會來修水電的那個. 但我搞不清楚她們排行, 本周回去再問清楚. 祖母出養給朱家當女兒, 爸說她還有一個同為養女的姊妹嫁九寮莊, 聽說夫家很有錢, 跟貧窮的祖母不大往來, 所以我也沒啥印象. 總之, 婆字輩都不在了, 真是歲月如梭. 

看完阿姨就直接載爸回鄉下, 順便將新買的時鐘帶回去更換, 同時把昨天買的久雄電蒸鍋帶回去教爸用. 不過因為還有胡瓜與高麗菜, 下周還會再做滷菜.

使用 Keras 測試 MNIST 手寫數字辨識資料集

我昨天在 Windows 上安裝好 TensorFlow + Keras 深度學習框架, 分別在 Win7 的 Python 3.6.1 與 Win10 的 Python 3.6.4 都遇到過錯誤訊息, 但最後均安裝成功, 總結經驗, 成功安裝的條件歸納如下 :
  1. 安裝 Python 64 位元版 
  2. 可能須安裝 Numpy+MKL (下載), 而非僅 Numpy 而已 (Python 3.6.4 不用)
  3. 可能須安裝 msvcp.dll (下載)
特別注意, 若原先是安裝 32 位元版之 Python, 則移除後務必將原安裝目錄 (例如 C:/Python36) 整個刪除乾淨再重新安裝 64 bit 版, 否則在匯入 keras 套件時會出現錯誤.

參考 :

Windows 安裝深度學習框架 TensorFlow 與 Keras

接下來要利用 Keras 來測試 MNIST 手寫數字辨識資料集, 主要是參考林大貴寫的 "TensorFlow+Keras 深度學習人工智慧實務應用" 這本書的第六章, 另外也參考了下面這兩本 :
  1. Deep Learning (齋藤康毅)
  2. Python Deep Learning (Valentino)
MNIST 手寫數字辨識資料集是機器學習領域最有名的資料集之一, 包含了 70000 個 0~9 手寫阿拉伯數字的 BMP 格式圖檔與其正確之標籤 (Label, 即圖檔對應之 0~9 數字), 其中前 60000 個為訓練樣本, 用來訓練神經網路以建立模型; 其餘 10000 個為測試樣本, 用來檢驗模型是否能正確推論或預測圖片中的數字. 資料集的每個圖片都是解析度為 28*28 (784 個 pixel) 的灰階影像, 每個像素為 0~255 之數值.

Source : MNIST_database

參考 :

https://en.wikipedia.org/wiki/MNIST_database

MNIST 資料集是卷積神經網路之父 Yann LeCun (揚.勒丘恩) 於貝爾實驗室進行圖像識別研究時所蒐集, 他也是在此時發明了卷積神經網路. Yann LeCun 曾在多倫多大學跟隨 Geoffrey Hinton 做博士後研究, 他與 Geoffrey HintonYoshua Bengio  被稱為深度學習領域的三巨頭. Yann LeCun 自 2013 年起任職臉書 AI 實驗室 (FAIR) 主任, 不過目前已逐步退出管理層, 專注於 AI 科研工作, 但仍繼續主導臉書 AI 研究方向, 參考 :

Facebook AI chief Yann LeCun is stepping aside to take on dedicated research role

以下為此次測試紀錄 :


1. 匯入 MNIST 模組

首先是從 Keras 匯入 mnist 模組 :

D:\Python\tensorflow>python
Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)]
 on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from keras.datasets import mnist        #匯入 mnist 模組
Using TensorFlow backend.                                         

可見 Keras 預設底層是使用 TensorFlow 運算引擎進行張量運算.


2. 載入 MNIST 資料集

接著呼叫 load_data() 載入 MNIST 資料集. 它會先到 C 碟的使用者目錄下的 .keras 子目錄檢查是否已有 mnist.npz 資料檔, 有的話就直接載入, 否則會自動到下列網址下載並存放於 C:\使用者\user_id\.keras\dataset\ 目錄下 :

https://s3.amazonaws.com/img-datasets/mnist.npz

>>> (x_train_image, y_train_label), (x_test_image, y_test_label)=mnist.load_data() 
Downloading data from https://s3.amazonaws.com/img-datasets/mnist.npz   
>>>

如果因防火牆阻擋無法以 minst.load_data() 下載 mnist.npz, 可用瀏覽器下載後放到 C:\使用者\user_id\.keras\dataset\ 下即可 :





3. 查詢資料集筆數

函數 minst.load_data() 的傳回值是兩組 tuple (其元素為串列), 第一組是訓練資料, 第二組是測試資料, 都是前為圖片 (image), 後為標籤 (label), 格式如下 :

(訓練圖片, 訓練標籤), (測試圖片, 測試標籤)

將傳回樣本傳入 len() 查詢資料集筆數 :

>>> print('train image=', len(x_train_image))   #顯示訓練圖片筆數 : 6 萬筆
train image= 60000
>>> print('train label=', len(y_train_label))       #顯示訓練標籤筆數 : 6 萬筆
train label= 60000
>>> print('test image=', len(x_test_image))       #顯示測試圖片筆數 : 1 萬筆
test image= 10000
>>> print('test label=', len(y_test_label))           #顯示測試標籤筆數 : 1 萬筆
test label= 10000

可見訓練樣本 60000 + 測試樣本 10000 共 70000 筆資料.


4. 查詢資料集外型 (shape)

圖像與標籤均有 shape 屬性紀錄樣本之外型 :

>>> print('x_train_image:',x_train_image.shape)     #顯示訓練樣本圖片外型
x_train_image: (60000, 28, 28)
>>> print('y_train_label:',y_train_label.shape)         #顯示訓練樣本標籤外型
y_train_label: (60000,)
>>> print('x_test_image:',x_test_image.shape)         #顯示測試樣本圖片外型
x_test_image: (10000, 28, 28)
>>> print('y_test_label:',y_test_label.shape)             #顯示測試樣本標籤外型
y_test_label: (10000,)

可見訓練圖片有 60000 張, 其解析度為 28*28; 而相對之標籤 (label) 則有 60000 個. 測試圖片有 10000 張, 其解析度為 28*28; 而相對之標籤 (label) 也是 10000 個.


5. 顯示第一筆訓練樣本圖片內容

從上面的 shape 屬性可知每一個樣本圖片解析度為 28*28, 即使用 784 個像素來描點, 每一個像素具體來說就是 0~255 的數字, 代表該畫素的灰階程度, 0 表示白色, 255 表示黑色 :

>>> print('x_train_image[0]=', x_train_image[0])
x_train_image[0]= [[  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   3  18  18  18 126 136
  175  26 166 255 247 127   0   0   0   0]
 [  0   0   0   0   0   0   0   0  30  36  94 154 170 253 253 253 253 253
  225 172 253 242 195  64   0   0   0   0]
 [  0   0   0   0   0   0   0  49 238 253 253 253 253 253 253 253 253 251
   93  82  82  56  39   0   0   0   0   0]
 [  0   0   0   0   0   0   0  18 219 253 253 253 253 253 198 182 247 241
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0  80 156 107 253 253 205  11   0  43 154
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0  14   1 154 253  90   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0 139 253 190   2   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0  11 190 253  70   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0  35 241 225 160 108   1
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0  81 240 253 253 119
   25   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0  45 186 253 253
  150  27   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0  16  93 252
  253 187   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0 249
  253 249  64   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0  46 130 183 253
  253 207   2   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0  39 148 229 253 253 253
  250 182   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0  24 114 221 253 253 253 253 201
   78   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0  23  66 213 253 253 253 253 198  81   2
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0  18 171 219 253 253 253 253 195  80   9   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0  55 172 226 253 253 253 253 244 133  11   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0 136 253 253 253 212 135 132  16   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]]
>>> print('y_train_label[0]=', y_train_label[0]) 
y_train_label[0]= 5 

可見此二維串列所儲存之圖片標籤為 5.


6. 顯示第一筆訓練樣本之圖片與標籤

顯示 2D 圖形須匯入 matplotlib 模組, 下列為參考書中範例所寫的 Pyhton 程式, 它會顯示第一個樣本 (索引 0) 的圖片與標籤 :

#show_train_image0.py
from keras.datasets import mnist
import matplotlib.pyplot as plt

def plot_image(image):                        #繪圖函數
fig=plt.gcf()                                         #取得 pyplot 物件參考
fig.set_size_inches(2, 2)                      #設定畫布大小為 2 吋*2吋
plt.imshow(image, cmap='binary')      #以 binary (灰階) 顯示 28*28 圖形
plt.show()                                             #顯示圖形

(x_train_image, y_train_label), \
(x_test_image, y_test_label)=mnist.load_data()   #載入 MNIST 資料集
print(y_train_label[0])                                           #顯示第一筆樣本之標籤 (label)
plot_image(x_train_image[0])                               #繪製第一筆樣本之圖形

將此程式存為 show_train_image0.py, 然後在檔案所在目錄以 python 指令執行此程式, 這時會顯示 MNIST 的第一筆樣本標籤為 5, 並開啟一個繪圖視窗顯示第一筆樣本的圖片 :

D:\Python\test>python show_train_image0.py
Using TensorFlow backend.
5




可見第一筆樣本是手寫數字 5.


7. 顯示第 n 筆訓練樣本之圖片與標籤 (利用命令列參數)

上面的程式只能顯示第一筆樣本, 我們可以透過命令列參數將要顯示之樣本索引傳給程式, 利用模組 sys 的 argv 屬性取得命令列參數, 用來取代上面程式中的索引 0 即可動態地控制要顯示的樣本, 參考 :

Python 命令行参数

如果在命令列執行 Python 指令時後面帶參數, 例如 :

D:\Python\test>python test.py arg1 arg2 arg3

則可利用 sys 模組的 argv 屬性串列來取得參數. 串列 sys.argv[] 的第一個元素是程式名稱, 以上面指令為例, 其內容為 :

['test.py', 'arg1', 'arg2', 'arg3']

使用 sys 模組需先用 import sys 匯入.

將上面的程式加上命令列參數存取功能修改如下 :

#show_train_image.py
import sys                                        #匯入系統模組
from keras.datasets import mnist
import matplotlib.pyplot as plt

def plot_image(image):
fig=plt.gcf()
fig.set_size_inches(2, 2)
plt.imshow(image, cmap='binary')
plt.show()

(x_train_image, y_train_label), \
(x_test_image, y_test_label)=mnist.load_data()
i=int(sys.argv[1])                            #命令列參數為字串, 須轉為整數
print(y_train_label[i])
plot_image(x_train_image[i])

將此程式存為 show_train_image.py, 然後於命令提示字元視窗執行此程式時傳入參數 1 即顯示第 2 筆樣本之圖片與標籤 :




可見第二筆樣本為手寫數字 0.


7. 顯示多筆訓練樣本之圖片與標籤 (利用命令列參數)

上面的程式都只能顯示一個樣本, 其實 matplotlib.pyplot 有一個 subplot() 函數可以在一張圖上繪製多個子圖, 參考 :

# matplotlib.pyplot.subplots
Matplotlib简介和pyplot的简单使用——subplot

參考書中範例將上面程式修改為如下可一次顯示多個樣本的程式如下 : 

#show_train_images.py
import sys                                        
from keras.datasets import mnist
import matplotlib.pyplot as plt

def plot_images_labels_prediction(images,labels,prediction,idx,num=10):
   fig=plt.gcf()                                                      #取得 pyplot 物件參考
   fig.set_size_inches(12, 14)                               #設定畫布大小為 12 吋*14吋
   if num > 25: num=25                                   #限制最多顯示 25 個子圖
   for i in range(0, num):                                       #依序顯示 num 個子圖
       ax=plt.subplot(5, 5, i+1)                                #建立 5*5 個子圖中的第 i+1 個
       ax.imshow(images[idx], cmap='binary')       #顯示子圖
       title="label=" + str(labels[idx])
       if len(prediction) > 0:                                #有預測值就加入標題中
           title += ",predict=" + str(prediction[idx])
       ax.set_title(title, fontsize=10)                        #設定標題
       ax.set_xticks([]);                                            #不顯示 x 軸刻度
       ax.set_yticks([]);                                            #不顯示 y 軸刻度
       idx += 1                                                          #樣本序號增量 1
   plt.show()                                                           #繪製圖形

(x_train_image, y_train_label), \
(x_test_image, y_test_label)=mnist.load_data()
i=int(sys.argv[1])                    #取得第一個命令列參數 ()
j=int(sys.argv[2])                    #取得第二個命令列參數
plot_images_labels_prediction(x_train_image,y_train_label,[],i,j)    #無預測值


此程式中繪圖函數 plot_images_labels_prediction() 的傳入參數有 5 個 :
  1. images=樣本之圖片串列
  2. labels=樣本之標籤串列
  3. prediction=預測值串列
  4. idx=資料集起始索引
  5. num=一次顯示之樣本數
其中 prediction 為預測值串列, 目前還未進行辨識用不到, 可傳入空串列即可. 而 num 預設值為 10, 如果只傳入一個參數, 沒有傳 num 給程式的話, 就顯示 10 個樣本. num 最大值被限制為 25, 即 1 次最多顯示 25 個樣本.

每個樣本圖片會被繪製在 pyplot 的子圖物件 ax 上, 利用子圖物件的 set_title() 方法將對應之標籤與預測值顯示在子圖上方的標題中. 由於一次要顯示的圖最多達 25 張 (即 5*5 方格), 因此畫布區域擴大為 12 吋*14 吋, 因每個子圖占 2 吋 * 2 吋, 高度部分有標題故多 2 吋. 

我仍然利用命令列傳入參數, 但此程式要傳入 idx 與 num 這兩個參數, idx 是一個 0 起始的索引, 用來指定要從資料集的哪一個樣本開始顯示; num 為要一次顯示的樣本數. 將上面程式存成檔案 show_train_images.py 後於命令列執行, 例如下面指令是從資料集第二個樣本 (索引 1) 開始顯示 10 個樣本 :

D:\test>python show_train_images.py 1 10
Using TensorFlow backend.

結果如下 : 



下面是從資料集開頭顯示 25 的樣本, 例如 :

D:\test>python show_train_images.py 0 25
Using TensorFlow backend.

結果為 :



這樣我們就可以指定任意起始索引與想要顯示幾筆樣本了, 但一次最多顯示 25 個樣本. 注意, MNIST 訓練樣本只有 60000 筆, 因此起始索引最多只到 59999,  例如最後 25 筆訓練樣本是從索引 59975 開始的 25 筆 :

D:\test>python show_train_images.py 59975 25
Using TensorFlow backend.




如果起始索引改為 59976, 則迴圈的最後一圈會因為存取不到索引 60000 而出現錯誤 :

D:\test>python show_train_images.py 59976 25
Using TensorFlow backend.
Traceback (most recent call last):
  File "show_train_images.py", line 25, in <module>
    plot_images_labels_prediction(x_train_image,y_train_label,[],i,j)
  File "show_train_images.py", line 11, in plot_images_labels_prediction
    ax.imshow(images[idx], cmap='binary')
IndexError: index 60000 is out of bounds for axis 0 with size 60000 


同樣地, 對於 MINST 資料集裡的 10000 個樣本, 我們也可以用這個方法來一次顯示多個測試樣本, 但要將上面程式中傳入函數 plot_images_labels_prediction() 的前兩個參數改為測試樣本串列, 程式修改為如下的 show_test_images.py :


#show_test_images.py
import sys                                     
from keras.datasets import mnist
import matplotlib.pyplot as plt

def plot_images_labels_prediction(images,labels,prediction,idx,num=10):
   fig=plt.gcf()
   fig.set_size_inches(12, 14)
   if num > 25: num=25
   for i in range(0, num):
       ax=plt.subplot(5, 5, i+1)
       ax.imshow(images[idx], cmap='binary')
       title="label=" + str(labels[idx])
       if len(prediction) > 0:
           title += ",predict=" + str(prediction[idx])
       ax.set_title(title, fontsize=10)
       ax.set_xticks([]);
       ax.set_yticks([]);
       idx += 1
   plt.show()

(x_train_image, y_train_label), \
(x_test_image, y_test_label)=mnist.load_data()
i=int(sys.argv[1])
j=int(sys.argv[2])
plot_images_labels_prediction(x_test_image,y_test_label,[],i,j)   #傳入測試樣本串列


顯示測試樣本的前 25 筆 :

D:\test>python show_test_images.py 0 25
Using TensorFlow backend.



測試樣本最後 25 筆 :

D:\test>python show_test_images.py 9975 25
Using TensorFlow backend.




MNIST 資料集的查詢與繪圖操作大致如上.

哈! Keras 實在是太帥了!  帥到不行! 

2018年2月26日 星期一

如何讓 Python2 與 Python3 共存

這兩天在為還原更新的 Win10 重新安裝 Python 3 時發現一個問題, 在安裝過程中我有勾選更新 path, 完成後在命令提示字元視窗下 python 指令還是一樣進入之前玩 GAE 時就安裝的 python 2.7 :

C:\Users\Tony>python 
Python 2.7.12 (v2.7.12:d33e0cf91556, Jun 27 2016, 15:24:40) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.

檢查環境變數沒問題, Python 3 與其 Script 都有在 path 變數裡面, 為何還是以 Python 2 為預設指令呢? 這是因為 Python 2.7 是比較早安裝的, 所以在 path 變數裡 C:\Python27\Scripts\ 與 C:\Python27\ 這兩項是位於 C:\Python36\Scripts\ 與 C:\Python36\ 之前, 當然會先抓到 Python 2 版的指令. 只要兩個順序調換, 讓 C:\Python36\Scripts\ 與 C:\Python36\ 先被抓到就可以了. 更改順序後下 set path 結果如下 :

C:\Users\tony>set path
Path=C:\Python36\Scripts\;C:\Python36\;C:\Program Files (x86)\Intel\iCLS Client\
;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\S
ystem32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\
Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R)
Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Managemen
t Engine Components\IPT;C:\Program Files\Intel\Intel(R) Management Engine Compon
ents\IPT;C:\Program Files (x86)\Java\jdk1.7.0_79\bin;C:\Python27\Scripts\;C:\Pyt
hon27\;
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY;.PYW

當然直接移除 Python 2 也是可以的, 但由於 Python 2.7 偶而還是會用到, 所以兩者必須共存才行. 這在樹莓派的 Rasbian Linux 下可透過設定以 python2 與 python3 指令分別進入 Pyhton 2 與 Python 3, 但在 Windows 下要怎麼做?

我參考了下面這篇文章, 作者將 Python 3 安裝目錄下的 python.exe 改為 python3.exe, 要進入 Python 3 IDLE 就下 python3 指令 :

Windows上如何同時使用Python2和3

但我認為應該反其道而行, 因為 Python 2.7 我目前較少用, 大都改用 Python 3, 所以我是將 Python 2 安裝目錄下的 python.exe 改成 python2.exe :




重新開啟命令提示字元視窗, 輸入 python2 就會進入 Python 2, 而輸入 python 則進入 Python 3 的 IDLE :

C:\Users\Tony>python2 
Python 2.7.12 (v2.7.12:d33e0cf91556, Jun 27 2016, 15:24:40) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()

C:\Users\Tony>python 
Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:54:40) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.

2018年2月25日 星期日

樹莓派安裝深度學習框架 TensorFlow 與 Keras

下午在 Windows 上成功安裝深度學習框架 TensorFlow+Keras, 晚飯後著手在 Pi 3 上安裝, 不過樹莓派的 TensorFlow 目前只支援 Python 3.4 下的 v1.1.0, 參考 :

在 Raspberry Pi 2,3 上安装 Tensorflow 搭建深度学习环境

此文所下載安裝之 TensorFlow 實際上是來自下列 GitHub 網站 :

GitHub : TensorFlow for Raspberry Pi

安裝程序如下 :


一. 安裝 TensorFlow (底層) :

1. 先更新 TensorFlow 的相依套件 :

sudo apt-get install python3-pip python3-dev 

2. 然後用 wget 下載 TensorFlow 1.1.0 版 :

wget https://github.com/samjabrahams/tensorflow-on-raspberry-pi/releases/download/v1.1.0/tensorflow-1.1.0-cp34-cp34m-linux_armv7l.whl

3. 安裝 TensorFlow : 

sudo pip3 install tensorflow-1.1.0-cp34-cp34m-linux_armv7l.whl

安裝過程非常久, 大約要半小時, 而且會不斷吐出一堆看似錯誤的訊息 :

........ (略)
trong -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 build/temp.linux-armv7l-3.4/numpy/random/mtrand/mtrand.o build/temp.linux-armv7l-3.4/numpy/random/mtrand/randomkit.o build/temp.linux-armv7l-3.4/numpy/random/mtrand/initarray.o build/temp.linux-armv7l-3.4/numpy/random/mtrand/distributions.o -Lbuild/temp.linux-armv7l-3.4 -o build/lib.linux-armv7l-3.4/numpy/random/mtrand.cpython-34m.so
    Creating build/scripts.linux-armv7l-3.4/f2py3
      adding 'build/scripts.linux-armv7l-3.4/f2py3' to scripts
    changing mode of build/scripts.linux-armv7l-3.4/f2py3 from 644 to 755

    warning: no previously-included files matching '*.pyo' found anywhere in distribution
    warning: no previously-included files matching '*.pyd' found anywhere in distribution
    warning: no previously-included files matching '*.swp' found anywhere in distribution
    warning: no previously-included files matching '*.bak' found anywhere in distribution
    warning: no previously-included files matching '*~' found anywhere in distribution
    changing mode of /usr/local/bin/f2py3 to 755
    Running from numpy source directory.
    /usr/lib/python3.4/distutils/dist.py:260: UserWarning: Unknown distribution option: 'python_requires'
      warnings.warn(msg)
    /tmp/pip-build-i0_rx06a/numpy/numpy/distutils/system_info.py:624: UserWarning:
        Atlas (http://math-atlas.sourceforge.net/) libraries not found.
        Directories to search for the libraries can be specified in the
        numpy/distutils/site.cfg file (section [atlas]) or by setting
        the ATLAS environment variable.
      self.calc_info()
    /usr/lib/python3.4/distutils/dist.py:260: UserWarning: Unknown distribution option: 'python_requires'
      warnings.warn(msg)
    /usr/lib/python3.4/distutils/dist.py:260: UserWarning: Unknown distribution option: 'define_macros'
      warnings.warn(msg)
Successfully installed tensorflow werkzeug protobuf wheel six numpy
Cleaning up...

但實際上這些訊息只是 Warning 而已, 並非安裝有甚麼問題, 不用管它, 靜靜等待安裝結束.  


4. 重新安裝 mock 以免匯入 tensorflow 時報錯 :

sudo pip3 uninstall mock 
sudo pip3 install mock
但我第四步沒有做, 毋須重新安裝 mock 即可順利匯入 TensorFlow 套件 :

pi@raspberrypi:~ $ python3
Python 3.4.2 (default, Oct 19 2014, 13:31:11)
[GCC 4.9.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow as tf 
>>> tf.__version__   
'1.1.0'


二. 安裝 Keras (上層) :

我在網路上查到下面這篇在 Pi 3 安裝 Keras 的文章 :

INSTALLING KERAS ON RASPBERRY PI 3

但此文是從 Numpi, Scipy 等 ML 基礎套件開始一一安裝, 但我之前都已安裝過了, 所以就跳過直接用 pip3 安裝 Keras, 很快就完成了 :

pi@raspberrypi:~ $ sudo pip3 install keras 
Downloading/unpacking keras
  Downloading Keras-2.1.4-py2.py3-none-any.whl (322kB): 322kB downloaded
Requirement already satisfied (use --upgrade to upgrade): numpy>=1.9.1 in /usr/local/lib/python3.4/dist-packages (from keras)
Requirement already satisfied (use --upgrade to upgrade): scipy>=0.14 in /usr/lib/python3/dist-packages (from keras)
Requirement already satisfied (use --upgrade to upgrade): six>=1.9.0 in /usr/local/lib/python3.4/dist-packages (from keras)
Downloading/unpacking pyyaml (from keras)
  Downloading PyYAML-3.12.tar.gz (253kB): 253kB downloaded
  Running setup.py (path:/tmp/pip-build-a1rgahzu/pyyaml/setup.py) egg_info for package pyyaml

Installing collected packages: keras, pyyaml
  Running setup.py install for pyyaml
    checking if libyaml is compilable
    arm-linux-gnueabihf-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -g -fstack-protector-strong -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -fPIC -I/usr/include/python3.4m -c build/temp.linux-armv7l-3.4/check_libyaml.c -o build/temp.linux-armv7l-3.4/check_libyaml.o
    build/temp.linux-armv7l-3.4/check_libyaml.c:2:18: fatal error: yaml.h: No such file or directory
     #include <yaml.h>
                      ^
    compilation terminated.

    libyaml is not found or a compiler error: forcing --without-libyaml
    (if libyaml is installed correctly, you may need to
     specify the option --include-dirs or uncomment and
     modify the parameter include_dirs in setup.cfg)

Successfully installed keras pyyaml
Cleaning up...
pi@raspberrypi:~ $ python3
Python 3.4.2 (default, Oct 19 2014, 13:31:11)
[GCC 4.9.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import keras
Using TensorFlow backend.
>>> keras.__version__
'2.1.4'

OK, 這樣樹莓派也可以跑 TesorFlow+Keras 了. 

Windows 安裝深度學習框架 TensorFlow 與 Keras

最近從市圖借到下面這本林大貴寫的 "TensorFlow+Keras 深度學習人工智慧實務應用", 此書在原理部分言簡意賅, 配合簡明插圖與實務操作說明, 我認為是 ML 初學者非常理想的入門書 :


Source : 博客來


 下午得空便在鄉下的 Win10 電腦上實際安裝 TensorFlow+Keras 框架, 以下是安裝紀錄 :


一. 安裝 TensorFlow (底層) :

TensorFlow 是 Google Brain 團隊所開發的低階深度學習框架, 可在各平台上進行高效能之矩陣運算, 原先僅使用於 Gmail 信件過濾, Google 語音辨識, Google 翻譯等 Google 自家產品上, 為了透過開源社群之力量使其成為市場標準, Google 於 2015 年 11 月將其原始碼開放. 參考 :

https://www.tensorflow.org

在 Windows 上安裝 TensorFlow 書中建議先安裝 Anaconda, 但我一直覺得 Anaconda 太龐大, 所以我還是傾向用命令提示字元視窗進行原生安裝 (native installation). 注意, 根據上面官網說明, 執行 TensorFlow 需要 Python 64 位元版本, 參考 :

https://www.tensorflow.org/install/install_windows

因此下載 Python 時不要按下載頁的那個大按鈕 (那是下載 32 位元版本), 而是要按 Python for "Windows" 超連結, 找尋 x86-64 executable installer 版下載安裝, 我下載的是目前的穩定版 v3.6.4 (python-3.6.4-amd64.exe)  :





Python 64 安裝好後, 可參考下列文章安裝 Python 機器學習套件 :

在 Windows 中安裝 Python 機器學習套件
Windows 安裝 Python 機器學習工具

包括下列 4 個指令 :
  1. pip3 install scipy (會同時安裝 Numpy)
  2. pip3 install matplotlib
  3. pip3 install pandas
  4. pip3 install scikit-learn
然後即可用 pip3 指令加 upgrade 參數安裝 tensorflow 套件, 並將執行過程輸出至檔案 tensorflow.txt 中, 這樣其相依套件如 numpy 等若有更新會自動刪除舊版再安裝新版, 參考 :

把「命令提示字元」視窗的輸出結果,直接複製到剪貼簿

D:\> pip3 install --upgrade tensorflow > tensorflow.txt

Collecting tensorflow
  Downloading tensorflow-1.5.0-cp36-cp36m-win_amd64.whl (31.1MB)
Collecting absl-py>=0.1.6 (from tensorflow)
  Downloading absl-py-0.1.10.tar.gz (79kB)
Collecting six>=1.10.0 (from tensorflow)
  Downloading six-1.11.0-py2.py3-none-any.whl
Collecting wheel>=0.26 (from tensorflow)
  Downloading wheel-0.30.0-py2.py3-none-any.whl (49kB)
Collecting protobuf>=3.4.0 (from tensorflow)
  Downloading protobuf-3.5.1-py2.py3-none-any.whl (388kB)
Collecting numpy>=1.12.1 (from tensorflow)
  Downloading numpy-1.14.1-cp36-none-win_amd64.whl (13.4MB)
Collecting tensorflow-tensorboard<1.6.0,>=1.5.0 (from tensorflow)
  Downloading tensorflow_tensorboard-1.5.1-py3-none-any.whl (3.0MB)
Collecting setuptools (from protobuf>=3.4.0->tensorflow)
  Downloading setuptools-38.5.1-py2.py3-none-any.whl (489kB)
Collecting html5lib==0.9999999 (from tensorflow-tensorboard<1.6.0,>=1.5.0->tensorflow)
  Downloading html5lib-0.9999999.tar.gz (889kB)
Collecting bleach==1.5.0 (from tensorflow-tensorboard<1.6.0,>=1.5.0->tensorflow)
  Downloading bleach-1.5.0-py2.py3-none-any.whl
Collecting markdown>=2.6.8 (from tensorflow-tensorboard<1.6.0,>=1.5.0->tensorflow)
  Downloading Markdown-2.6.11-py2.py3-none-any.whl (78kB)
Collecting werkzeug>=0.11.10 (from tensorflow-tensorboard<1.6.0,>=1.5.0->tensorflow)
  Downloading Werkzeug-0.14.1-py2.py3-none-any.whl (322kB)
Installing collected packages: six, absl-py, wheel, setuptools, protobuf, numpy, html5lib, bleach, markdown, werkzeug, tensorflow-tensorboard, tensorflow
  Found existing installation: six 1.10.0
    Uninstalling six-1.10.0:
      Successfully uninstalled six-1.10.0
  Running setup.py install for absl-py: started
    Running setup.py install for absl-py: finished with status 'done'
  Found existing installation: setuptools 28.8.0
    Uninstalling setuptools-28.8.0:
      Successfully uninstalled setuptools-28.8.0
  Found existing installation: numpy 1.12.1+mkl
    Uninstalling numpy-1.12.1+mkl:
      Successfully uninstalled numpy-1.12.1+mkl
  Running setup.py install for html5lib: started
    Running setup.py install for html5lib: finished with status 'done'
Successfully installed absl-py-0.1.10 bleach-1.5.0 html5lib-0.9999999 markdown-2.6.11 numpy-1.14.1 protobuf-3.5.1 setuptools-38.5.1 six-1.11.0 tensorflow-1.5.0 tensorflow-tensorboard-1.5.1 werkzeug-0.14.1 wheel-0.30.0

這樣便安裝好 TensorFlow 框架了, 但是進入 Python IDLE 匯入 tensorflow 套件時卻出現 "找不到指定的模組" 的錯誤訊息 :

D:\test>python
Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import tensorflow as tf          (匯入 tensorflow 套件並取名為 tf)
Traceback (most recent call last):
  File "C:\Python36\lib\site-packages\tensorflow\python\platform\self_check.py", line 47, in preload_check
    ctypes.WinDLL(build_info.msvcp_dll_name)
  File "C:\Python36\lib\ctypes\__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] 找不到指定的模組

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python36\lib\site-packages\tensorflow\__init__.py", line 24, in <module>
    from tensorflow.python import *
  File "C:\Python36\lib\site-packages\tensorflow\python\__init__.py", line 49, in <module>
    from tensorflow.python import pywrap_tensorflow
  File "C:\Python36\lib\site-packages\tensorflow\python\pywrap_tensorflow.py", line 30, in <module>
    self_check.preload_check()
  File "C:\Python36\lib\site-packages\tensorflow\python\platform\self_check.py", line 55, in preload_check
    % build_info.msvcp_dll_name)
ImportError: Could not find 'msvcp140.dll'. TensorFlow requires that this DLL be installed in a directory that is named in your %PATH% environment variable. You may install this DLL by downloading Visual C++ 2015 Redistributable Update 3 from this URL: https://www.microsoft.com/en-us/download/details.aspx?id=53587

錯誤原因是找不到 msvcp.dll 這個動態連結檔 (DLL), 並建議到微軟網站下載 VC++ 2015 更新檔, 我下載的是名為 vc_redist.x64.exe 的 64 位元版本 :




下載後直接點擊安裝, 完成後即可順利匯入 tensorflow 套件了 :

>>> import tensorflow as tf
>>> tf.__version__                  #查詢 tebsorflow 版本
'1.5.0'

參考 :

Error importing tensorflow on windows 10

如果因防火牆無法直接用 pip3 安裝, 參考上面安裝過程所示正確版本, 依序下載安裝下列相依模組安裝 :

https://pypi.python.org/pypi/absl-py
https://pypi.python.org/pypi/six#downloads
https://pypi.python.org/pypi/wheel#downloads
https://pypi.python.org/pypi/protobuf/3.5.1
https://pypi.python.org/pypi/numpy#downloads
https://pypi.python.org/pypi/html5lib/0.9999999
https://pypi.python.org/pypi/bleach/1.5.0
https://pypi.python.org/pypi/bleach/1.5.0#downloads
https://pypi.python.org/pypi/Markdown
https://pypi.python.org/pypi/Werkzeug
https://pypi.python.org/pypi/tensorflow-tensorboard
https://pypi.python.org/pypi/tensorflow/1.5.0

手動安裝過程如下 (必須依序, TensorFlow 的兩個檔案要最後安裝) :

D:\Python\tensorflow>pip3 install absl-py-0.1.10.tar.gz
Processing d:\python\tensorflow\absl-py-0.1.10.tar.gz
Requirement already satisfied: six in c:\python36\lib\site-packages (from absl-p
y==0.1.10)
Installing collected packages: absl-py
  Running setup.py install for absl-py ... done
Successfully installed absl-py-0.1.10

D:\Python\tensorflow>pip3 install six-1.11.0-py2.py3-none-any.whl
Processing d:\python\tensorflow\six-1.11.0-py2.py3-none-any.whl
Installing collected packages: six
  Found existing installation: six 1.10.0
    Uninstalling six-1.10.0:
      Successfully uninstalled six-1.10.0
Successfully installed six-1.11.0

D:\Python\tensorflow>pip3 install wheel-0.30.0-py2.py3-none-any.whl
Processing d:\python\tensorflow\wheel-0.30.0-py2.py3-none-any.whl
Installing collected packages: wheel
Successfully installed wheel-0.30.0

D:\Python\tensorflow>pip3 install protobuf-3.5.1-py2.py3-none-any.whl
Processing d:\python\tensorflow\protobuf-3.5.1-py2.py3-none-any.whl
Requirement already satisfied: setuptools in c:\python36\lib\site-packages (from
 protobuf==3.5.1)
Requirement already satisfied: six>=1.9 in c:\python36\lib\site-packages (from p
rotobuf==3.5.1)
Installing collected packages: protobuf
Successfully installed protobuf-3.5.1

D:\Python\tensorflow>pip3 install numpy-1.14.1-cp36-none-win_amd64.whl
Processing d:\python\tensorflow\numpy-1.14.1-cp36-none-win_amd64.whl
Installing collected packages: numpy
  Found existing installation: numpy 1.12.1+mkl
    Uninstalling numpy-1.12.1+mkl:
      Successfully uninstalled numpy-1.12.1+mkl
Successfully installed numpy-1.14.1

D:\Python\tensorflow>pip3 install html5lib-0.9999999.tar.gz
Processing d:\python\tensorflow\html5lib-0.9999999.tar.gz
Requirement already satisfied: six in c:\python36\lib\site-packages (from html5l
ib==0.9999999)
Building wheels for collected packages: html5lib
  Running setup.py bdist_wheel for html5lib ... done
  Stored in directory: C:\Users\cht\AppData\Local\pip\Cache\wheels\c7\97\52\e819
f90e3405b8364664de7d3da830ea032434cf57eb9975f1
Successfully built html5lib
Installing collected packages: html5lib
Successfully installed html5lib-0.9999999

D:\Python\tensorflow>pip3 install bleach-1.5.0-py2.py3-none-any.whl
Processing d:\python\tensorflow\bleach-1.5.0-py2.py3-none-any.whl
Requirement already satisfied: six in c:\python36\lib\site-packages (from bleach
==1.5.0)
Requirement already satisfied: html5lib!=0.9999,!=0.99999,<0.99999999,>=0.999 in
 c:\python36\lib\site-packages (from bleach==1.5.0)
Installing collected packages: bleach
Successfully installed bleach-1.5.0

D:\Python\tensorflow>pip3 install Markdown-2.6.11-py2.py3-none-any.whl
Processing d:\python\tensorflow\markdown-2.6.11-py2.py3-none-any.whl
Installing collected packages: Markdown
Successfully installed Markdown-2.6.11

D:\Python\tensorflow>pip3 install Werkzeug-0.14.1-py2.py3-none-any.whl
Processing d:\python\tensorflow\werkzeug-0.14.1-py2.py3-none-any.whl
Installing collected packages: Werkzeug
Successfully installed Werkzeug-0.14.1

D:\Python\tensorflow>pip3 install tensorflow_tensorboard-1.5.1-py3-none-any.whl
Processing d:\python\tensorflow\tensorflow_tensorboard-1.5.1-py3-none-any.whl
Requirement already satisfied: six>=1.10.0 in c:\python36\lib\site-packages (fro
m tensorflow-tensorboard==1.5.1)
Requirement already satisfied: werkzeug>=0.11.10 in c:\python36\lib\site-package
s (from tensorflow-tensorboard==1.5.1)
Requirement already satisfied: wheel>=0.26; python_version >= "3" in c:\python36
\lib\site-packages (from tensorflow-tensorboard==1.5.1)
Requirement already satisfied: html5lib==0.9999999 in c:\python36\lib\site-packa
ges (from tensorflow-tensorboard==1.5.1)
Requirement already satisfied: bleach==1.5.0 in c:\python36\lib\site-packages (f
rom tensorflow-tensorboard==1.5.1)
Requirement already satisfied: protobuf>=3.4.0 in c:\python36\lib\site-packages
(from tensorflow-tensorboard==1.5.1)
Requirement already satisfied: numpy>=1.12.0 in c:\python36\lib\site-packages (f
rom tensorflow-tensorboard==1.5.1)
Requirement already satisfied: markdown>=2.6.8 in c:\python36\lib\site-packages
(from tensorflow-tensorboard==1.5.1)
Requirement already satisfied: setuptools in c:\python36\lib\site-packages (from
 protobuf>=3.4.0->tensorflow-tensorboard==1.5.1)
Installing collected packages: tensorflow-tensorboard
Successfully installed tensorflow-tensorboard-1.5.1

D:\Python\tensorflow>pip3 install tensorflow-1.5.0-cp36-cp36m-win_amd64.whl
Processing d:\python\tensorflow\tensorflow-1.5.0-cp36-cp36m-win_amd64.whl
Requirement already satisfied: protobuf>=3.4.0 in c:\python36\lib\site-packages
(from tensorflow==1.5.0)
Requirement already satisfied: wheel>=0.26 in c:\python36\lib\site-packages (fro
m tensorflow==1.5.0)
Requirement already satisfied: absl-py>=0.1.6 in c:\python36\lib\site-packages (
from tensorflow==1.5.0)
Requirement already satisfied: tensorflow-tensorboard<1.6.0,>=1.5.0 in c:\python
36\lib\site-packages (from tensorflow==1.5.0)
Requirement already satisfied: numpy>=1.12.1 in c:\python36\lib\site-packages (f
rom tensorflow==1.5.0)
Requirement already satisfied: six>=1.10.0 in c:\python36\lib\site-packages (fro
m tensorflow==1.5.0)
Requirement already satisfied: setuptools in c:\python36\lib\site-packages (from
 protobuf>=3.4.0->tensorflow==1.5.0)
Requirement already satisfied: bleach==1.5.0 in c:\python36\lib\site-packages (f
rom tensorflow-tensorboard<1.6.0,>=1.5.0->tensorflow==1.5.0)
Requirement already satisfied: werkzeug>=0.11.10 in c:\python36\lib\site-package
s (from tensorflow-tensorboard<1.6.0,>=1.5.0->tensorflow==1.5.0)
Requirement already satisfied: html5lib==0.9999999 in c:\python36\lib\site-packa
ges (from tensorflow-tensorboard<1.6.0,>=1.5.0->tensorflow==1.5.0)
Requirement already satisfied: markdown>=2.6.8 in c:\python36\lib\site-packages
(from tensorflow-tensorboard<1.6.0,>=1.5.0->tensorflow==1.5.0)
Installing collected packages: tensorflow
Successfully installed tensorflow-1.5.0


接下來是可以安裝 Keras 框架.


二. 安裝 Keras (上層) : 

Keras 是 Python 深度學習的一種上層框架 (模型層 model level) , 只負責機器學習模型之建立, 訓練, 與預測, 其底層的張量 (矩陣) 運算是依賴後端引擎 (backend engine) 來支援. 目前 Keras 提供兩種後端引擎 : Theano 與 TensorFlow, 後者具有跨平台與高效能之優點. 參考 :

https://keras.io

Keras 字源來自希臘語, 原意為 horn (角), 最早出現於史詩奧德賽 Odyssey 中, 參考 :

https://keras.io/#why-this-name-keras

Keras 的原始作者是 Francois Chollet, 他也是 Manning 出版的 "Deep Learning with Python" 一書的作者. Keras 早期版本於 2015 年三月底釋出, 經過社群力量改進, 目前最新版本是 2.1.4. Keras 於 2017 年被 Google TensorFlow 團隊相中納入核心函式庫; 微軟的 CNTK 也在其 2.0 版支援 Keras 為上層 ML 抽象框架, 這使得 Keras 使用者在 2017 年底突破 20 萬, 參考 :

https://en.wikipedia.org/wiki/Keras


Source : Amazon


使用 pip3 安裝 keras 並將執行結果導至 keras.txt 檔案中 :

D:\> pip3 install keras > keras.txt   

Collecting keras
  Downloading Keras-2.1.4-py2.py3-none-any.whl (322kB)
Requirement already satisfied: scipy>=0.14 in c:\python36\lib\site-packages (from keras)
Requirement already satisfied: six>=1.9.0 in c:\python36\lib\site-packages (from keras)
Collecting pyyaml (from keras)
  Downloading PyYAML-3.12.tar.gz (253kB)
Requirement already satisfied: numpy>=1.9.1 in c:\python36\lib\site-packages (from keras)
Building wheels for collected packages: pyyaml
  Running setup.py bdist_wheel for pyyaml: started
  Running setup.py bdist_wheel for pyyaml: finished with status 'done'
  Stored in directory: C:\Users\user\AppData\Local\pip\Cache\wheels\2c\f7\79\13f3a12cd723892437c0cfbde1230ab4d82947ff7b3839a4fc
Successfully built pyyaml
Installing collected packages: pyyaml, keras
Successfully installed keras-2.1.4 pyyaml-3.12

如果因防火牆無法直接用 pip3 安裝, 參考上面安裝過程, Keras 只有一個相依套件 PyYAML, 先下載安裝 PyYAML 再安裝 Keras :

https://pypi.python.org/pypi/PyYAML
https://pypi.python.org/pypi/Keras

手動安裝過程如下 :

D:\Python\tensorflow>pip3 install PyYAML-3.12.tar.gz
Processing d:\python\tensorflow\pyyaml-3.12.tar.gz
Building wheels for collected packages: PyYAML
  Running setup.py bdist_wheel for PyYAML ... done
  Stored in directory: C:\Users\cht\AppData\Local\pip\Cache\wheels\7b\34\c5\bf29
ad6ffcf25face23150f29caabc7c8bde70e0bb921b325a
Successfully built PyYAML
Installing collected packages: PyYAML
Successfully installed PyYAML-3.12

D:\Python\tensorflow>pip3 install Keras-2.1.4-py2.py3-none-any.whl
Processing d:\python\tensorflow\keras-2.1.4-py2.py3-none-any.whl
Requirement already satisfied: numpy>=1.9.1 in c:\python36\lib\site-packages (fr
om Keras==2.1.4)
Requirement already satisfied: scipy>=0.14 in c:\python36\lib\site-packages (fro
m Keras==2.1.4)
Requirement already satisfied: pyyaml in c:\python36\lib\site-packages (from Ker
as==2.1.4)
Requirement already satisfied: six>=1.9.0 in c:\python36\lib\site-packages (from
 Keras==2.1.4)
Installing collected packages: Keras
Successfully installed Keras-2.1.4


安裝完成後, 進入 Python IDLE 匯入 keras 套件並檢視其版本 :

>>> import keras
Using TensorFlow backend.
>>> keras.__version__       #檢視 keras 版本
'2.1.4'

匯入套件時會顯示 "Using TensorFlow backend", 表示 Keras 預設以 TensorFlow 作為後端 (即底層) 深度學習引擎進行張量 (矩陣) 運算, 而這本書就是以 TensorFlow 為後端.

完成 TensorFlow + Keras 框架安裝後, 接下來就可以按圖索驥, 開始 ML 的實驗了.

參考 :

Windows 安裝 Tensorflow
如何在Windows上安裝Keras、Theano、Tensorflow,並將Keras的後端由Theano切換為Tensorflow

2018-02-25 補充 :

晚上在高雄的電腦上安裝 Python 32 位元版本 (因系統回復更新), 結果無法安裝 TensorFlow (找不到符合之版本) :

D:\>pip3 install --upgrade tensorflow > tensorflow.txt 
  Could not find a version that satisfies the requirement tensorflow (from versions: )
No matching distribution found for tensorflow
D:\>python
Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:04:45) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.

回頭看 TensorFlow 官網說明, 原來需安裝 Python 64 位元版本. 已移除 32 位元版本改安裝 64 位元版本.

2018-02-26 補充 :

今天翻到第六章開始測試 MNIST 資料集, 但自 Keras 匯入 np_utils 模組時出現錯誤 :

Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)]
 on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> import pandas as pd 
>>> from keras.utils import np_utils 
Using TensorFlow backend.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python36\lib\site-packages\keras\__init__.py", line 3, in <module>
    from . import utils
  File "C:\Python36\lib\site-packages\keras\utils\__init__.py", line 25, in <mod
ule>
    from .training_utils import multi_gpu_model
  File "C:\Python36\lib\site-packages\keras\utils\training_utils.py", line 7, in
 <module>
    from ..layers.merge import concatenate
  File "C:\Python36\lib\site-packages\keras\layers\__init__.py", line 4, in <mod
ule>
    from ..engine import Layer
  File "C:\Python36\lib\site-packages\keras\engine\__init__.py", line 8, in <mod
ule>
    from .training import Model
  File "C:\Python36\lib\site-packages\keras\engine\training.py", line 11, in <mo
dule>
    from scipy.sparse import issparse
  File "C:\Python36\lib\site-packages\scipy\__init__.py", line 61, in <module>
    from numpy._distributor_init import NUMPY_MKL  # requires numpy+mkl
ImportError: cannot import name 'NUMPY_MKL'

原來光是安裝 Numpy 還不夠, Keras 還用到了 Intel 的 MKL 數學函式庫, 我在以前安裝 ML 套件時就遇到過此問題, 參考 :

在 Windows 中安裝 Python 機器學習套件

Numpy + MKL 套件可在下列網址下載 :

https://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy




然後以系統管理員身分開啟命令提示字元視窗以 pip3 指令安裝 Numpy + MKL :

D:\>pip3 install numpy-1.14.1+mkl-cp36-cp36m-win_amd64.whl

注意, 若不是以系統管理員身分開啟命令提示字元視窗, 可能會出現如下存取權限被拒問題 :

PermissionError: [WinError 5] 存取被拒。: 'C:\\Users\\tony\\AppData\\Local\\Temp\
\pip-o1p89kef-uninstall\\python36\\lib\\site-packages\\numpy\\.libs\\libopenblas
.bnvrk7633hsx7yvo2tadgr4a5kekxjaw.gfortran-win_amd64.dll'

安裝完畢後就可以順利匯入 np_utils 模組了 :

D:\Python\tensorflow>python
Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)]
 on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> import pandas as pd 
>>> from keras.utils import np_utils   
Using TensorFlow backend
>>>

可見 keras 已可正常匯入, 並以 TensorFlow 為後端運算引擎.

註 : 後來發現其實這是 Python 3.6.1 版才會有此問題, 用最新的 3.6.4 版就不會.


2018-02-28 補充 :

高雄家中的電腦還原更新後重新安裝 Python 時沒注意到官網預設是下載 32-bit 版的, 結果到安裝 TensorFlow 時出現 "找不到符合之版本" 訊息, 仔細閱讀 TensorFlow 官網說明才知道必須安裝 Python 64-bit 版才行, 於是刪除 32-bit 版重新安裝 64-bit 版後安裝 TensorFlow 與 Keras 都沒問題了, 但是在匯入 keras 時卻出現了下面 "cannot import name '_ccallback_c'" 錯誤訊息 :

C:\Users\Tony>python
Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:54:40) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import keras
Using TensorFlow backend.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python36\lib\site-packages\keras\__init__.py", line 3, in <module>
    from . import utils
  File "C:\Python36\lib\site-packages\keras\utils\__init__.py", line 25, in <module>
    from .training_utils import multi_gpu_model
  File "C:\Python36\lib\site-packages\keras\utils\training_utils.py", line 7, in <module>
    from ..layers.merge import concatenate
  File "C:\Python36\lib\site-packages\keras\layers\__init__.py", line 4, in <module>
    from ..engine import Layer
  File "C:\Python36\lib\site-packages\keras\engine\__init__.py", line 8, in <module>
    from .training import Model
  File "C:\Python36\lib\site-packages\keras\engine\training.py", line 11, in <module>
    from scipy.sparse import issparse
  File "C:\Python36\lib\site-packages\scipy\__init__.py", line 118, in <module>
    from scipy._lib._ccallback import LowLevelCallable
  File "C:\Python36\lib\site-packages\scipy\_lib\_ccallback.py", line 1, in <module>
    from . import _ccallback_c
ImportError: cannot import name '_ccallback_c' 
>>>

來回檢查 Numpy, Scipy, TemsorFlow, Keras 都是最新版, 怎會出問題? 難道是之前的 Python 32-bit 版殘餘勢力作祟? 因為在刪除 32-bit 版後我有注意到原安裝目錄 C:\Python36 仍然存在, 當時想應該沒關係吧! 真的, 沒關係就是有關係, 無計可施之餘只好刪除已安裝的 Python 64-bit, 然後將安裝目錄 C:\Python36 也全部刪除乾淨後再重新安裝 Python 64-bit, Scipy, matplotlib, pandas, TensorFlow, 與 Keras, 結果 OK!

結論 : 刪除舊版 Python 時一定要將原安裝目錄刪除掉. 剪不斷理還亂!

2018 年第 8 周記事

本周前半段是年假, 週三開工後只上三天班又放假了, 感覺過得很快哩! 本想周四晚上與大帥聚聚, 但因週四晚上還在公司忙無法聚會, 今早 Line 他原來正要去搭機返廈門, 下次回台是五月中了.

年前接到小舅子 Line, 問我放在鄉下的 Wii 還能用嗎? 雖然已經很久沒玩了, 但去年曾開機檢查沒問題, 他說文文想要玩, 所以年初三我將主機稍微整理開機, 發現主機沒問題, 但遙控器有一支沒過電, 換新電池也不行, 可能內部故障. 這是最早出來的 Wii, 是小舅子的小舅子 (很複雜) 剛去聯發科任職的公司年終禮物, 日本原裝的, 因那時安安還太小不會玩, 小舅子就拿來給小狐狸他們玩, 大概是二哥小二時候吧! 同學老張也有 Wii, 他有非常多遊戲, 為此我還去買了一顆 2.5 吋硬碟來灌頂, 其中他們最愛玩太鼓達人了. 但後來我的 iPad 上有憤怒鳥之後, 漸漸地 Wii 就被晾在一邊了.

過年後辦公室第一件喜事是我的工作搭檔升官 (晉升為工程師), 我為她感到高興, 也因此被連請了兩天便當外加一個下午茶. Something new is good!

週六早上我又去義大看高樹阿姨, 傷口已拆線, 排尿量有增加, 右腳浮腫情形有改善, 看來精神有轉好. 希望阿姨病況繼續好轉, 就算打個五五波, 只要能恢復自主呼吸, 其他就好辦.

週六下午載姊姊去高鐵站坐車回台北, 下周大學要開學了. 過年期間她上網取消了蒙古文選修, 因為去台大上完蒙文課又要趕回師大上主修課會遲到. 我也覺得還是修實用的日文好. 不過這年頭還有人對蒙文與俄文有興趣還真少見, 姊姊對西里耳字母的語言似乎很有興趣.

購買久雄多功能隨身蒸氣電鍋

年初一晚上小舅來訪時, 談到我每周幫爸滷菜雖然方便, 但他覺得菜冷凍太多天不好, 應該吃新鮮烹煮的才營養. 他建議準備食材分裝好, 要吃的時候再煮. 之前幫爸買的大同無水料理鍋他似乎還是覺得操作麻煩, 所以我到露天尋找方便的鍋具時, 找到這款電蒸鍋, 只要單鍵操作即可烹煮, 可說是方便的一人電鍋 :

# 露天 : 九陽迷你電蒸鍋 $450

這種迷你電蒸鍋廠家有好幾個, 我最先找到的是久雄 (台灣製) 這款 :

久雄多功能隨身蒸氣電鍋久熊 智慧型多功能烹煮鍋 / 蒸氣電鍋 台灣製隨身小電鍋 $599

賣家在高雄大順路與建工街交叉路口附近 (灣中街), 自取也很方便, 但看到久陽比較便宜, 就改買九陽的. 久雄的 Youtube 有介紹影片, 看來功能應該差不多 :







三洋電熱蒸氣飯盒

2018年2月23日 星期五

北本先生

昨天吃早餐時看台視的蠟筆小新, 其中一集是關於隔壁大嬸的先生, 小新一家都很好奇這個從未出現的人到底長相如何? 但幾次窺伺都被送貨的白馬宅配送貨員遮住了, 只知道隔壁大嬸的先生姓北本.




查 Google 發現網路上早就有小新迷寫過這個問題了, 參見 :

蜡笔小新隔壁大婶的老公现身了啊啊啊!

甚至有人猜測隔壁大嬸的先生可能是情報員, 喜歡三姑六婆說三道四的大嬸搞不好是他的耳目哩! 參考 :

蠟筆小新里的八大未解之謎

2018年2月22日 星期四

去看高樹阿姨

因為今天要下午才進辦公室, 所以早上開車經國十下燕巢交流道去義大看在外科加護病房的高樹阿姨. 今天她的幾個女兒與孫女都來了, 因為要跟醫生討論後續處理方式. 醫生看到我是一群女生裡面唯一的男生, 可能以為我是阿姨的兒子, 問我是阿姨的甚麼人? 我說我媽跟阿姨情同姊妹!

醫生說了半天, 阿姨的女兒們實在不知如何告訴她們的母親, 腫瘤已經很大無法處理, 如果感到痛苦要拿掉呼吸器? 她們說不出來. 之前都一直鼓勵阿姨要加油, 這回卻要告訴她情況如此, 這 ... 實在太殘忍了. 最後醫生帶大家進去技巧性地詢問阿姨帶呼吸器是否不舒服, 有想要拿下來嗎? 結果她搖搖頭.

其實阿姨意識清楚, 可點頭搖頭表達是或否, 求生意志看來很強. 因為加護病房已住一個月, 預後似乎非常不好, 醫生建議家屬與阿姨談一下病情, 詢問病人意願, 看看接下來程序要如何走 : 拿掉呼吸器? 還是找安寧病房或外面療護機構?

走出醫院看到外面藍藍的天空, 心情卻盪到谷底. 想到講話鏗鏘有力的阿姨如今困在那擺滿儀器的斗室中與病魔奮戰, 我希望她能戰勝, 今年端午節還是能吃到她裹的超好吃粽子.

2018年2月21日 星期三

幾本物聯網與機器學習原文好書

最近在亞馬遜找到幾本非常棒的書如下 :
  1.  Algorithms For Dummies
    此書以 Python 介紹演算法
  2. Arduino Building exciting LED based projects and espionage devices
    介紹家居自動化, 機器狗, 雲端監視系統等 DIY 專案
  3. Arduino Interrupts Speed up your Arduino to be responsive to events
    探討 Arduino 中斷之妙用
  4. Bash Cookbook
    Linux Bash Shell 好書
  5. Beginning Artificial Intelligence with the Raspberry Pi (Good)
    使用樹莓派與 Python 實作 AI 機器學習
  6. Best Raspberry PI Zero Project For Home Automation
    樹莓派 Zero 用於空拍機飛控
  7. Building Smart Homes with Raspberry Pi Zero
    使用 Pi Zero 建構智慧居家 
  8. Building a Quadcopter with Arduino
    使用 Arduino 建構四旋翼機
  9. Building Blockchain Projects
如果有中文譯本是最好  (簡繁均可) , 閱讀速度快; 沒有也 OK, 畢竟等翻譯可能要一年以上. 還不如直接看原文. 這裡面物聯網的東西比較好玩, 學習 ML 只是想讓物聯網更好玩而已. 

2018年2月20日 星期二

20W 太陽能板短路測試

去年買了一塊 20W 太陽能板想要用來給小型抽水機用, 但一直沒時間動手測試. 上個月去上過職業工會辦的太陽能訓練班, 才了解原來太陽能板是電流源, 不是電壓源, 所以可以直接短路量測其短路電流.

年初三下午 13:30 烈陽正熾, 我將板子拿出來用三用電表量短路電流, 測得約 1.01A :




背後銘牌顯示短路電流應該是 1.25A, 可能是要正午 12 點測量比較準 :




希望今年能抽空把菜園灑水工程完成.

2018 年第 7 周記事

今天是年初五, 2018 的農曆年就這樣過去, 明天又要開始工作了, 我是蠻期待的, 因為 SOP 撰寫越來越順手, 雖然很多不是屬於我的工作最後都交到我手上, 但越忙越有價值, 越閃躲越無趣. 不過, 並不是每個人都像我一樣樂在工作, 研究所同學在 Line 群組貼了這張圖 :




哇咧, 有這麼嚴重嗎? 同學回覆 : "非常可怕". 沒想到國高中老師是最不樂在工作的一群! 難怪教育一直辦不好. 如何讓老師樂在工作, 大概是教育改革最被忽視的一環. 沒有快樂的老師, 怎會有甚麼教育熱情呢?

當然還有一種可能是老師本身的選擇問題, 可能只是覺得工作穩定又有月退而選擇當老師, 但實際執教後發現志趣不合又沒勇氣另謀出路, 只好將就將就, 於是人生最精華部分就在這種將就中度過, 自己的潛能也就此埋沒, 實在可惜. 如何將對的人將來能放到對的的位子上讓其發光發熱, 這是教育最重要的意義.

春節前帶了一堆書回鄉下準備好好來 K, 但實際完成的不多. 年初一早上台北的小阿姨與阿龍, 還有小芸表妹帶著她小女兒回鄉, 初二初三陪他們去附近走走蠻開心的, 我們三個表兄妹從來沒這樣一起出去過哩. 下次要先規劃好行程才能將時間充分利用. 明年小阿姨若有回來我打算初三去美綠訂一桌請三個阿姨還有小舅他們, 估計約 10 人一桌即可.

不過今年過年有一件事不開心, 除夕下午拜完祖先, 帶了一箱水果邀菁菁一起去母親的好友高樹阿姨家送禮, 因已好久沒去了, 有點忘記路怎麼走, 打電話去問, 阿姨的媳婦告訴我要往建興方向才對. 但到阿姨家沒看到人, 她媳婦才說阿姨住院了, 而且是腎臟母細胞癌末期在加護病房靠呼吸器維持生命, 哇, 怎會如此嚴重? 端午節才包了兩大串粽子給我們不是嗎? 明日早上須請個假去義大看望. 

人生的變化總是來得太突然, 而我們總是太忙而疏於聯絡.

2018年2月19日 星期一

Python 學習筆記 : 檔案與目錄處理

前陣子在河堤新書展示櫃看到下面這本碁峰出的 "Python 初學特訓班 (增訂版)", 翻閱發現此書除了前面是適合初學者的 Python ABC 之外, 還包括了許多功能與實用技巧的介紹, 例如網路爬蟲, Matplotlib 圖表繪製, Facebook 貼文與照片下載, Youtube 影片下載, 甚至 OpenCV 臉部辨識 ... 等等, 可以說 Python 的重要應用都含括進來了, 真是一本初學加應用的好書.


Source : 金石堂


另外一本去年買的 "Python 程式設計實務 (博碩, 何敏煌)" 也是類似基礎 + 應用的好書 :


Source : 金石堂


還有還參考了一本借自母校高科大的 "精通 Python" :


Source : 金石堂


今年一定要攻克 Python 這關, 掃除進取機器學習的障礙. 雖然之前在研究 MicroPython on ESP8266 時已經對 Python 基礎做過大致整理, 但畢竟 MicroPython 只是 Python 3 的精簡版, 特別是檔案處理部分不過應景而已, 與樹莓派上的全功能 Python 有不小差距.

那就從 Python 檔案處理著手測試吧! Python 提供下列套件來操作檔案與目錄 :


 檔案處理套件 說明
 os 建立或刪除目錄, 刪除檔案, 執行作業系統命令
 os.path 處理檔案路徑與名稱, 檢查檔案或路徑是否存在, 計算檔案大小
 os.walk 搜尋指定目錄與其子目錄, 以遞迴方式取得目錄中所有檔案與下一層目錄
 shutil 可複製, 移動, 刪除檔案與目錄之跨平台套件
 glob 支援以萬用字元 * 取得指定條件之檔案串列


一. 用 os.path 套件取得檔案與目錄資訊 :

os.path 套件提供下列方法從作業系統取得檔案或目錄資訊, 使用前須用 import os.path 匯入 :

import os.path

其方法摘要如下表 :


 os.path 套件方法 說明
 abspath(x) 傳回指定之檔案或目錄 x 之絕對路徑名稱
 basename(x) 傳回路徑名稱 x 的最後一個名稱 (檔案或目錄)
 dirname(x) 傳回路徑名稱 x 的上層完整路徑名稱
 getsize(x) 傳回指定檔案 x 的大小 (byte)
 split(x) 將絕對路徑 x 中的檔案與上層目錄分開後以 tuple 傳回 (可取出檔名)
 splitdrive(x) 將絕對路徑 x 中的磁碟機與上層目錄分開後以 tuple 傳回 (可取出磁碟機)
 join(x, y) 將路徑 x 與檔案名稱 y 結合成完整絕對路徑後傳回
 exists(x) 檢查指定之目錄或檔案 x 是否存在
 isabs(x) 檢查指定之路徑 x 是否為完整之絕對路徑名稱
 isfile(x) 檢查指定之路徑 x 是否為檔案
 isdir(x) 檢查指定之路徑 x 是否為目錄


方法 abspath() 會傳回指定檔案或目錄之絕對路徑, 而 isabs() 則用來檢查傳入之路徑是否為絕對路徑, 例如我在 D 碟下有一個 test 目錄與一個 main.py 檔案, 而 test 下又有一個 test 目錄 :

D:\test
    |---- test\
    |---- main.py

D:\test>python
Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os.path
>>> abs=os.path.abspath("main.py")   #傳回絕對路徑字串
>>> abs
'D:\\test\\main.py'
>>> os.path.isabs(abs)                           #檢查是否為絕對路徑 (是)
True
>>> os.path.isabs("main.py")                 #檢查是否為絕對路徑 (否)
False

在樹莓派的 pi 使用者目錄下有一個 lastip.txt 檔案與 test 目錄, test 目錄下又還有一個 test 目錄, 例如 :

/home/pi
     |-----laspip.txt
     |-----test
               |----test

pi@raspberrypi:~ $ python3
Python 3.4.2 (default, Oct 19 2014, 13:31:11)
[GCC 4.9.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os.path
>>> abs=os.path.abspath("lastip.txt")
>>> abs
'/home/pi/lastip.txt'
>>> os.path.isabs(abs)
True
>>> os.path.isabs("lastip.txt")
False

方法 basename() 會傳回一個絕對路徑中的最後名稱 (即檔案或目錄名稱), 而方法 dirname() 則是傳回一個絕對路徑中的上層目錄路徑 (即父目錄路徑), 方法 isfile() 與 isdir() 分別檢查傳入之路徑為檔案還是目錄, 例如 :

>>> import os.path
>>> abs=os.path.abspath("main.py")
>>> abs
'D:\\test\\main.py'
>>> file=os.path.basename(abs)    #傳回檔案或目錄之絕對路徑
>>> file
'main.py'
>>> os.path.isfile(file)                   #檢查是否為檔案 (是)
True
>>> os.path.isdir(file)                    #檢查是否為目錄 (否)
False
>>> dir=os.path.dirname(abs)        #傳回上層目錄路徑
>>> dir
'D:\\test'
>>> abs=os.path.abspath("test")     #傳回檔案或目錄之絕對路徑
>>> abs
'D:\\test\\test'
>>> dir=os.path.dirname(abs)         #傳回上層目錄路徑
>>> dir
'D:\\test'
>>> os.path.isdir(dir)                       #檢查是否為目錄 (是)
True

在樹莓派的 Raspbian 測試結果如下 :

>>> import os.path
>>> abs=os.path.abspath("lastip.txt")
>>> abs
'/home/pi/lastip.txt'
>>> file=os.path.basename(abs)
>>> file
'lastip.txt'
>>> os.path.isfile(file)
True
>>> os.path.isdir(file)
False
>>> dir=os.path.dirname(abs)
>>> dir
'/home/pi'
>>> abs=os.path.abspath("test")
>>> abs
'/home/pi/test'
>>> dir=os.path.dirname(abs)         #上一層目錄路徑
>>> dir
'/home/pi'
>>> os.path.isdir(dir)
True
>>> os.path.isfile(dir)
False

目前目錄 "." 與上一層目錄 ".." 也可以用 isdir() 檢測, 在 Windows 與 Linux 用法相同, 例如 :

>>> os.path.isdir(".")
True
>>> os.path.isdir("..")
True
>>> os.path.isfile(".")
False
>>> os.path.isfile("..")
False

方法 splitdrive() 會將傳入之絕對路徑拆成磁碟機與路徑, 傳回此兩字串組成之 tuple; 方法 join() 則可將這兩部分組合成絕對路徑, 例如在 Windows 下測試 :

>>> abs=os.path.abspath("main.py")          #傳回絕對路徑字串
>>> drive, path=os.path.splitdrive(abs)    #將絕對路徑拆成磁碟機與路徑
>>> drive
'D:'
>>> path
'\\test\\main.py'
>>> os.path.join(drive, path)      #將磁碟機與路徑組合成絕對路徑
'D:\\test\\main.py'

樹莓派的測試結果 :

>>> import os.path
>>> abs=os.path.abspath("lastip.txt")
>>> abs
'/home/pi/lastip.txt'
>>> drive, path=os.path.splitdrive(abs)
>>> drive         
''                                 #Linux 磁碟機為空字串
>>> path
'/home/pi/lastip.txt'

可見在 Linux 系統裡, splidrive() 傳回的磁碟機是空字串, 書中範例是 MacOS 結果一樣.

還有一個在檔案目錄處理最常用的 exists(), 此方法用來檢測傳入之檔案或目錄是否存在, 傳入參數可以是檔案或目錄名稱, 也可以是絕對路徑, 當傳入參數為檔案或目錄名稱時, 表示此為目前目錄下之檔案或子目錄. 例如 :

>>> import os.path
>>> os.path.exists("main.py")     #目前目錄下有 main.py 故傳回 True
True
>>> os.path.exists("xyz.py")        #目前目錄下沒有 xyz.py 故傳回 False
False
>>> abs=os.path.abspath("main.py")
>>> os.path.exists(abs)                 #傳入檔案絕對路徑
True


二. 用 os 套件操作檔案與目錄  :

os 套件中有下列方法可用來建立或刪除目錄, 刪除檔案, 以及執行作業系統命令 (不能建立檔案), 使用前須先用 import os 匯入 :


 os 套件方法 說明
 listdir(d)  顯示目錄 d 底下的檔案與子目錄
 mkdir(d) 建立目錄 d, 須搭配 os.path.exists() 檢查目錄是否存在以免產生執行錯誤
 rmdir(d) 刪除目錄 d, 須搭配 os.path.exists() 檢查目錄是否存在以免產生執行錯誤
 chdir(d) 切換工作目錄至目錄 d
 getcwd() 傳回目前的工作目錄
 remove(f) 刪除檔案 f, 須搭配 os.path.exists() 檢查檔案是否存在以免產生執行錯誤
 rename(old, new) 將舊目錄或檔案名稱 old 改成新目錄或檔案名稱
 system(c) 執行作業系統命令 c


注意, 不論是建立或刪除目錄, 刪除檔案都應先以 os.path.exists() 方法檢查目錄或檔案是否已存在以避免產生執行錯誤, 例如下列指令會在目前目錄 D:\test 下建立 kkk 子目錄 :

>>> import os
>>> os.mkdir("kkk")

這時若再執行一次 os.mkdir("kkk") 指令就會出現錯誤, 因為 kkk 子目錄已經存在 :

>>> os.mkdir("kkk")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileExistsError: [WinError 183] 當檔案已存在時,無法建立該檔案。: 'kkk'

正確方式為先用 os.path.exists() 方法檢查目錄是否已存在 :

>>> import os
>>> dir="kkk"
>>> if not os.path.exists(dir):
...     os.mkdir(dir)
... else:
...     print(dir + "已經建立")
...
kkk已經建立

刪除目錄時也是一樣要先檢查是否已存在, 例如 :

>>> import os
>>> dir="kkk"
>>> if os.path.exists(dir):
...     os.rmdir(dir)
...     print(dir + " 已刪除")
... else:
...     print(dir + " 不存在")
...
kkk 已刪除
>>> os.rmdir(dir)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [WinError 2] 系統找不到指定的檔案。: 'kkk'

可見刪除目錄後直接用 os.rmdir() 再刪除一次就會出現 FileNotFoundError 錯誤. 

同樣地, 刪除檔案時也要先檢查是否存在, 例如 :

>>> import os
>>> file="test.txt"
>>> if os.path.exists(file):
...     os.remove(file)
...     print(file + " 已刪除")
... else:
...     print(file + " 不存在")
...
test.txt 已刪除
>>> os.remove(file)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [WinError 2] 系統找不到指定的檔案。: 'test.txt'

可見成功刪除 test.txt 後直接用 os.remove() 再刪除一次就會出現 FileNotFoundError 錯誤. os 套件中沒有建立檔案的函數, 建立檔案使用 Python 內建函數 Open().

方法 os.rename() 可用來更改檔案或目錄名稱, 例如 :

>>> import os
>>> os.path.exists("test.txt")         #改名前 test.txt 存在
True
>>> os.path.exists("tt.txt")            #改名前 tt.txt 不存在
False
>>> os.rename("test.txt","tt.txt")   #將 test.txt 改名為 tt.txt
>>> os.path.exists("test.txt")          #改名後 test.txt 已不存在
False
>>> os.path.exists("tt.txt")             #改名後 tt.txt 存在
True

最後 os.system() 函數用來呼叫執行作業系統命令列指令, 例如在 Windows 系統中使用 os.system() 呼叫 mkdir 可建立目錄, 呼叫 cls 可清除螢幕等, 測試如下 :

>>> os.system("mkdir test")    #系統指令正常執行傳回 0
0
>>> os.system("clear")            #系統指令未正常執行傳回 1
'clear' 不是內部或外部命令、可執行的程式或批次檔。
1                       

傳入的系統指令若正確會在執行完畢後傳回 0, 否則傳回 1.


三. 用 shutil 處理檔案與目錄  :

shutil 套件為一跨平台檔案處理套件, 使用前需用 import shutil 匯入. 它提供如下之高階檔案與目錄處理方法 :

 shutil 套件方法 說明
 copyfile(s, d) 複製檔案 s 至檔案 d (僅內容, 不包括屬性)
 copy(s, d) 複製檔案 s 至檔案 d (包括權限屬性)
 copy2(s, d) 複製檔案 s 至檔案 d (包括全部屬性)
 copytree(s, d) 將目錄 s 以及其下所有檔案與子目錄複製到 d
 rmtree(d) 刪除目錄 d 以及其下所有檔案與子目錄
 move(s, d) 將目錄或檔案 s 搬移為 d

其中複製檔案有僅複製內容的 copyfile(); 有可複製權限之 copy(); 以及可複製全部屬性的 copy2(); 這三個檔案複製方法都會傳回目的檔案名稱, 例如 :

>>> import shutil
>>> shutil.copyfile("t111.txt", "u222.log")    #複製 t111.txt 內容為 u222.log
'u222.log'
>>> shutil.copy("t111.txt", "v333")               #複製 t111.txt 內容與權限屬性為 v333
'v333'
>>> shutil.copy2("t111.txt", "w444.txt")       #複製 t111.txt 內容與全部屬性為 w444.txt
'w444.txt'
>>> shutil.move("w444.txt", "w444")           #將 w444.txt 改為 w444
'w444'

為了測試 copytree() 與 rmtree() 方法, 先用 os.mkdir() 建立一個目錄 x555 :

>>> import os
>>> os.mkdir("x555")                            #建立空目錄 x555
>>> shutil.copytree("x555", "y666")     #複製為 y666, 傳回目的目錄 y666
'y666'
>>> shutil.rmtree("y666")                      #刪除目錄 y666


四. 用 glob.glob 處理檔案列表  :

glob 是一個外部套件, 其用途是取得指定路徑下的檔案列表 (注意, 只有檔案, 不包括目錄), 使用前先用 import glob 匯入, 然後呼叫 glob.glob(pathname) 方法, 傳入指定絕對或相對路徑 pathname 與檔案匹配規則, 會傳回一個符合該規則之檔案串列, 例如在 Windows 我的 D 碟 test 目錄下有如下的檔案與目錄 :

D:\test
    |---- kkk
              |----t111.txt
              |----u222.log
              |----v333

glob.glob() 可傳入目前目錄 D:\test 下的子目錄路徑, 例如 kkk, 但那樣只會傳回目錄 kkk 本身而已, 必須加上檔案匹配規則才會列出檔案, 匹配規則可以使用類似正規表示法中的 * 或 ? 等通配符號, * 表示任何數目之任何字元, 而 ? 表示單一字元. 也可以使用 [abc] 來表示含有 a, b, 或 c 字元之檔案名稱, 或者 [0-9], [a-z], [A-Z] 等表示含有數字或英文字母之檔名, 例如 :

>>> import glob
>>> glob.glob("kkk")                     #沒有檔案匹配規則, 只傳回 kkk 子目錄而已
['kkk']           
>>> glob.glob("kkk/*")                  #用 * 傳回 kkk 子目錄下全部檔案
['kkk\\t111.txt', 'kkk\\u222.log', 'kkk\\v333']
>>> glob.glob("kkk/*.*")               #用 *.* 只列出副檔名含有小數點者
['kkk\\t111.txt', 'kkk\\u222.log']
>>> glob.glob("kkk/*.l??")             #用 ? 只匹配單一字元
['kkk\\u222.log']
>>> glob.glob("kkk/t*")                       
['kkk\\t111.txt']

不過這些匹配方式只是 UNIX shell 的匹配規則而已, 並未支援完整的正規表示法.

以上範例目錄分隔符號使用的是右斜線, 而傳回之檔案串列中的路徑分隔符號則為兩個左斜線. 在 Windows 下 glob.glob() 之傳入參數也可以用左斜線, 但必須使用兩個, 否則會傳回空串列, 例如 :

>>> glob.glob("kkk\t*")                  #Windows 下使用單一左斜線會傳回空串列
[]
>>> glob.glob("kkk\\t*")                 #Windows 下須使用兩個左斜線     
['kkk\\t111.txt']

但在 Linux 中傳入之路徑分隔符號則一律是右斜線, 例如在樹莓派中我也建立與上面 Windows 一樣之檔案結構 :

/home/pi/test
    |---- kkk
              |----t111.txt
              |----u222.log
              |----v333

pi@raspberrypi:~/test $ python3
Python 3.4.2 (default, Oct 19 2014, 13:31:11)
[GCC 4.9.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import glob
>>> glob.glob("kkk")
['kkk']
>>> glob.glob("kkk/*.*")
['kkk/t111.txt', 'kkk/u222.log']
>>> glob.glob("kkk/*")
['kkk/t111.txt', 'kkk/v333', 'kkk/u222.log']
>>> glob.glob("kkk/*.l??")
['kkk/u222.log']
>>> glob.glob("kkk/t*")
['kkk/t111.txt']
>>> glob.glob("kkk\t*")       #Linux 中路徑分隔符不可用左斜線
[]
>>> glob.glob("kkk\\t*")      #Linux 中路徑分隔符不可用左斜線
[]

可見在 Linux 中傳回之檔案串列都是使用右斜線當路徑分隔符號.

除了使用相對路徑外, 也可以在 glob.glob() 中傳入絕對位址, 這須使用 os.path.abspath() 方法, 例如 :

>>> import os.path
>>> dir=os.path.abspath("kkk")    #傳回 kkk 子目錄絕對位址
>>> dir
'D:\\test\\kkk'
>>> glob.glob(dir)                         #沒有檔案匹配規則, 只傳回 kkk 子目錄而已
['D:\\test\\kkk']
>>> glob.glob("kkk/*")                 #相對位址
['kkk\\t111.txt', 'kkk\\t222.txt']
>>> glob.glob(dir + "/*")               #字串串接路徑與檔案匹配規則 (絕對位址)
['D:\\test\\kkk\\t111.txt', 'D:\\test\\kkk\\t222.txt']

可見, 若使用絕對位址, 則傳回值也是絕對位址.

參考 :

簡單掌握Python中glob模塊查找文件路徑的用法


五. 用 os.walk() 取得檔案目錄之樹狀結構  :

os.walk(p) 方法可以用來搜尋指定目錄, 傳入參數 p 為一個目錄之絕對路徑, 它會傳回一個具有三個元素之串列 [dir_name, subdir_name, files] :

dir_name : 目前目錄名稱

~待續