2022年3月31日 星期四

關於智慧手錶

小米手環我從 V2 戴到 V3, 整體感覺它續航力佳, 大約兩周才充一次電, 缺點是充電頭似乎常接觸不良, 常常要插拔好幾次才看到螢幕顯示電池充電中動畫. 今天在 YT 看到下面這個介紹小米運動型智慧手錶影片, 覺得其功能非常豐富, 特別是有 5ATM, 可戴著游泳與潛水 (50 米) 非常適合我每周游泳需要 (雖然戴著有度數的蛙鏡, 但在泳池要看牆上掛的時鐘還是不很清楚) : 





小米運動版智慧手錶官網價格是 $3295 元 :


此手錶最大特點是搭載 4 模 GPS 定位, 名符其實的運動版手錶. 另外一個介紹影片 :





另外一款還不錯的是 M85, 主要亮點是可以透過藍芽撥接電話, 來電一鍵接聽不須拿手機, 只是不 知音質如何, 音量是否可調? 此款無 GPS, 故運動紀錄需靠手機 App, 且因為有通話喇叭的關係只能生活防水 : 


2022-04-17 補充 : 

今天看到下面這篇文章 :


作者認為, 智慧手錶的功能只是輔助手機, 不需要買太好的 (太貴), 因為兩年後一定會有更好更省電的產品上市, 不要把智慧手錶當成可以完全取代手機的功能 (錶帶也是, 不需要買一堆錶帶), 只要具備如下條件即可 :
  • 防水或防潑水 (生活防水)
  • 待機時間要夠長 : 目前技術好像只能120小時左右 (五天), 電池容量也在300~380mAh之間
  • 藍芽通話 : 透過藍芽與手機連線後接打電話 : 開車, 騎車必備之功能
  • 內建喇叭 : 有些手錶要插耳機才能講電話, 這樣很不方便
  • 可與手機同步提醒訊息 (簡訊、Line…)
  • 繁體中文 : 沒中文很難摸索或操作
這樣來看似乎 M85 就符合這些條件, 價格在 1000 元以下算很親民, 內建喇叭可藍芽接打電話 (只限手機電話, Line 電話只有通知訊息, 不會顯示接電話按鈕), 3~6 天充電一次也還 OK, 還具備第三大項可有可無功能中的相機拍照控制與播放音樂等. 但作者仍勸人在智慧手錶續航力與使用介面還沒進化到很方便使用之前, 不要買智慧手錶, 更不要花大錢買貴的智慧手錶, 參考 :

# [3C]我把我的3支智慧手錶都賣人了

至於該文建議功能裡的可插 SIM 卡手機, 對岸牆國有不少這種產品, 但以給小孩用的為多.我找到一款 TCL MT43AX 的智慧手錶不僅可插 4G LTE SIM 卡直接當手機用, 還具有 GPS 追蹤以及跌倒通知功能, 適合給長輩使用, 價格約 4600 ~5000 左右 :


 它的電池是 600 MAH 的, 所以續航力應該有 1~2 週 (廠商回答約 1~2 天就要充電).  




這款手錶 PChome 與 momo 都有賣 :


遠傳有代理與門號資費方案, 參考 :


機器學習筆記 : 深度學習的 16 堂課 (六)

本篇繼續整理 "深度學習的16堂課" 這本書的讀後筆記, 本系列之前的文章參考 : 


以下是我讀第六章 "神經網路的基礎-人工神經元與激活函數" 的摘要筆記, 本章主要在解釋神經元構造與動作原裡, 以及常用的 sigmoid, softmax 等激活函數 :
  1. 美國神經生物學家 Frank Rosenblatt 於 1950 年代將自己對生物神經元的認識轉成感知器 (perceptron) 演算法, 這是最早的人工神經元. 他大部分的研究都是在任職於康乃爾航空實驗室時完成. 他打造的 Mark I 感知器是人工智慧的老祖宗. 
  2. 感知器的運作機制如下 : 
    (1). 接收其他神經元之輸入訊號
    (2). 計算各輸入作加權總合
    (3). 若加權總合超過閥值 (threshold) 就將訊號傳給其他神經元
    以數學表示 : z=xw+b 
    x=輸入向量, w=權重矩陣, b=偏值向量 (=閥值的負數), 建構神經網路的最重要任務是找出最佳的權重參數, 這必須透過訓練神經網路才能達到. 
  3. 感知器中超過閥值就輸出訊號的行為稱為激活函數 (activation function), 具體而言就是 step (步進) 函數, 除此外還有 sigmoid, tanh, ReLu, 與 softmax 等函數. 激活函數必須是非線性函數, 這樣才能增加神經元對非線性規則的學習能力. 
  4. Step 雖然是非線性激活函數, 但加權總合 z 不管多小, 只要超過 0 就輸出 1, 小於 0 就輸出 0, 在訓練神經網路時只要稍微調整 w 與 b 參數就會讓輸出在 0 與 1 之間來回變動, 使得感知器的輸出變化較極端, 這種情況可以用 sigmoid 激活函數來改善, 它是函數值介於 0~1 的平滑非線性函數 : sigmoid=1/(1 + exp(-z)), Python 程式碼如下 :

    from math import e
    def sigmoid(z):
        return 1/(1+e**-z)

    不過 sigmoid 有神經元飽和問題, 當 z 趨近 0 與 1 時, 調整 w 與 b 參數對輸出幾乎毫無影響, 神經元像是死掉了, 很難再訓練神經網路. 
  5. 激活函數 tanh 與 sigmoid 圖形很像, 都是非線性的平滑曲線 :
    tanh=(exp(z)-exp(-z))/(exp(z)+exp(-z))
    差別是 sigmoid 的輸出值在 0~1 之間, 而 tanh 的輸出值則在 -1 ~ 1 之間. 
  6. 激活函數 ReLu 事實上是由兩個線性函數組成的非線性函數 :
    在 z<=0 時一律輸出 0, z 為正值時輸出 z.
    許多深度神經網路的中間隱藏層大多使用 ReLu
  7. 在深度學習架構中, 激活函數的非線性性質非常重要, 正因為這些非線性的轉換與篩選, 才讓模型有逼近任何連續函數的能力. 
  8. 如何選擇激活函數 :
    (1). step 函數 :
    容易讓輸出值劇烈震盪, 不適合用在神經網路模型. 
    (2). sigmoid 函數 :
    加權總和較大正負值時容易飽和使訓練效率低下, 只適合用在二元分類的輸出層.
    (3). softmax 函數 :
    適用於多元分類.
    (4). tanh 函數 :
    比 sigmoid 訓練效率佳, 但普及程度不如 ReLu.
    (5). ReLu 函數 :
    首選, 可在最短時間訓練出優良的神經網路.
  9. 還有更多進階的激活函數, 例如 leaky ReLu, parametric ReLu 等, 參考 :
    http://keras.io/layers/advanced-activations
2022-04-05 補充 :

關於啟動 (激活) 函數我之前有寫過筆記, 參考 :


好站 : Lavochkin La-7 RC Plane DIY build (手作 RC 固定翼飛機)

今天在 YT 看到這個實作 RC 固定翼飛機的影片, 作者 (NumaVIG flights) 全程示範手作前蘇聯二戰時期的 La-7 戰鬥教練機, 工藝非常了得 (尤其是 31:50 製作機艙透明罩的手法真是厲害) : 





此款飛機是前蘇聯拉沃奇金設計局設計製造, 除了前蘇聯空軍使用外, 還賣到中國, 捷克, 北韓, 羅馬尼亞等國家, 參考 : 


此飛機的製作尺寸參考 : 


虛標瓦數的太陽能板

最近由於停電頻仍, 搭建小功率儲能型太陽能板的想法又浮現腦海, 這幾天在 Aliexpress 找到幾款號稱 300W~5000W 不等的太陽能板, 價格在 US$25~75 元之間, 誇張的是尺寸居然只有 40*30 cm 左右, 我原先以為這些中國製太陽能板這幾年有了技術突破, 可以將容量 100~300W 尺寸窗戶大 (約 150*100 cm) 的太陽能板縮小到一塊瓷磚大小, 不禁對牆國的技術感到萬般佩服 : 


Aliexpress 上還有非常多這類動輒標榜 300W 以上的太陽能板, 價格如此便宜, 讓我越看越興奮差點手殘買下去, 但仔細端詳這些商品規格, 內容與標題顯然有矛盾, 而且越看越奇怪, 這些能板的能量密度非常驚人, 例如上面第一款 U$25.22 那款, 尺寸是 43*20 cm, 面積是 0.086 平方米 (姑且當作整個都鋪滿 CELL), 標題毫不客氣標上 1000W 容量 : 




計算能量密度是 1000/0.086=11628 W/cm2, 亦即每平方米能發出 11KW ! 這不科學, 因為根據維基百科, 目前效能最高的太陽能板能量密度只有每平方米 175W, 參考 :

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




其實仔細看其規格就會發現這塊 43*20cm 的太陽能板實際功率只有 13W 而已 : 



網頁最底下也有很多人懷疑標題的瓦數不實, 具有誤導性 :




一般 100W 太陽能板大概都 2000 元上下, 且尺寸都像窗戶這麼大, 例如 :


我認為這些虛標的中國太陽能板商家可能會辯稱這 300W/1000W 指的是控制器的功率吧! 12V*30A=360W, 18V*60A=1080W. 我以前在 Aliexpress 買過很多電子零件與模組, 產品大致都還不錯, 但這回看到這些虛標的太陽能板實在讓人不敢苟同. 這些號稱 300W 的小太陽能板實際功率應該只有 15~30W, 戶外活動時拿來給手機充充電倒還可以. 

補充 : 

下面這家標 100W 雖然還是不太可能, 但至少沒這麼誇張 : 


工作電流 8A, 電壓 12V, 確實接近 100W, 但這麼小的板子能輸出 8A 嗎? 必須實測才知道. 

2022年3月30日 星期三

電池與逆變器功率計算

今天在尋找逆變器時在露天找到下面這個純正弦波逆變器 : 


此賣家品項眾多, 但評價數量卻很少, 難道是剛開業嗎? 我通常是找評價多且好的賣家較保險. 不過重點是它的說明資料非常豐富, 摘要整理如下 :

1. 為何應選純正弦波逆變器? 理由如下 :
  • 純正弦波逆變器有較強的負載能力, 對電器無害.
  • 修正正弦波驅動風扇會有吱吱聲, 轉得較慢, LED 燈會較暗.
2. 汽車電瓶與逆變器功率 :
  • 一般轎車電瓶 12V, 貨車 24V.
  • 功率 P=V*I, 12V 80AH 電瓶功率=12*80=960W, 乘以逆變器轉換效率 90% : 960*0.9=864W, 即此電瓶可用負載 864W. 
  • 電瓶工作時間=V*I*0.9*0.8/負載功率, 其中 0.9 為逆變器轉換效率, 0.8 為電池放電係數, 例如 12V 80AH 電瓶驅動 100W 燈泡之工作時間為 12*80*0.9*0.8/100=6.912, 近 7 小時.
3. 電動車的電瓶 :
  • 電壓有 48V 與 60V 兩種.
  • 容量有 12AH 與 20AH 兩種, 工作時間計算方式同上.
4. 感性負載 :
  • 馬達, 壓縮機, 電磁閥等內含線圈的元件稱為感性負載 (電壓超前電流), 其啟動電流是正常運轉時的 3~7 倍, 例如 150W 的冰箱啟動功率高達 1000W. 
  • 若有感性負載, 選擇逆變器時需以峰值功率為準. 一般逆變器所標功率是峰值功率, 正常持續輸出功率約為所標之一半. 
5. 連接逆變器與電瓶時, 應先接負極再接正接. 

2022年3月29日 星期二

機器學習筆記 : 深度學習的 16 堂課 (五)

本篇繼續整理 "深度學習的16堂課" 這本書的讀後筆記, 本系列之前的文章參考 : 


以下是我讀第五章 "先動手實作! 5 行程式體驗神經網路模型" 的摘要筆記與測試紀錄 (此書第一篇前四章是 ML 知識介紹, 本章開始才有程式碼實作, 第二篇 5~8 章介紹深度學習核心概念) :
  1. Tensorflow 2 開始將原本獨立的高階 API Keras 套件納入 Tensorflow 中, 成為 tf.Keras 子套件, 使建構神經網路的程式碼更加簡潔. 
  2. MNIST 是由 Yann LeCun, Corinna Cortes, 與微軟 AI 研究員 Burges 整理的手寫數字資料集, 含有 70000 張 28x28 解析度的手寫數字圖片, 其中 60000 張是訓練資料集 (training datatset), 10000 張是測試資料集 (test dataset). 
  3. 基本的淺層神經網路由輸入層, 隱藏層, 與輸出層構成, 以 MNIST 來訓練手寫數字圖片辨識模型來說, 輸入層需有 28x28=784 個神經元 (用來接收每張圖的 784 個像素), 輸出層需有 10 個神經元 (表示 0~9 數字的機率, 最高者為其預測結果), 隱藏層用來學習輸入資料的特徵, 其神經元數目是超參數, 可任意指定, 一般使用 2 的次方數字 (例如 64). 由於 MNIST 資料集是以 2D 陣列表示, 因此在饋入神經網路之前須將其拉平為 1D 陣列. 
  4. 在 Google 雲端硬碟中的 Colab 運算平台執行機器學習運算非常方便, 用法參考 :
    方便好用的 Google Colab 運算平台
    如果要在 Colab 上用 matplotlib 繪圖, 需先執行下列程式碼 :
    %matplotlib inline    
  5. 在 Colab 平台進行 MNIST 資料集訓練 : 
    (1). 匯入模組 :
    from tensorflow.keras.datasets import mnist          # 匯入 MNIST 資料集
    from tensorflow.keras.models import Sequential   # 匯入堆疊模型
    from tensorflow.keras.layers import Dense             # 匯入密集層
    from tensorflow.keras import optimizers                # 匯入優化器
    from tensorflow.keras.utils import plot_model       # 匯入繪圖模型
    from tensorflow.keras.utils import to_categorical   # 匯入分類器
    import matplotlib.pyplot as plt                                  # 匯入繪圖模組 pyplot
    import numpy as np                                                    # 匯入 Numpy

    (2). 載入 MNIST 資料集 : 

    (X_train, y_train), (X_test, y_test)=mnist.load_data()    
    這會傳回兩組 tuple第一組是 6 萬筆的訓練集, X_train 是訓練集的圖片資料, y_train 是訓練集的標籤 (答案); 第二組是 1 萬筆的測試集, X_test 是測試集的圖片資料, y_test 是測試集的標籤 (答案), 結果如下 : 


    大寫 X 表示這是 2D 以上的向量; 而小寫 y 表示這是 1D 的向量或純量.

    (3). 查看資料集內容 :

    X_train.shape    
    (60000, 28, 28)   
    表示訓練集有 6 萬筆資料, 每筆圖片解析度是 28x28.
    然後用 Numpy 的 set_printoptions() 設定列印寬度為無限大, 這樣才不會因為過長而跳行, 接著列印訓練集的第一筆資料圖片內容 :
    np.set_printoptions(linewidth=np.inf)      
    X_train[0]    




    看起來是數字 5. 接著查看訓練集標籤內容 :
    y_train[0:12]   
    array([5, 0, 4, 1, 9, 2, 1, 3, 1, 4, 3, 5], dtype=uint8)


    可見訓練集第一張圖片確實是 5.

    (4). 用 Matplotlib 繪製 MNIST 資料圖片 :
     
    plt.figure(figsize=(5, 5))     # 設定 5吋*5吋畫布
    for k in range(12):              # 繪製前 12 張圖片
        plt.subplot(3, 4, k+1)      # 指定 3*4 網格中第 k+1 個子圖繪圖區
        plt.imshow(X_train[k], cmap='gray')     # 在第 k+1 個子圖繪製第 k 張圖片
    plt.tight_layout()    
    plt.show()    

    上面程式碼用來繪製 MNIST 測試集的前 12 張圖片, 這裡要注意, plt.subplot() 的子圖網格系統編號是 1 起始的, 但 MNIST 的資料編號則是 0 起始的. 關於 Mplotlib 用法參考 :

    Python 學習筆記 : Matplotlib 資料視覺化 (一) 基本篇
    Python 學習筆記 : Matplotlib 資料視覺化 (二) 統計圖
    Python 學習筆記 : Matplotlib 資料視覺化 (三) 進階篇

    結果如下 :



    (5). 資料預處理 : 
    資料預處理主要有兩項, 首先要將全部資料集的圖片資料從 28*28 的 2D 陣列型態拉平為 1*784 的 1D 陣列, 這樣才能與神經網路的輸入層結構匹配 (同時也將原本 0~255 的整數像素由 uint8 改為 float32 浮點數), 這主要是依賴 Numpy 的 reshape() 與 astype() 達成. 其次是要將資料正規化, 將所有資料轉成 0~1 之間的數值, 這樣模型的訓練成效較好. 最簡單的正規化就是除以最大值 (255) :

    X_train=X_train.reshape(60000, 784).astype('float32')    # 2D 資料展平為 1D
    X_test=X_test.reshape(10000, 784).astype('float32')         # 2D 資料展平為 1D
    X_train /= 255              # 正規化
    X_test /= 255                # 正規化
    X_train[0]                    # 顯示第一張圖片




    (6). 標籤預處理 : 

    除了資料需要預處理外, 輸出標籤 (即 y_train 與 y_test) 也需要預處理, 將原本的 0~9 用 one-hot 編碼為 10 維的 1D 陣列, 這要用到 Keras 的 to_categorical() 函式 :

    y_train=to_categorical(y_train, 10)     # 訓練集標籤 one-hot 編碼
    y_test=to_categorical(y_test, 10)          # 測試集標籤 one-hot 編碼
    y_train[0]            # 顯示訓練集第一張圖的標籤


    可見第一張圖 5 只有在 [5] 位置是 1, 其餘為 0. 

    (7). 建立, 編譯, 與訓練神經網路模型 :

    使用 Sequential 模型建立三層神經網路 :


    model=Sequential()     # 建立序列式模型
    model.add(Dense(64, activation='sigmoid', input_shape=(784,)))   # 輸入+隱藏層
    model.add(Dense(10, activation='softmax'))    # 輸出層
    model.compile(loss='mean_squared_error',    
                             optimizer=optimizers.SGD(learning_rate=0.01),    
                             metrics='accuracy')                    # 編譯模型
    model.fit(X_train, y_train, batch_size=128, epochs=200, verbose=1,      
                    validation_data=(X_test, y_test))       # 訓練模型

    此處 model 只呼叫 add() 兩次就建立了三層模型, 因為第一次呼叫 add() 時同時建立了輸入層 (用 input_shape 參數指定 784 個神經元) 與隱藏層 (64 個神經元), 因為在 tf.Keras 中第一層是輸入層間隱藏層, 第二次呼叫 add() 建立輸出層時不需指定 input_shape, 模型會自動連結上一層的 64 個神經元. 呼叫 Dense() 函式是要建立全連接的密集層, 該層的每個神經元都會與上一層的每個神經元連接. 參數 activation 指定激活函數 (activation function), 用來增加神經元對非線性規則的學習能力. 激活函數 softmax 可將輸出層神經元的輸出限制在 0~1 之間, 而這 10 個值加起來是 1, 故 softmax 有輸出機率值的效果. 
    呼叫 fit() 編譯模型時傳入 loss 參數指定損失函數類型來計算模型預測值與正確答案之誤差, optimizer 參數指定優化器, 用來調整權重使誤差值能降到最低. metrics 參數則指定如何評估模型的學習成效, 'accuracy' 表示以準確度來評估. 
    呼叫 fit() 訓練時傳入參數 batch_size=128 表示訓練時每次從 6 萬筆資料集中取 128 筆資料進行訓練 (考量到記憶體容量, 並不是把訓練集一次全部饋入神經網路, 而是分批饋入), 依序跑完 6 萬筆稱為一個 epoch (一輪), 參數 epochs=200 表示這 6 萬筆要跑 200 輪. 參數 verbose=1 表示顯示完整的訓練過程 (包含進度條). 


    跑 200 個 epoch (輪) 花了 6 分鐘, 最後達到 86.4% 精確度 :


  6. 儲存 ipynb 檔副本於 GitHub :
    Colab 的執行過程除了會儲存在 Google 雲端硬碟裡, 還可以儲存副本到自己的 GitHub 儲存庫裡, 上面的程式碼 ipynb 檔的 GitHub 網址如下 :
    https://github.com/tony1966/colab/blob/main/deep_learning_illustrated_ch5_mnist.ipynb



     

2022年3月28日 星期一

機器學習筆記 : 深度學習的 16 堂課 (四)

本篇繼續整理 "深度學習的16堂課" 這本書的讀後筆記, 本系列之前的文章參考 : 


以下是讀完第四章 "遊戲對局-Alpha Go, DQN, RL 概述" 的摘要筆記 :
  1. 訓練機器下棋與玩遊戲背後所使用的技術是增強式學習 (Reinforcement Learning, RL), 此架構中有一個會與環境 (Environment, 例如遊戲, 或自駕車的駕駛場景等) 進行一連串互動的代理人(Agent, 例如遊戲中的虛擬玩家, 自駕車的隱形司機等), 代理人在採取動作 (Action, 例如遊戲搖桿或上下左右按鍵) 後會收到環境給它的狀態 (State, 例如遊戲的最新畫面) 與回饋值 (Reward, 可稱為獎勵或處罰). 強化式學習演算法本身不具有任何背景知識, 完全依靠回饋值來修正動作而學習到正確的回應方式. 
  2. 當強化學習加上神經網路時就會冠上深度兩字, 被稱為深度強化式學習 (Deep Reinforcement Learning, DRL), 這個神經網路的目的是要用來學習, 當環境傳來各種狀態時, 代理人應該要執行甚麼動作, 才能將回饋值最大化. 
  3. 大多數情況下深度強化式學習都發生在模擬環境中, 亦即指要讓代理人多模擬幾回合, 不斷產生的模擬數據 (動作 & 結果) 都可以做維神經網路的訓練資料.
  4. 深度強化式學習最早的應用是用來玩電子遊戲, 由 Demis Hassabis 等人於 2010 年創立的英國 DeepMind 公司於 2013 年發表了 Deep Q-Learning Netwwork, DQN) 技術, 可以讓模型學會玩多款 Atari 遊戲機的遊戲. 他們所訓練的遊戲代理人會不斷從環境 (即遊戲) 收到狀態資訊 (即以像素表示的遊戲畫面), 宛如人類玩家在盯著螢幕一樣. 為了有效處理這些像素資訊, DQN 也加入了卷積神經網路 (CNN) 以便從高達每秒 200 萬像素的資料中萃取出關鍵特徵. 在訓練過程中 DQN 的代理人除了獲得當前狀態 (螢幕像素), 回饋值 (遊戲得分), 以及可以採取的動作 (可按哪個按鈕) 外, 並不會得到任何指示. DeepMind 團隊評估了 DQN 在 49 款 Atari 遊戲中的表現, 有 94% 表現超越其他機器學習方法, 超過 50% 優於人類的成績. 由於 DQN 的卓越成果, Google 於 2014 年以 5 億美元收購了 DeepMind
  5. 真正讓深度強化式學習大放異彩的其實是複雜度與難度比電子遊戲還高的棋類遊戲, 特別是於 2015 年 10 月以五比零全勝成績擊敗華裔法籍職業圍棋手樊麾的 AlphaGo, 這是歷史上電腦首次打敗人類職業圍棋棋士.  2016 年 3 月 AlphaGo 更以 4:1 成績擊敗擁有 18 項世界圍棋冠軍頭銜, 全球頂尖的南韓職業圍棋棋士李世乭九段而獲得全球矚目, AlphaGo 也因此被韓國棋院授予職業九段榮譽.
  6. 相較於西洋棋而言, 圍棋棋子在棋盤上的位置超過 2*10**170 種, 比西洋棋高出 10**100 倍. 一般的棋類遊戲像西洋棋等只要用蒙地卡羅搜尋法 (Monte Carlo Tree Search, MCTS) 即可應付, 但對複雜度高的圍棋來說並不足以達到很好的表現. DeepMind 研究員 David Silver 等人結合 MTCS, 監督式學習, 以及強化式學習, 大幅地提升了 AlphaGo 演算法的能力.
  7.  AlphaGo 的運作方式分為兩個階段, 研究人員先以圍棋專家歷史棋局資料集 (棋譜) 與監督式學習建立了所謂的策略網路 (policy  network) 演算法, 只要給定棋局目前的狀態, 演算法便能將可能的下一步列成一張簡短的清單. 然後再以自我對奕 (self-play) 的強化式學習加強這個策略網路. 經過一輪輪的自我對奕, 代理人的棋力也不斷提升. 此外 AlphaGo 用蒙地卡羅搜尋法設計了一個估值網路 (value network) 來預測對奕的贏家, 評估棋子大量的選擇點位置, 然後用兩個深度學習網路來習得有效的落子方式. 
  8. OpenAI Gym :
    http://github.com/openai/gym
  9. OpenAI Hide and Seek :
    # http://openai.com/blog/emergent-tool-use/
    https://www.youtube.com/watch?v=kopoLzvh5jY


  10. DeepMind Lab 是 Google DeepMind 開發的模擬環境, 其安裝使用參考 :
    # http://bit.ly/buildDML

機器學習筆記 : 深度學習的 16 堂課 (三)

本篇繼續整理 "深度學習的16堂課" 這本書的讀後筆記, 本系列之前的文章參考 : 


以下是讀完第三章 "機器藝術-對抗式生成網路概述" 的摘要 :
  1. 對抗式生成網路 (GAN, Generative Adversarial Network) 是 2014 年由當時還是 Yoshua Bengio 實驗室博士生的 Ian Goodfellow 所構想出來的一種深度學習演算法 (他在史丹佛讀書時則是吳恩達的學生), 此演算法建構的生成模型 (generative model) 可以自動生成沒有出現過的東西, 例如模仿莎士比亞風格的名言, 旋律, 或抽象的藝術品. Ian Goodfellow 的創見來自他將兩個神經網路組合成一個深度學習模型的突發奇想, 然後訓練它們使其彼此互相競爭. 這兩個網路一個是用來用來產生假圖的生成器 (generator), 另一個則是用來鑑別真假的鑑定器 (discriminator), 循環競爭促使生成器產生更精良的假圖, 同時也使鑑定器進化出更好的鑑別能力, 最終讓模型生成風格與原始訓練圖片非常接近的假圖. 2014 年 Ian Goodfellow 在 NeurIPS 大會發表了 GAN, 並展示了用 GAN 生成的手寫數字, 人臉, 以及飛機, 汽車, 狗等圖片, 這些都是利用 MNIST 與 CIFAR-10 等資料集訓練出來的. Ian Goodfellow 目前於蘋果公司擔任機器學習總監. 
  2. 2016 年美國工程師Alec Raford 在 GAN 的基礎上加入卷積神經網路, 提出 Deep convolution GAN (深度卷積對抗式生成網路), 利用所謂的潛在空間 (latent space) 生成更逼真的圖片. 潛在空間可以說是真圖的濃縮特徵, 可用來協助生成器生成圖片. 潛在空間的概念與詞向量空間類似, 它用高維向量來表示圖片中的不同特徵, 高維空間的每個軸代表不同的意義, 例如性別差異, 年齡大小或有無戴眼鏡等, 空間中的每個點代表一張圖片 (與詞向量空間中某點代表某詞類似), 兩個點位置越靠近表示兩點所代表的圖片越相似, 將這些點的座標向量進行運算, 其結果代表意義上的移動, 例如將 '戴眼鏡的男人' 減掉 '沒戴眼鏡的男人', 再加上 '沒戴眼鏡的女人' 運算後得到的向量會非常接近 '戴眼鏡的女人' 這個點.
  3. GAN 生成圖片的展示 :
    http://bit.ly/InterpCeleb


    下面這個網頁使用 GAN 產生假的人臉, 猜猜看哪個是真人臉孔 : 
    https://www.whichfaceisreal.com/
  4. 2017 年柏克萊大學人工智慧實驗室 (BAIR) 提出的 CycleGAN 可以將照片轉換成不同的藝術風格, 稱為風格轉移 (style transfer) : 
    https://junyanz.github.io/CycleGAN/
    其應用範例例如 :
    (1). 將莫內的畫轉成照片, 或者將照片轉成莫內畫風
    (2). 將斑馬變成馬, 或者將馬變成斑馬
    (3). 將春景變成冬景
    BAIR 實驗室還推出另一個稱為 conditional GAN (cGAN) 的應用 : pix2pix, 可將手繪圖案變成照片 :
    https://affinelayer.com/pixsrv/index.html 
    在左邊 INPUT 框內繪製主題圖案 (例如貓), 按中間的 process 鍵就會在右方框產生圖片, 因為它會依據輸入條件 (即所繪製的圖形) 來產生結果, 故稱為條件式 GAN (cGAN) :


  5. 另外一個 GAN 應用是 Han Zhang 等人提出的 StackGAN, 它是將兩個 GAN 網路堆疊起來, 第一個 GAN 先產生較粗糙低解析度的小圖 (建立基本輪廓與顏色), 結果再送至第二個 GAN 來轉成高解析度的大圖. 其獨特之處是它可以從文字敘述 (條件) 作為輸入來產生圖片, 參考 :
    使用Keras實現StackGAN 
    https://github.com/Vishal-V/StackGAN
    Let’s Read Science! “StackGAN: Text to Photo-Realistic Image Synthesis”


  6. 深度學習在影像處理方面的應用也非常多, 例如傳統影像處理軟體只能對整個圖片進行降躁, 但透過深度學習就能在不同區域進行不同的降躁處理. 其它的應用例如將原本全黑圖片調亮, 或調整背景光源等, 參考 :



2022年3月27日 星期日

2022 年第 13 周記事

周五接到小舅媽通知, 周日早上要去掃外公外婆的墓, 所以今早八點我就先去小舅家等左營阿姨, 結果她卻直接去墓園了. 每年大概就是我們這幾個人去, 大多數人家已於上週之前就掃過了, 今天整個墓園僅有兩三家而已, 晚拜的好處就是不會人潮車潮擁擠. 拜完我先去愛心與市集買豆腐, 回來安頓好中午再去小舅家吃午飯. 

過年前種的那批玉米今日全部採收, 留了三條煮湯外其餘都先下鍋. 順便將田埂旁空地鋤一鋤, 準備下周再買 20 株來種. 今日去小舅家看到他把空地整理得非常好, 胡瓜從園子裡爬上頂樓, 還可以遮陽哩. 他那邊可種地有限還能產出豐富, 相比之下我的菜園就太曝畛天物了. 下午去菜園採玉米才發現角落的香蕉被爸挖掉了, 說是不會再開花, 我看被挖斷的幼苗葉子還是綠油油, 就把它移到馬路邊波蘿蜜樹旁挖個洞種下去, 這是從公司花園移植來的, 那個花園的植栽已全部被夷平, 所以這棵香蕉樹是唯一的樹種了.  




去年跟賣鳳梨的人要的鳳梨頭拿回來種在菜園一年多, 今天發現居然已結出果實 : 




鳳梨可用無性生殖法栽培, 切掉的鳳梨頭放入土中還會繼續存活茁壯. 

2022年3月26日 星期六

機器學習筆記 : 深度學習的 16 堂課 (二)

本篇繼續整理 "深度學習的16堂課" 這本書筆記, 本系列前一篇文章參考 : 


以下是讀完第二章 "用機器處理自然語言" 的摘要筆記 :
  1. 英國哲學家維根斯坦 (Ludwig Wittegenstein, 出身於奧匈帝國豪門) 在其著作 "哲學研究" 一書中談到 : "我們不應該去猜測一個字的功能為何, 而是要去研究它是如何被使用的, 並從中習得其意思". 以深度學習為基礎的自然語言處理其原理與上述想法一致, 必須弄清楚一個字在語言中的脈絡, 才能確定它的意思是甚麼. 亦即, 字的真正意思決定於其語境或上下文 (context, 或脈絡字), 而不是其表面上的意義.
  2. 傳統機器學習的缺點是需要在建模前先進行耗時費力的特徵工程, 將原始資料轉換成機器學習演算法能接受的輸入特徵, 這意味著如果要用它來處理自然語言, 你必須先受過語言學訓練, 才有能力將語言資料轉換成可用之特徵. 深度學習則免除了特徵工程這道程序, 只要把原始資料直接餵給深度學習模型, 模型會在訓練階段自動從資料中取得特徵. 需要大量手工的特徵工程除了費時費工外, 其取得之特徵適用的範圍也有不夠廣泛的問題. 
  3. 深度學習模型中靠近輸入層的神經元學習到的是資料中的簡單特徵, 而靠近輸出層的後段神經元學習到的是較抽象與複雜的特徵, 這在用深度學習來做 NLP 時仍然適用. 
  4. NLP 的常見應用 :
    (1). 文件分類 : 例如判別正面/負面
    (2). 機器翻譯 : 兩種語言對翻
    (3). 搜尋引擎 : 自動補字, 預測搜尋資訊
    (4). 語音辨識 : 例如 Siri
    (5). 聊天機器人 : AI 客服機器人
  5. 雖然說深度學習不需要特徵工程, 但原始的文字資料也不是真的就直接送進深度學習模型, 而是需要做預處理, 將文字量化為數字形式後, 才能餵給深度學習網路. 常見的語言量化做法有兩種 :
    (1). One-hot encoding (獨熱編碼, 或單一有效編碼)
    (2). Word vector (詞向量)  
  6. One-hot 編碼是一種只記錄位置訊息的編碼, 文本中的每個字以單字表長度做維度, 以 1 標示它在單字表 (語料庫) 中的位置, 其餘用 0 表示. 例如 'This is a book' 共有四個單字, 其字典為 ['this', 'is', 'a', 'book'], 所以 'This' 的 one-hot 編碼是 1000, 其中的 1 標示 'This' 的位置; 同理 'is' 的編碼是 0100; 'a' 的編碼是 0010; 'book' 的編碼是 0001, 整個句子就可用一個矩陣表示 [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]. 顯然地, one-hot 編碼不可避免會形成稀疏矩陣, 且只記錄位置訊息量太低.
  7. 詞向量 (word vector) 又稱為詞嵌入 (word embeddings) 或向量空間嵌入 (vector-space embeddings), 它會同時紀錄單字的位置與意義, 是開發者較偏愛的編碼方式. 詞向量空間的概念是將語料庫中的每個字詞都與一個多維度向量空間中的位置對應起來, 這是模型訓練前須先完成的前置工作. 初始時各字詞所對應的向量空間位置是隨機決定的, 在訓練中深度學習模型會分析哪些字較常與特定字詞一起使用, 就會逐漸移動到適合的新位置上 (物以類聚), 這樣語意相近的字詞就會靠得比較近.  
  8. 從語料庫建立詞向量方式 : 走訪語料庫, 先從第一個單字出發, 一次往右移一個字, 目前指標所指的字稱為目標字 (target word), 其前後幾個字 (數量由開發者指定) 稱為脈絡字 (context words), 然後使用例如 Word2Vec 或 GloVe 等具有深度學習概念的轉換工具 (演算法) 將語料庫中的字逐一嵌入詞向量空間, 這些工具通常用以給定的脈絡字預測目標字的方式來決定目標字該放到詞向量空間哪一個位置. 
  9. 詞向量空間屬於 n 維向量高維度空間 (維度取決於語料庫的資訊量), 其拓樸結構過於抽象, 超出人腦的認知. 但透過對詞向量進行運算, 計算詞向量座標之間的方向與距離, 可以了解詞與詞之間的關係與意義. 
  10. 用 Word2viz 體驗二維詞向量空間 :
    # http://lamyiowce.github.io/word2viz
    這是使用 60 億個字的語料庫訓練出來的詞向量空間, 每一個單字已根據其意義被放在是當位置. 此網站可用互動方式將新詞嵌入此詞向量空間. 右上方下拉式選單請固定在 "Gender analogies" 選項, 然後於 "Modify words" 項下的兩個 "Type a new word" 欄中輸入一組新的單字, 例如 princess 與 prince, 然後按 'Add pair' 鈕即可 :




    可見 prince 與 princess 跟 king 與 queen 距離很近, 且 prince 靠近 king, 而 princess 靠近 queen, 反映了性別上的異同. 

機器學習筆記 : 深度學習的 16 堂課 (一)

以下是我閱讀下面這本書的筆記, 這本書我這兩天已看完了, 現在回頭重讀並整理筆記, 前四章都是知識性的介紹, 到第五章後才有實作, 要上 Colab 來實際跑一跑程式碼 :



Source : 博客來


此書譯自 Addison-Wesley 2020 年出版的這本 :



Source : 博客來


以下是讀完第一章 "生物視覺與機器視覺" 的摘要筆記 (添加了我蒐集整理的資訊) : 
  1. 三葉蟲 (trilobites) 在西元前 500 多年以前就發展出視覺能力. 
  2. 現代哺乳動物大腦的皮質 (cerebral cortex) 有很大一部份都與視覺有關. 1981 年諾貝爾醫學獎就頒給了 David HubelTorsten Wiesel, 與 Roger Sperry, 以表彰他們自 1959 年開始在哺乳動物大腦神經生理學與視覺訊息處理上的貢獻. 他們的研究也啟發了深度學習中的卷積神經網路 (CNN) 的發明. 
  3. 皮質 (又稱灰白質) 是大腦中最晚演化出來的部分, 負責處理動物較複雜的行為. 皮質只有在哺乳類動物與少數爬蟲類 (例如蜥蜴與烏龜) 的大腦中才有, 參考 :
    https://www.mpg.de/12027342/molecular-atlas-reptile-brain 
    灰質 (gray matter) 位於大腦最外層, 負責為大腦進行複雜計算. 大腦的絕大部分為白質 (white matter), 它相當於是大腦中的高速公路, 負責將訊息傳送到更遠的地方. 而灰質則類似區域聯絡道路, 負責將訊息傳送到神經元以進行計算. 
  4. David Hubel 與 Torsten Wiesel 在貓的視覺皮質神經實驗中發現, 接收眼球訊息的神經元對於簡單的直線邊緣最敏感, 此外, 特定神經元會對特定傾斜角度的邊緣產生反應, 即每個細胞都對應不同的角度, 一群神經元就可以對應 360 度的角度了, 這些神經元稱為簡單神經元. 他們的系統性實驗結果建立了視覺皮質的地圖. 
  5. 皮質中的簡單視覺神經元處理過的信號會被送往一群複雜神經元, 在此不同角度的直線會被組合與消化, 變成幾何圖形的角或弧線等複雜形狀. 
  6. 受到 David Hubel 與 Torsten Wiesel 等人關於視覺神經的研究啟發, 當時任職於 NHK 視覺實驗室的日本工程師福島邦彥 (Kunihiko Fukushima, 京都大學電機博士) 於 1979 年提出了新認知機 (neocognitron), 這是一個深度神經網路, 也是最早的卷積神經網路雛形, 越前面的神經元處理較簡單的物體特徵 (例如傾斜角), 越後面的神經元則處理複雜抽象的特徵. 福島邦彥將新認知機的前兩層類神經元以 David Hubel 與 Torsten Wiesel 所稱的簡單 (S 細胞) 與複雜神經元 (C 細胞) 來命名. 福島邦彥由於在神經網路與模式識別上的貢獻, 獲頒 2021 年美國歷史最悠久獎額也最高的鮑爾獎 (Bower Award), 參考 :
    https://vitomag.com/tech/odeou.html 
    福島邦彥可以說是第一個把動物大腦神經網路模型搬到計算機上的人, 也是 CNN 網路之父.
  7. 受到新認知機的啟發, 當代深度學習大師 Yoshua Bengio 與 Yann LeCun 等人於 1998 年提出 深度學習模型 LeNet-5, 這是歷史上第一個卷積神經網路 (CNN), 借助於更大量的訓練資料與更強大的計算力, 它使用了反向傳播演算法大幅提高了手寫辨識數字的精確度 (因它能使每一層神經元更有效率地學習), 也是最早進入商用地深度學習模型. 
  8. 傳統機器學習麻煩的地方是開發者必須花費大量精力於特徵的擷取上, 此過程稱為特徵工程 (feature engineering), 首先須以複雜的演算法對資料進行預處理 (preprocessing), 將資料轉換成傳統統計工具 (例如迴歸, 隨機森林, 支持向量機等) 可處理的輸入特徵, 花費太多時間在資料加工上, 沒有餘力去建立與優化模型. 深度學習則相反, 開發者不需要去做特徵工程, 模型會自動從原始資料中萃取有用的特徵, 這是深度學習與傳統機器學習最大的不同. 
  9. 2012 年的 ILSVRC 影像辨識競賽由 Alex Krizhevsky 與 Ilya Sutskever 團隊 (都來自深度學習之父 Geoffrey Hinton 的實驗室) 的作品 AlexNet 以巨大差距拿下冠軍, 使 2012 年成為機器視覺技術的分水嶺, 此後在 ILSVRC 中取勝的隊伍, 所使用的演算法全部都是以深度學習為基礎. 到了 2015 年, 深度學習在機器視覺上更勝過人類. 
  10. AlexNet 成功的因素 :
    (1). 使用資料擴增 (data augmentation) 技術增加資料量, 使模型的訓練更加有效. 
    (2). 使用 GPU 來提升計算效能
    (3). 擁有更多神經層, 且採用了捨棄法 (dropout) 提升模型的預測準確率. 
  11. 加拿大多倫多大學教授 Geiffrey Hinton 被稱為深度學習之父, 曾領導 Google Brain, 他與Yoshua Bengio 以及 Yann LeCun 共同獲得 2019 年電腦科學最高榮譽圖靈獎 (Turing Awards).
  12. 深度學習大大地減少了建立模型所需要的特定領域知識, 使得機器學習的焦點從特徵工程轉移到深度學習的網路架構改進以及模型的鉉練. 它最大的價值就是, 隨著各式各樣的應用快速出現, 人們套用深度學習技術的能力變得比他們的專業領域能力還要重要
  13. Google 的深度學習體驗網站 TensorFlow Playgound :
    # http://bit.ly/TFplayground
    此神經網路目的是要學習網頁上橘色點與藍色點的分布情形, 它會在網頁上自動生成神經網路模型, 然後輸入任一個座標 (x1, x2), 它就能辨識此為哪一種顏色的點. 注意, 在網路學習階段, 右下角的 "show test data" 不要打勾, 因為訓練階段只能使用 train 的資料, 不可讓網路接觸到測試 (test) 的資料. 
  14. 限時塗鴉牆遊戲網頁 :
    # http://quickdraw.withgoogle.com
    按 "開始塗鴉" 後依指示畫一個物體, 神經網路會即時猜測化的是甚麼.

申請第二個 Line 帳號

最近從水某那裏獲得一個型號為 M2-802L 的華為舊平板, 外型為較長的七吋, 雖然比 iPad Mini 較長些, 但好處是還可安裝 ASUS Web Storage, 而且 Micro USB 介面接上筆電就可以馬上搬檔案, 而且七吋剛好可以一手掌握, 看 pdf 或 epub 電子書很方便, 最近都用這台看書, iPad 2 太重改放家裡. 

因為以前母親的手機門號我有保留下來, 轉成中華電信如意卡,  這是我買給媽與阿姨們聊天之用, 保留門號一方面是紀念, 也做為我的備用門號, 且預付卡只要每半年儲值 100 元即可, 也不花甚麼錢. 昨天就在這台華為平板上安裝了 Line, 然後用這支手機門號註冊了第二個帳號, 我打算用來測試 Line bot 用, 最近剛好有網友詢問 Line bot 問題, 空懸已久的學習測試計畫也該了結啦. 

本息平均攤還與本金平均攤還

元旦上台北一趟看到姊姊與同學租的房間好小, 從來沒想再置產的我突然起心動念, 因為蠻後悔當年回高雄時將土城海山捷運站旁的房子賣掉 (理財腦殘啊), 要不然姊姊就有現成居所了. 

那幾年其實財神都三番兩次眷顧我, 具體來說就是鳳山荷風透天, 美術館透天, 以及公司附近寶成 70 坪大樓這三案, 當時價格都是 700~800 萬之間, 每家房仲小姐都打了兩三次電話來詢問意願, 甚至明示價錢可再談, 可惜那時剛繳完房貸不想再揹, 也不想換屋, 加上缺乏投資眼光, 結果都被我殘忍地拒絕了, 殘念~~~. 

台北房子貴, 大安區更貴, 我以前想都沒想在台北市買房子. 今天看到信義房屋廣告, 好奇查了一下, 發現古亭站附近有預售的一房一廳一衛的套房, 價格約一千萬, 就問姊姊意思, 她說那是她三十歲時存到頭期款後的計畫. 我說如果我先投資, 繳到十年後退休剩下你來繳, 哈哈. 姊姊說等轉職到老師的後製公司也許可以來考慮看看.

我先到 591 房貸網算了一下月繳房貸 :


以房價 1000 萬計算結果如下 : 




大概比租套房多出 1 萬塊左右, 專家說租不如買, 租三十年 1.5*12*30=540 萬, 相當於買了半棟套房.  但這裡有分"本息均攤" 與 "本金均攤", 這是啥意思? 下面這篇解釋甚詳 : 


傳統本息均攤是每期繳款金額相同, 但本金與利息比例不同; 而本金均攤的利息是用本金餘額去算, 所以每期的繳款金額會不同, 但有加速還款效果, 總繳利息比本息均攤要少, 但先苦後甘, 前期每月付款會較高. 不過本息均攤每月繳款金額固定較好管理, 且若手邊有閒錢提前還款還是一樣有節降利息效果. 

目前通膨持續升溫, 現金越變越薄, 姊姊每月還是要繳房租, 不如 .... 不過這還只是突然的想法而已, 畢竟 1000 萬不是小數目. But, 如果下期統一發票能中特獎就好了, 哈哈. 

參考 :


2022年3月24日 星期四

Python 學習筆記 : 檢視物件成員與取得變數名稱字串的方法

在探索 Python 套件時, 常需要呼叫內建函式 dir() 來取得一個物件的所有成員串列, 透過走訪列印此串列元素即可一窺物件有哪些屬性與方法. 例如機器學習套件 Scikit-learn 有一個資料前處理模組  preprocessing, 在匯入後即可傳入 dir() 來觀察 :

>>> from sklearn import preprocessing   
>>> dir(preprocessing)      
['Binarizer', 'CategoricalEncoder', 'FunctionTransformer', 'Imputer', 'KBinsDiscretizer', 'KernelCenterer', 'LabelBinarizer', 'LabelEncoder', 'MaxAbsScaler', 'MinMaxScaler', 'MultiLabelBinarizer', 'Normalizer', 'OneHotEncoder', 'OrdinalEncoder', 'PolynomialFeatures', 'PowerTransformer', 'QuantileTransformer', 'RobustScaler', 'StandardScaler', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '_discretization', '_encoders', '_function_transformer', 'add_dummy_feature', 'base', 'binarize', 'data', 'imputation', 'label', 'label_binarize', 'maxabs_scale', 'minmax_scale', 'normalize', 'power_transform', 'quantile_transform', 'robust_scale', 'scale']

但是這個串列輸出很簡略且包山包海 (例如還有以雙底線 __ 開頭結尾的內部變數), 並無法了解這些成員究竟哪些是變數哪些是函式, 解決辦法是利用內建函式 eval() 與 type(), 並配合字串的 startswith() 方法來過濾, 例如 : 

>>> members=dir(preprocessing)     
>>> for mbr in members:                         # 走訪成員
     obj=eval('preprocessing.' + mbr)        # 用 eval() 求值取得成員之參考
     if not mbr.startswith('_'):                     # 走訪所有不是 "_" 開頭的成員
         print(mbr, type(obj))                        # 印出成員名稱與類型

Binarizer <class 'type'>
CategoricalEncoder <class 'type'>
FunctionTransformer <class 'type'>
Imputer <class 'type'>
KBinsDiscretizer <class 'type'>
KernelCenterer <class 'type'>
LabelBinarizer <class 'type'>
LabelEncoder <class 'type'>
MaxAbsScaler <class 'type'>
MinMaxScaler <class 'type'>
MultiLabelBinarizer <class 'type'>
Normalizer <class 'type'>
OneHotEncoder <class 'type'>
OrdinalEncoder <class 'type'>
PolynomialFeatures <class 'type'>
PowerTransformer <class 'type'>
QuantileTransformer <class 'type'>
RobustScaler <class 'type'>
StandardScaler <class 'type'>
add_dummy_feature <class 'function'>
base <class 'module'>
binarize <class 'function'>
data <class 'module'>
imputation <class 'module'>
label <class 'module'>
label_binarize <class 'function'>
maxabs_scale <class 'function'>
minmax_scale <class 'function'>
normalize <class 'function'>
power_transform <class 'function'>
quantile_transform <class 'function'>
robust_scale <class 'function'>
scale <class 'function'>

參考 :


其中的關鍵是在 eval() 中必須傳入物件或模組名稱與其成員之組合字串, 例如 'preprocessing.Binarizer', 這個在檢視個別物件或模組時沒有問題, 但如果要把上面的程式碼寫成函式就會遇到如何取得一個變數的名稱字串問題.

簡言之, 上面的程式碼我想寫成如下函式 :

def list_members(parent_obj):
    members=dir(parent_obj)
    parent_obj_name=?????     
    for mbr in members:
        child_obj=eval(parent_obj_name + '.' + mbr) 
        if not mbr.startswith('_'):
          print(mbr, type(child_obj))    

但要如何取得傳入的物件名稱呢? 這當然不能套用傳入的物件 parent_obj, 這個是物件本身, 而我要的是它的名稱字串 'parent_obj'. 在谷歌大神幫助下找到下面這篇文章 : 


其中 "étale-cohomology" 所給的回覆最簡單, 解決辦法是使用可以檢視物件結構的內建函式 inspect() 來檢視 Frame 執行容器物件, 利用掃描容器內的執行物件比對是否為所傳入之物件, 符合就傳回其 key (物件名稱字串), 從而取得物件名稱, 程式碼如下 :

import inspect 
def varname(x): 
    return [k for k,v in inspect.currentframe().f_back.f_locals.items() if v is x][0]

參考 :


例如 :

>>> import inspect    
>>> def varname(x):      
  return [k for k,v in inspect.currentframe().f_back.f_locals.items() if v is x][0]     

>>> list1=[1, 2, 3]    
>>> varname(list1)       
'list1'   
>>> from sklearn import preprocessing    
>>> varname(preprocessing)        
'preprocessing'        

可見此方法確實能傳回物件的名稱字串, 這樣就可以把這個 varname() 函式用在上面的 list_members() 函式了, 完整的程式碼如下 :

import inspect 
def varname(x): 
    return [k for k,v in inspect.currentframe().f_back.f_locals.items() if v is x][0]
def list_members(parent_obj):
    members=dir(parent_obj)
    parent_obj_name=varname(parent_obj)       
    for mbr in members:
        child_obj=eval(parent_obj_name + '.' + mbr) 
        if not mbr.startswith('_'):
            print(mbr, type(child_obj))

例如 : 

>>> def list_members(parent_obj):    
    members=dir(parent_obj)   
    parent_obj_name=varname(parent_obj)       
    for mbr in members:   
        child_obj=eval(parent_obj_name + '.' + mbr)       
        if not mbr.startswith('_'):     
            print(mbr, type(child_obj))      
            
>>> list_members(preprocessing)    
Binarizer <class 'type'>
CategoricalEncoder <class 'type'>
FunctionTransformer <class 'type'>
Imputer <class 'type'>
KBinsDiscretizer <class 'type'>
KernelCenterer <class 'type'>
LabelBinarizer <class 'type'>
LabelEncoder <class 'type'>
MaxAbsScaler <class 'type'>
MinMaxScaler <class 'type'>
MultiLabelBinarizer <class 'type'>
Normalizer <class 'type'>
OneHotEncoder <class 'type'>
OrdinalEncoder <class 'type'>
PolynomialFeatures <class 'type'>
PowerTransformer <class 'type'>
QuantileTransformer <class 'type'>
RobustScaler <class 'type'>
StandardScaler <class 'type'>
add_dummy_feature <class 'function'>
base <class 'module'>
binarize <class 'function'>
data <class 'module'>
imputation <class 'module'>
label <class 'module'>
label_binarize <class 'function'>
maxabs_scale <class 'function'>
minmax_scale <class 'function'>
normalize <class 'function'>
power_transform <class 'function'>
quantile_transform <class 'function'>
robust_scale <class 'function'>
scale <class 'function'>

Bingo! 收工! 

2022-07-08 補充 :

我把上面的程式命名為 members.py 模組, 放在 GitHub 儲存庫 :


下載到工作目錄後匯入此模組, 然後呼叫其 list_members() 函式並傳入物件或模組即可, 例如 :

>>> from PIL import ImageColor   
>>> import members as mbr   
>>> mbr.list_members(ImageColor)      
Image <class 'module'>
colormap <class 'dict'>
getcolor <class 'function'>
getrgb <class 'function'>
re <class 'module'>

可見 PIL 套件下的 ImageColor 模組有 5 個公開成員. 

2022年3月23日 星期三

露天購買 18650 充電式照明燈

前年參加小學母校校慶時贈送的禮物之一是兩個太陽能手電筒, 都放在鄉下方便爸晚上到菜園抓菜蟲時照明之用, 白天都放在樓上陽台邊曬太陽, 上週被強風吹下一樓摔壞一個, 我看裡面使用的電池是鎳氫充電電池, 儲電能力不夠, 難怪曬了一天都覺得電力不足. 我在露天找尋適合的手電筒, 找到下面這款使用可裝卸 18650 鋰電池的很合用, 採用並聯電池即使只有一顆 18650 也 OK : 





買兩個 380*2 + 70 合併運費=830 元. 一個放高雄, 預防突然停電時可做為照明之用. 

2022年3月22日 星期二

SpaCy 學習筆記 (三) : 在 Colab 上安裝執行 SpaCy

前兩篇的 SpaCy 測試都是在本機或其官網上執行, 本篇則是要在谷歌 Colab 平台上安裝 SpaCy 與語言統計模型後利用 Google 雲端計算資源來執行自然語言處理管線, 好處是完全不需要擔心本機安裝時可能會遇到的問題, 且可將執行 NLP 任務的過程紀錄下來或分享到 GitHub. 

本系列之前的文章參考 :


Colab 是整合於谷歌雲端硬碟上的免費線上運算平台, 用法可參考這篇 : 



一. 在雲端硬碟建立資料夾與 Colab : 

在谷歌雲端硬碟上安裝 SpaCy 套件與模型之前, 基於資料整理歸檔考量, 最好先建立一個資料夾來收納 ipynb 等相關檔案, 首先按雲端硬碟左上角的 " + 新增" 鈕, 點選 "資料夾" :




在彈出視窗中輸入資料夾名稱, 例如 "SpaCy NLP", 按 "建立" 鈕 :




如此便在雲端硬碟下建立了 "SpaCy NLP" 這個資料夾, 點選進入此資料夾後, 再次按左上角的 "+新增" 鈕, 點選選單中最底下的 "更多", 於次選單中點選 "Google colaboratory" : 




 這樣會新增並開啟一個 Colab 筆記本, 也就是一個 Jupyter Notebook 頁面 (.ipynb 檔) :




接著就可以在此 .ipynb 檔案上安裝 SpaCy 套件與其語言模型了. 


二. 安裝或升版 SpaCy 套件 : 

在 Colab 筆記本的程式碼欄位內輸入下列指令安裝 SpaCy :

!pip install spacy    

按欄位前面的 Play 鍵執行安裝, 結果顯示之前已安裝過 2.2.4 版 :




若要升級到最新版, 按左上角 "+程式碼" 鈕新增一個儲存格, 輸入升版指令 : 

!pip install -U spacy 




可見下載安裝了最新的 SpaCy 3.2.3 版. 

可再新增儲存格輸入如下指令檢查 SpaCy 版本 : 

import spacy  
spacy.__version__    

結果如下 : 




可見確實是 SpaCy 3.2.3 版.


三. 安裝語言的統計模型 : 

在 Colab 安裝 SpaCy 的語言模型必須使用 pip 指令線上安裝, 每個語言模型的下載網址可在 SpaCy 官網查詢 :


例如英文與中文的模型網址如下 : 


以體積最小的英文模型 en_core_web_sm 為例, 其模型之 whl 檔或 gz 檔查詢方式如下 :






其模型網址為 :

https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.2.0/en_core_web_sm-3.2.0-py3-none-any.whl   (13.3 MB)

於 Colab 筆記本新增一儲存格, 輸入如下指令安裝此英文模型 : 

!pip install https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.2.0/en_core_web_sm-3.2.0-py3-none-any.whl     

結果如下 : 





中文模型 zh_core_web_sm 的 whl 檔網址為 :

https://github.com/explosion/spacy-models/releases/download/zh_core_web_sm-3.2.0/zh_core_web_sm-3.2.0-py3-none-any.whl    (47.2 MB)

於 Colab 筆記本新增一儲存格, 輸入如下指令安裝此英文模型 : 

!pip install https://github.com/explosion/spacy-models/releases/download/zh_core_web_sm-3.2.0/zh_core_web_sm-3.2.0-py3-none-any.whl    

結果如下 : 




這樣就可以開始在 Colab 上執行 NLP 管線任務了, 依序新增儲存格輸入如下指令 : 

import spacy
nlp=spacy.load('en_core_web_sm')
doc=nlp('I am going to visit the White House.')
print(f'text\tlemma_\ttag_\tpos_\tdep_\thead')  
for token in doc:
    fstr=(f'{token.text}\t{token.lemma_}\t{token.tag_}\t{token.pos_}\t'
          f'{token.dep_}\t{token.head}')
    print(fstr)

結果如下 : 




注意, 此例中因為 f 字串太長了, 所以將其分兩列放在小括號 () 中. 


四. 語法相依關係與命名實體視覺化 :

在 Colab 執行視覺化與在本機使用 Jupyter Notebook 一樣必須呼叫 doc.render() 而不是 doc.serve(), 而且必須傳入參數 jupyter=True 才能在網頁中繪製圖形. 為了簡單起見, 下面改為分析 'I live in Taiwan' 這個句子來分析, 新增儲存格輸入如下指令 :

doc=nlp('I live in Taiwan.')    
spacy.displacy.render(doc, jupyter=True)       

參考 : 


結果如下 : 




可見 displaycy.render() 不傳入 style 參數時預設是 'dep', 即繪製語法相依圖. 若傳入 style='ent' 則顯示命名實體標記圖, 例如 : 

spacy.displacy.render(doc, style='ent', jupyter=True)

結果如下 : 




上面也安裝了中文模型 zh_core_web_sm, 所以最後來試試中文的視覺化, 輸入如下指令 :

nlp=spacy.load('en_core_web_sm')    
text='''戴笠, 浙江省江山縣人, 中華民國陸軍中將, 生於清光緒 23 年,
國民政府軍統局少將副局長, 蔣介石愛將, 民國 35 年 3 月 17 日於南京上空飛機失事身亡.'''   
doc=nlp(text)   
spacy.displacy.render(doc, style='ent', jupyter=True)    

結果如下 : 




與前一篇測試使用 SpaCy 線上視覺化的輸出有些不一樣, 例如 '蔣介石愛將' 被標記為 ORG (很奇怪), 以及 '南京' 未被辨識出來等, 其餘相同. 

在 Colab 上執行 SpaCy 最方便的地方就是會自動記錄執行過程為 ipynb 檔, 以上測試過程我分享於 GitHub, 開啟後可點選 "檔案/在雲端硬碟另存複本" 複製到個人的雲端硬碟上 :