what are single/dual homed/multi-homed network topologies?

在討論廣域網路如何將客戶端(client)連向伺服端(server),或輻輳(spoke)連向軸心(hub)的連線拓樸時,
常根據源頭(source or home)個數,及線路(link)個數,將連線拓樸依其可靠度/成本分成四類如下:

1.single homed = single-link single-source 單線路單源頭拓樸
2.dual homed = dual-link single-source 雙線路單源頭拓樸
3.single multi-homed = single-link multiple-source 單線路多源頭拓樸
4.dual multi-homed = dual-link multiple-source 雙線路多源頭拓樸

單線路單源頭(single homed)拓樸的成本最低,但是可靠度最差。
雙線路多源頭(dual multi-homed)拓樸的可靠度最佳,但是成本最高。

四類連線拓樸的各種實例可參考如下網頁介紹:
  https://datapacket.com/blog/multihomed-network-vs-single-homed-network

how to check windows version

查看windows版本兩種方法:

1. 指令ver

    Microsoft Windows [版本 10.0.17134.471]

2. 指令 slmgr.vbs -dlv

    軟體授權服務版本: 10.0.17134.471

    名稱: Windows(R), Professional edition
    描述: Windows(R) Operating System, VOLUME KMSCLIENT channel
    啟用識別碼: x-x-x-x-x
    應用程式識別碼: x-x-x-x-x
    延伸的PID: x-x-x-x-x-1028-17134.0000-1382018
    產品金鑰通路: Volume: GVLK
    安裝識別碼: x
    部分產品金鑰: x
    授權狀態: 已取得授權
    大量授權啟用到期: 255777分鐘(178天)
    剩餘的Windows重設授權狀態計數: 1001
    剩餘的SKU重設授權狀態計數: 1001
    信任時間: 2018/12/13 下午06:42:18
    已設定的啟用類型: All

    最近的啟用資訊:
    金鑰管理服務用戶端資訊
      用戶端電腦識別碼(CMID): x-x-x-x-x
      已登錄的KMS電腦名稱:  x.x.edu.tw:1688
      KMS電腦IP位址: x.x.x.x
      KMS電腦延伸的PID: x-x-x-x-x-1028-9600.0000-2932015
      啟用間隔: 120分鐘
      更新間隔: 10080分鐘
      啟用KMS主機快取

four design examples for the add function as class or instance methods

物件導向程式設計在規劃一個運算方法時,面臨兩種選擇

  1. 運算要定義為類別方法或物件方法
  2. 運算結果要定義為方法回傳值,或覆蓋原物件

這兩者選擇完全取決於設計者。底下以簡單的整數加法運算為例,說明定義為類別方法或物件方法,回傳結果或覆蓋原物件,其製作及使用上的差別。 一般是類別設計者參考下面表格先決定運算要如何使用,再決定如何製作。


回傳結果 覆蓋原物件
類別方法 範例: sum=Integer.add(3, 5) → 回傳 8
特性: 不改變原物件,偏向函數式設計
範例: Integer.addInPlace(obj, 5) → obj 由 3 變成 8
特性: 直接修改物件,副作用明顯
物件方法 範例: sum=obj.add(5) → 回傳新物件值 8,原 obj 仍為 3
特性: 保留原物件,方便鏈式操作
範例: obj.addInPlace(5) → obj 由 3 變成 8
特性: 高效但有副作用,難以追蹤狀態
A.四種加法運算的個別設計範例如下:

(1) 類別方法,回傳結果
 public class WholeNumber
 {
    public int number;

    public WholeNumber(int n)
    {
      this.number = n;
    }

    public String toString()
    {
      return String.format("%d", number);
    }

    public static WholeNumber add(WholeNumber n1, WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = n1.number + n2.number;
      return n;
    }

    public static void main(String args[])
    {
      WholeNumber n1 = new WholeNumber(3);
      WholeNumber n2 = new WholeNumber(4);

      // 呼叫加法運算時,須傳入兩個運算元n1,n2,並預期=號接收新結果物件n3
      WholeNumber n3 = WholeNumber.add(n1, n2);

      // n3:7 = n1:3 + n2:4
      System.out.printf("n3:%s = n1:%s + n2:%s\n", n3, n1, n2);
    }
  } 


(2) 類別方法,結果覆蓋原物件
 public class WholeNumber
 {
    public int number;

    public WholeNumber(int n)
    {
      this.number = n;
    }

    public String toString()
    {
      return String.format("%d", number);
    }

    public static void add(WholeNumber n1, WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = n1.number + n2.number;
      n1.number = n.number;
    }

    public static void main(String args[])
    {
      WholeNumber n1 = new WholeNumber(3);
      WholeNumber n2 = new WholeNumber(4);
      WholeNumber n1_copy = new WholeNumber(3);

      // 呼叫加法運算時,須傳入兩個運算元n1,n2,並預期n1由結果覆蓋
      WholeNumber.add(n1, n2);<

      // n1:7 = n1:3 + n2:4
      System.out.printf("n1:%s = n1:%s + n2:%s\n", n1, n1_copy, n2);
    }
  } 


(3) 物件方法,回傳結果
 public class WholeNumber
 {
    public int number;

    public WholeNumber(int n)
    {
      this.number = n;
    }

    public String toString()
    {
      return String.format("%d", number);
    }

    public WholeNumber add(WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = this.number + n2.number;
      return n;
    }

    public static void main(String args[])
    {
      WholeNumber n1 = new WholeNumber(3);
      WholeNumber n2 = new WholeNumber(4);

      // 呼叫加法運算時,只額外傳入運算元n2,並預期=號接收新結果物件n3
      WholeNumber n3 = n1.add(n2);

      // n3:7 = n1:3 + n2:4
      System.out.printf("n3:%s = n1:%s + n2:%s\n", n3, n1, n2);
    }
 } 


(4) 物件方法,結果覆蓋原物件
 public class WholeNumber
 {
    public int number;

    public WholeNumber(int n)
    {
      this.number = n;
    }

    public String toString()
    {
      return String.format("%d", number);
    }

    public void add(WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = this.number + n2.number;
      this.number = n.number;
    }

    public static void main(String args[])
    {
      WholeNumber n1 = new WholeNumber(3);
      WholeNumber n2 = new WholeNumber(4);
      WholeNumber n1_copy = new WholeNumber(3);

      // 呼叫加法運算時,只額外傳入運算元n2,並預期n1由結果覆蓋
      n1.add(n2);

      // n1:7 = n1:3 + n2:4
      System.out.printf("n1:%s = n1:%s + n2:%s\n", n1, n1_copy, n2);
    }
 }


B.四種加法運算的整合設計範例如下,將四種寫法合併成一支類別,方便比較四種用法的不同:


 class WholeNumber
 {
    public int number;

    // 建構子
    public WholeNumber(int n)
    {
      this.number = n;
    }
    
    // 拷貝建構子
    public WholeNumber(WholeNumber n)
    {
      this.number = n.number;
    }

    // 列印方法
    public String toString()
    {
      return String.format("%d", number);
    }

    // 類別方法,結果由新物件回傳
    public static WholeNumber classAddReturn(WholeNumber n1, WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = n1.number + n2.number;
      return n;
    }

    // 類別方法,結果覆蓋n1物件
    public static void classAddOverwrite(WholeNumber n1, WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = n1.number + n2.number;
      n1.number = n.number;
    }

    // 物件方法,結果由新物件回傳
    public WholeNumber instanceAddReturn(WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = this.number + n2.number;
      return n;
    }

    // 物件方法,結果覆蓋本物件
    public void instanceAddOverwrite(WholeNumber n2)
    {
      WholeNumber n = new WholeNumber(0);
      n.number = this.number + n2.number;
      this.number = n.number;
    }

    // 測試四種加法的主程式
    public static void main(String args[])
    {
      WholeNumber n1,n2,n3,n4,n1_copy;
      
      n1 = new WholeNumber(3);
      n2 = new WholeNumber(4);
      
      // 呼叫加法運算時,須傳入兩個運算元n1,n2,並預期=號接收新結果物件n3
      n3 = WholeNumber.classAddReturn(n1, n2);
      
      // n3:7 = n1:3 + n2:4
      System.out.printf("n3:%s = n1:%s + n2:%s\n", n3, n1, n2);


      n1_copy = new WholeNumber(n1);
      // 呼叫加法運算時,須傳入兩個運算元n1_copy,n2,並預期n1_copy由結果覆蓋
      WholeNumber.classAddOverwrite(n1_copy, n2);
      
      // n1:7 = n1:3 + n2:4
      System.out.printf("n1:%s = n1:%s + n2:%s\n", n1_copy, n1, n2);


      // 呼叫加法運算時,只額外傳入運算元n2,並預期=號接收新結果物件n4
      n4 = n1.instanceAddReturn(n2);

      // n4:7 = n1:3 + n2:4
      System.out.printf("n4:%s = n1:%s + n2:%s\n", n4, n1, n2);


      n1_copy = new WholeNumber(n1);
      // 呼叫加法運算時,只額外傳入運算元n2,並預期本物件n1_copy由結果覆蓋
      n1_copy.instanceAddOverwrite(n2);

      // n1:7 = n1:3 + n2:4
      System.out.printf("n1:%s = n1:%s + n2:%s\n", n1_copy, n1, n2);
    }
 } 

Virtual Machine Spec for Google Colab Environment

Google Colab提供最多12小時連線的Jupyter Notebook開發環境,其2018年底層的虛擬機實測規格如下:

CPU: Intel(R) Xeon(R) TwinCore @ 2.20GHz x 2

Memory: 13GB

Drive: 347GB

GPU: Tesla K80 with 4992 cores at 556MHz + 11GB Memory

OS: Ubuntu 18.04.1 LTS

Time Limit: 12 hours

規格實測的python指令如下:

# https://stackoverflow.com/questions/48750199/google-colaboratory-misleading-information-about-its-gpu-only-5-ram-available
# memory footprint support libraries/code
!ln -sf /opt/bin/nvidia-smi /usr/bin/nvidia-smi
!pip install gputil
!pip install psutil
!pip install humanize
import psutil
import humanize
import os
import GPUtil as GPU
GPUs = GPU.getGPUs()
# XXX: only one GPU on Colab and isn? guaranteed
gpu = GPUs[0]
def printm():
 process = psutil.Process(os.getpid())
 print("Gen RAM Free: " + humanize.naturalsize( psutil.virtual_memory().available ), " | Proc size: " + humanize.naturalsize( process.memory_info().rss))
 print("GPU RAM Free: {0:.0f}MB | Used: {1:.0f}MB | Util {2:3.0f}% | Total {3:.0f}MB".format(gpu.memoryFree, gpu.memoryUsed, gpu.memoryUtil*100, gpu.memoryTotal))
printm()

!df
!cat /etc/issue
!nvidia-smi
!nvidia-smi -L

!cat /proc/cpuinfo
!cat /proc/meminfo

create bootable iso from windows installation files

如果擁有 Windows 作業系統安裝檔案,可以利用 ImgBurn 軟體,將微軟安裝目錄製作成.iso,方便虛擬機安裝作業系統之用。 其關鍵步驟在選擇正確開機檔案,及載入磁區數目。重要參數如下:
  1.Source: Windows作業系統安裝檔案位置
  2.Destination: .iso檔案位罝
  3.Advanced/Bootable Disc
     Make Image Bootable
       Emulation Type: None (Custom)
       Boot Image: \boot\etfsboot.com
       Platform ID: 80x86
       Developer ID: Microsoft Corporation
       Load Segment: 07C0
       Sectors To Load: 8
  4.Build

  其中,載入磁區數目為 8,推測是因為 etfsboot.com 檔案為4KB,佔512B磁區8個。

參考: Youtube: How to create a Bootable ISO Image *from* a Bootable USB Drive

how to decode web content in gzip or deflate format using Java API?

有些網站回傳網頁會進行內容壓縮,壓縮方法常見有gzip或deflate,
可由回傳內容的ContentEncoding標頭決定如何處理回傳的壓縮內容。

以Java為例,解壓縮寫法如下:


      // 設定下載網址
      URL url = new URL("http://comment.bilibili.tv/29545595.xml");  
      HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
      //conn.setRequestProperty("Accept-Encoding", "identity");

      // 連線取得網頁輸入流
      conn.connect();  
      System.out.printf("con.getContentEncoding()=%s\n",conn.getContentEncoding());
      InputStream in = conn.getInputStream();

      if(conn.getContentEncoding().equals("gzip"))
          in = new GZIPInputStream(conn.getInputStream());  

      if(conn.getContentEncoding().equals("deflate"))
          in = new InflaterInputStream(conn.getInputStream(), new Inflater(true));

      // 從網頁輸入流列印內容到螢幕
      BufferedReader bin = new BufferedReader(new InputStreamReader(in, "UTF-8"));  
      String s = null;  
      while((s=bin.readLine())!=null){  
         System.out.println(s);  
      }  
      bin.close();

what is the use of the ROC curve in data mining?

對於多類別的分類問題,ROC(Receiver Operating Characteristic,接收器作業特徵值)曲線圖 可用來觀察分類器在參數不同鬆緊設定下,預測某特定類別值的表現情形。 因此,ROC曲線圖適合用來調整參數,呈現對於不同類型分類錯誤的取捨結果。

假設雙類別問題中,資料集案例數陽遠少於陰,因此比較關心陽類別的預測表現。 則ROC平面可定義成 橫軸為偽陽率(陰預測為陽比率,False Positive Rate)=FP/(FP+TN),又稱錯誤命中率、假警報率,其值相當於(1-特殊度); 縱軸為真陽率(陽預測為陽比率,True Positive Rate)=TP/(TP+FN),又稱召回率、敏感度、偵測率。

假設分類器可預測案例為陽的機率,則給定陽機率門檻參數可決定案例類別如下: 若預測機率高於門檻,則案例歸為陽,否則歸為陰。 因此,陽機率門檻參數的調整將位於如下兩種極端情況之間:

  1. 惜口如金,嚴苛型參數: 設定陽機率門檻很高,很少案例歸為陽,但判斷為陽的案例其正確率也很高。 由於多數案例判斷為陰,因此本來是陽誤歸為陰的機會增加,即第一類錯誤較多。
  2. 來者不拒,寬鬆型參數: 設定陽機率門檻很低,很多案例歸為陽,但判斷為陽的案例其正確率也很低。 由於多數案例判斷為陽,因此本來是陰誤歸為陽的機會增加,即第二類錯誤較多。

由上面可以知道,機率門檻參數的調整基本上就是在第一類錯誤及第二類錯誤之間作取捨。 如果第一類錯誤較可容忍,第二類錯誤較不可容忍,參數要調向嚴苛方向,即門檻要調高; 反之如果第一類錯誤較不可容忍,第二類錯誤較可容忍,參數要調向寬鬆方向,即門檻要調低。 因此,繪製ROC曲線的目的就在顯示不同分類錯誤的取捨結果。

ROC曲線畫法如下: 設定陽機率門檻變化由最嚴1到最鬆0,將各門檻值的分類器表現,其偽陽率及真陽率的交點連線起來,形成ROC曲線圖。 其中,若將所有案例依預測為陽的機率由大到小排序,則橫軸的偽陽率相當於機率在陽機率門檻值以上的陰案例出現比例; 縱軸的真陽率相當於機率在陽機率門檻值以上的陽案例出現比例。 ROC曲線由左到右表示,某分類器從預測陽性全不容許錯到完全容許錯之間,所有陽案例出現比例的變化。 對角直線由左到右表示,隨機分類器從0%全預測為陽,到100%全預測為陽,所有陽案例出現比例的變化。 任一分類器只要ROC曲線位於對角線上方就比隨機分類器好,離的越遠,越靠近左上角越好。

例如,使用 Weka 的 簡單貝氏分類器(NaiveBayes) 套用到內附的 乳癌案例集 (breast-cancer.arff)。 此案例集的雙類別分佈為: 無復發事件(no-recurrence-events)201例,有復發事件(recurrence-events)85例。 顯然復發案例較少,因此我們將針對復發預測進行門檻調整,畫出復發預測的ROC曲線圖如下。 此曲線圖橫軸(X)為偽陽率或假警報率,縱軸(Y)為真陽率或偵測率。

若照預設的陽機率門檻0.5,則凡是案例預測為陽的機率高於門檻者,皆視為陽(即復發)。 所以系統在偽陽率=16.4%之下,可以達到真陽率=43.5%。 表示若允許16.4%的假警報錯誤,則偵測率可達43.5%。 曲線圖上每個點表示1個案例,最右上為預測為陽機率接近0的案例,最左下為預測為陽機率接近1的案例, 中間案例則按預測為陽機率由低(曲線右上)到高(曲線左下)依序擺放。 因此,位居分界線的門檻案例約略落在1(曲線右上)起算第215個案例的預測機率位置上。 凡機率在門檻案例以上(曲線往左)者皆預測為陽性(即復發),以下(曲線往右)者皆預測為陰性(即不復發)。 有關第215個排序的門檻案例,其相關資訊如下:

此時的混淆矩陣長相如下:

分類判斷為陽分類判斷為陰
案例實際為陽真陽性(TP=37)偽陰性(FN=48)
案例實際為陰偽陽性(FP=33)真陰性(TN=168)

如果調升陽機率門檻大於0.5門檻,也就是變嚴苛、不容錯,由ROC曲線可以看到,門檻案例的分界線將往曲線左方移動。 也就是偽陽率變低,但是真陽率也將跟著變低。最極端情況,陽機率門檻設為1,偽陽率及真陽率將雙雙落為0,也就是不容假警報錯誤下,偵測率將為0%。 此時的混淆矩陣長相如下,所有案例都處於預測為陰的過於保守情況:

分類判斷為陽分類判斷為陰
案例實際為陽真陽性(TP=0)偽陰性(FN=85)
案例實際為陰偽陽性(FP=0)真陰性(TN=201)

反之,如果調降陽機率門檻小於0.5門檻,也就是變寬鬆、更容錯,由ROC曲線可以看到,門檻案例的分界線將往曲線右方移動。 也就是偽陽率變高,但是真陽率也將跟著變高。最極端情況,陽機率門檻設為0,偽陽率及真陽率將雙雙達頂1,也就是完全容許假警報錯誤下,偵測率將為100%。 此時的混淆矩陣長相如下,所有案例都處於預測為陽的過於積極情況:

分類判斷為陽分類判斷為陰
案例實際為陽真陽性(TP=85)偽陰性(FN=0)
案例實際為陰偽陽性(FP=201)真陰性(TN=0)

所以畫出分類器的某類別ROC曲線圖可以輔助用戶在偽陽率及真陽率之間,也就是容許假警報錯誤及偵測率之間作取捨,道理在此。 取捨的依據就是調整預測為陽的機率門檻,在適當鬆緊之間,找到一個平衡點,能同時滿足自己可容許的假警報率及希望的偵測率。

另外,每個分類器在ROC平面,依陽機率門檻值的變化可以畫出一條ROC曲線。此曲線底下的面積稱為AUC(Area Under the Curve)。 AUC值最大為1,最小為0,值越大越好,可表示任抽一個陽案例及陰案例,分類器會讓陽案例的位置排在陰案例之前的機率。 隨機分類器的ROC曲線為一左下到右上的對角直線,其AUC值為0.5,表示任抽一陽一陰,陽會排在陰之前的機率為0.5。

    註:
  1. An Introduction to ROC Analysis
  2. ROC曲線
  3. 混淆矩陣定義如下:
    分類判斷為陽分類判斷為陰
    案例實際為陽真陽性(TP, True Positive)偽陰性(FN, False Negative)
    案例實際為陰偽陽性(FP, False Positive)真陰性(TN, True Negative)

Summary of Java Collection Framework

Java API 提供收藏架構(Collection Framework),內含眾多寫好的記憶體容器,即資料結構。
收藏架構的容器支援泛型,可儲存任意物件當元素。
架構當中,介面負責制定容器操作的方法規格,類別負責實作眾多介面規格。
收藏介面是整個架構的根介面,此容器模擬一個收納袋(bag)或多值集合(multiset)的運作,
值可重複,無位置概念,但可詢問是否包含某元素。如果想列舉內容,可取得容器的迭代器,進行元素的列舉。
以下摘要幾種常用的容器介面,及其實作類別。

A.介面
  Collection 收藏:    放個別物件,  可重複放,無位置概念,無排序
  List 清單:          放個別物件,  可重複放,任意位置概念,無排序
  Queue 佇列:         放個別物件,  可重複放,頭位置概念,無排序
  Deque 佇列:         放個別物件,  可重複放,頭尾概念,無排序
  Set 集合:           放個別物件,不可重複放,無位置概念,無排序
  SortedSet 有序集合: 放個別物件,不可重複放,有頭尾概念,有排序
  Map 映射:           放成對物件,不可重複放,無位置概念,無排序
  SortedMap 有序映射: 放成對物件,不可重複放,有頭尾概念,有排序

B.類別
  Collection:   Vector,Stack,ArrayList,ArrayBlockingQueue,
  LinkedList,PriorityQueue,HashSet,TreeSet,...
  List:  Vector,Stack,ArrayList,LinkedList,...
  Queue: LinkedList,PriorityQueue,ArrayBlockingQueue,...
  Deque: ArrayDeque,LinkedList,LinkedBlockingDeque,...
  Set:  HashSet,TreeSet,LinkedHashSet,...
  SortedSet: TreeSet,...
  Map:  HashMap,TreeMap,HashTable,Properties,...
  SortedMap: TreeMap,...

  註: Vector (向量) 和 ArrayList (陣列清單) ,兩者差異在前者支援多緒安全性,後者無
      HashTable (雜湊表) 和 HashMap (雜湊映射), 兩者差異也在前者支援多緒安全性,後者無
      HashTable (雜湊表) 和 Properties (屬性表),兩者差異在後者多了檔案輸出入功能

C.收藏架構圖 (介面方法區分唯讀及讀寫兩類)

regular expressions (a|b) and [ab] are the same?

正規式 (a|b) 和 正規式 [ab] 兩者皆可匹配1個a或1個b,所以匹配效果一樣。
但是兩者的語法不同,表達能力也不同,說明如下:
[]表示匹配中括號(bracket)內字元集合的一個字元,所以只能匹配1個字元;
()表示匹配小括號(parenthesis)內直槓(vertical bar,|)隔開的任一正規式,所以可能匹配不止1個字元。

例如: 
1.正規式 hello 匹配 hello 5個字元
2.正規式 [hello] 匹配 h或e或l或o 任1個字元
3.正規式 (hello) 匹配 hello 5個字元
4.正規式 (hello|world) 匹配 hello 或 world 5個字元
5.正規式 ([hello]|world) 匹配 h或e或l或o 任1個字元  或 world 5個字元

參考:
difference b/w [ab] and (a|b) in regex match?

Use a jupyter and docker environment for learning tensorflow

想要學習Google的開源機器學習套件tensorflow,可以研讀網路上很多Python語言寫的程式範例。
但是,要讓自己的機器能跑得動這些Python寫的tensorflow範例,首先須跨越2個門檻:

1.安裝Python: 
    Python語法分Python2及Python3,IDE介面分jupyter及spyder等,套件管理分anaconda,pip等,
    在選擇眾多之下判斷及安裝皆費時。

2.安裝tensorflow: 
    除了依硬體分成CPU,GPU兩版,軟體也依Windows, Ubuntu, MacOS三種不同作業系統,而分成
    virtualenv、pip、anaconda、docker、原始碼等多種安裝法,各有不同安裝步驟及參數要設定。
    尤其安裝過程到底是使用 Python2 或 Pyhton3 也很容易因此而發生相容性問題。

以下介紹一個利用docker容器原理,快速建立執行tensoflow環境的作法:

1.安裝 docker 容器管理軟體:
    https://www.docker.com/community-edition#/download
       分成 Windows, Linux, Mac等免費版本,下載安裝合適公用版(community edition)
    其中,Windows 10可直接安裝 Docker CE for Windows,內含Windows及Linux兩種核心引擎
    若 Windows 非第10版,建議在Linux虛擬機環境下使用Docker,依序安裝如下軟體:
         VirtualBox Binaries Windows hosts + Ubuntu Desktop + Docker CE for Ubuntu

2.下載 jupyter/tensorflow-notebook 容器映像檔:
    https://hub.docker.com/r/jupyter/tensorflow-notebook/
    利用如下 docker 指令下載容器映像檔,內含Scipy Notebook + Tensorflow and Keras for Python 3.x (without GPU support)
    # docker pull jupyter/tensorflow-notebook
    註: 本映像檔可由如下github提供的 Dockerfile 從Ubuntu製成
         https://github.com/jupyter/docker-stacks/tree/master/tensorflow-notebook 
         https://github.com/jupyter/docker-stacks/tree/master/scipy-notebook
         https://github.com/jupyter/docker-stacks/tree/master/minimal-notebook
         https://github.com/jupyter/docker-stacks/tree/master/base-notebook
         Ubuntu 16.04 (xenial)

3.下載 nfmcclure/tensorflow_cookbook 程式範例:
    https://github.com/nfmcclure/tensorflow_cookbook
    利用如下 git 指令下載範例
    > git clone https://github.com/nfmcclure/tensorflow_cookbook.git
    或
    點選[Download ZIP]下載範例壓縮檔解開

    註: TensorFlow Machine Learning Cookbook範例採用 Pyhton3 撰寫

4.啟動執行範例:
    假設程式範例位於/home/user/docker/tensorflow_cookbook,網頁連線埠為8080,
    則可利用如下指令啟動容器:
    # docker run -it --rm \
        -p 8080:8888 \
        -v /home/user/docker/tensorflow_cookbook:/work \
        --name tflow jupyter/tensorflow-notebook \
        start-notebook.sh --NotebookApp.token='demo' --NotebookApp.notebook_dir='/work'

    然後開啟瀏覽器,利用網址 http://localhost:8080,密碼 demo,連到容器,執行tensorflow範例。

    註: docker run imagePath 指令可將映像檔imagePath放入容器執行,猶如虛擬機開機一般,其參數說明如下:
        -it 保留終端機供互動用,按Ctrl-C可結束容器
        --rm 容器結束時,容器也自動刪除
        -p 8080:8888 將容器內部的8888埠對應到主機的8080埠,供外部使用
        -v outerPath:innerPath 將主機的outerPath目錄掛載到容器內部的innerPath目錄,方便內外硬碟資料共享
        --name tflow 為容器命名為tflow,方便之後取用
        jupyter/tensorflow-notebook 為映像檔在docker hub的標準名稱
        start-notebook.sh  為容器啟用後執行的批次檔,主要啟動jupyter notebook,允許預設8888埠網頁連線
        --NotebookApp.token='demo' 設定網頁連線密碼 demo,以防外人取用
        --NotebookApp.notebook_dir='/work' 設定notebook初始開檔目錄,設為/work可以對應到掛載進來的外部範例目錄,方便取用

   註: 利用docker容器啟動包含jupyter notebook及tensorflow環境的容器,執行tensorflow範例程式的長相如下:

how to call Java classes in a web page by cheerpj

🚀 在瀏覽器中直接執行 Java:CheerpJ v3 實作指南 長期以來,Java Applets 因為安全性與插件問題早已退出歷史舞台。但隨著 WebAssembly (Wasm) 技術的成熟,現在網頁安裝如下 CheerpJ v3 套件庫,就可以在瀏覽器中直接呼叫 ...

總網頁瀏覽量