003.00 監督式學習

Jason990420發表於2019-09-17

003.00 監督式學習

建檔日期: 2019/09/17
更新日期: None
語言: Python 3.7.4, urllib3 1.25.3, numpy 1.16.4, matplotlib 3.1.0, Pillow 6.1.0
系統: Win10 Ver. 10.0.17763

主題: 003.00 監督式學習

前言:

看到人工智慧, 機器學習, 再到深度學習, 一大堆雜七雜八的資料, 得花多久的時間才能搞懂作什麼, 先找了一個範例, 這個範例是採用100張的明星照片, 建立一個模型用來分辨照片中的明星是男是女, 先區分為80張的訓練組及20張的測試組, 除了圖片以外, 還要自行確認每張照片中的明星是男是女, 建立性別資料. 該模型輸出只有兩種類別, 男或女, 或者說是不是男的, 或者說是不是女的, 這是一種二選一分類的模型, 不同的功能會有不同的模型, 這裡採用的是邏輯迴歸的演算法.

本範例主要的是採用numpy來作所有的處理, 而不是如其的人工智慧庫給你一個函式, 什麼都作完了, 這樣你不會清楚知道發生什麼事. 在本範例中瞭解了整個模型建構及演算法細節, 感覺在人工智慧上跨了一大步.

範例來源: https://datascienceintuition.wordpress.com...

要一步一步的說明細節, 不如看下圖比較直接, 後面再稍作解釋, 就容易看懂了.

Python

1. 準備資料作為輸入

a. 照片來源

照片當然可以自己拍, 不過挺花時間的, 在學習階段, 直接上網下載就行, 網上有很多資料庫免費提供, 比如: https://lionbridge.ai/datasets/the-50-best....


一般的庫大都是一行就下載下來, 這裡是從網頁中讀取100張的照片, 存放到子目錄中, 下次就不用再下載一次

def load_100_pictures():
    if not os.path.exists('img_align_celeba'):
        os.mkdir('img_align_celeba')
        for img_i in range(1, 101):
            f = '000%03d.jpg' % img_i
            url = 'https://s3.amazonaws.com/cadl/celeb-align/' + f
            print(url, end='\r')
            urllib.request.urlretrieve(url, os.path.join('img_align_celeba', f))
    print('Celeb Net dataset already downloaded')
b. 資料分為兩群, 訓練群及測試群.

一般測試群大約佔1/4資料, 這個比例可以自行分配. 訓練群用來讓模型找到自己內部最佳的引數, 也就是wi及b. 測試群用來測試最後模型的準確性.

c. 照片為jpg檔

每一個畫素都含有三個0~255的R,G,B值, 光的三要素R(紅),G(綠),B(藍)合成在一起, 才是該畫素的顏色.

d. 照片資料的shape為(100張, 218高, 178寛, 3色)

在輸入到模型中, 必須先處理一下, 才能符合模型的輸入要求. 除了簡單化, 也可以減少記憶體的使用和處理的時間. 不過, 過度的簡化可能會造成資訊量的流失, 造成模型建造失敗.

e. 每張照片高218畫素, 寛178畫素

我們先裁成(178, 178)的正方形. 照片群就變成(100張, 178高, 178寛, 3色), 資料量一下就少了20%左右.

def imcrop_tosquare(img):
    if img.shape[0] > img.shape[1]:
        extra = (img.shape[0] - img.shape[1]) // 2
        crop = img[extra:-extra, :]
    elif img.shape[1] > img.shape[0]:
        extra = (img.shape[1] - img.shape[0]) // 2
        crop = img[:, extra:-extra]
    else:
        crop = img
    return crop
f. 將照片的尺寸由(178, 178)改為(64, 64)

縮小的照小在人眼看來, 仍然可以輕易辨認出性別來. 照片群就變成(100張, 64高, 64寛, 3色), 因為這個尺寸是以平方來計算的, 所以資料量一下就少了87%左右, 總計資料量只有約原來的10%. 當然, 我們還可以再把RGB三色轉換為灰階, 資料量就會變成只有約原來的3.3%, 不過我們還是保留沒有這樣作, 當然各位可以試試.

imgs = []
for file_i in files:
    # 照片格式都是(218, 178, 3), 高218, 寛178, RGB三色/每點
    img = plt.imread(file_i)
    # 裁成(178,178,3), 正方形照片
    square = imcrop_tosquare(img)
    # 以LANCZOS方法來重設大小為(64,64,3),
    # 足以辨識就可以了, 照片太大, 處理時間與記憶體都會佔用太多
    rsz = np.array(Image.fromarray(square).resize((64, 64), resample=Image.LANCZOS))
    # list結果為(100, 64, 64, 3), 100筆, 64x64, RGB三色的照片資料
    imgs.append(rsz)
g. 再把資料從 0 ~ 255 轉為 0 ~ 1

在邏輯迴歸計算時, 有使用到指數的運算, 大於1的數, 很容易就會造成系統數值溢位錯誤.

data = np.array(imgs)/255
h. 建立資料標籤

照片資料中並沒有我們所要的性別資料, 所以我們要自己看照片判斷建立. 還有建立兩個分類的標籤['Male 男', 'Female 女'], 這裡我們定義0為男性, 1為女性.

classes=np.array(['Male', 'Female'])
y=np.array([1,1,0,1,1,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,1,0,1,1,1,1,0,1,0,0,1,1,0,0,0,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,1,0,0,1,0,0,0,0,1,0,1,1,1,0,1,1,0,0,0,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1])
y=y.reshape(1,y.shape[0])
i. 把照片分為兩群, 訓練群及測試群
train_x_orig=data[:80,:,:,:]
test_x_orig=data[80:,:,:,:]
y_train=y[:,:80]
y_test=y[:,80:]
j. 最後我們要把二維的畫素資料轉換為一維的畫素資料

這樣才能符合模型的輸入要求. 轉換的方式是把每一行的點連續接在一起再轉置, 如此一來, 訓練組照片從(80, 64, 64, 3)變為(12288,80), 測試組照片從(20,64,64,3)變為(12288,20).

# 訓練資料80筆, 測試資料20筆, 照片每邊64點
m_train = train_x_orig.shape[0]
m_test = y_test.shape[1]
num_px = train_x_orig.shape[1]
# (80, 64, 64, 3) -> (1228,80), (20,64,64,3) -> (1228,20)
train_x = train_x_orig.reshape(train_x_orig.shape[0],-1).T
test_x = test_x_orig.reshape(test_x_orig.shape[0],-1).T

2. 對每一筆輸入訓練用資料的特徵值X或xi隨意設定權重W或wi, 並隨意設定一個偏差值b

在這裡, 簡單為主, 我們都設為0

    w = np.zeros((1,12288))
    b = 0

3. 計算sigma, Σ值

只要在計算前把矩陣的shape, 也就是資料擺對方向及位置, 就會很容易計算, 這也是numpy陣列強大的所在, 簡單的一個運算就把事情作完了.

sigma =np.dot(w,X)+b

4. 使用sigmoid函式

將Σ作非線性轉換成-1 ~ 1的數值, 得到我們的預測值A或a, A中的每一項a就代表該照片經模型預測的性別結果, 因為在模型中, 利用預測A與實際Y的差異去調整權重wi及偏差b, 以得到更接近實際Y的預測A, 這也是負回饋的一種應用.

def sigmoid(z):
    # 建立sigmoid函式, 將輸入值非線性轉換為-1~+1的數值
    s = 1/(1+np.exp(-z))
    return s
A = sigmoid(np.dot(w,X)+b)

5. 以邏輯迴歸的方式, 計算誤差值

這裡稱為成本cost, 原則上, cost越小越好, 因為cost可以代表所有預測值與實際值的差異或誤差值總和.

cost = (-1/m)*(np.dot(Y,np.log(A.T))+ np.dot((1-Y),np.log((1-A).T)))

6. 根據輸入的特徵值, 預測值及測試用的實際值, 計算成本對權重wi的導數dw (實際上是dcost/dw), 以及對偏差值b的導數db (實際上是dcost/db)

在sigma Σ中, xi不是一個變數, 是已知的輸入資料, wi及b才是在模型作訓練時的變數, 所以我們要對wi及b來求導數, 用來作為迴歸方法中的反饋引數. 導數代表的意義是指該變數的變化量, 所造成輸出的變化量, 導數值越大, 變化量越大, 我們要調整wi或b的量就越大, 越接近最低點, 導數值就越小, 一直到導數值為0, 或足夠接近0, 最低點的導數或斜率就是0.

    dw = (1/m)*np.dot((A-Y),X.T)
    db = (1/m)*np.sum((A-Y))

7. 根據成本對權重wi的導數,對偏差值b的導數, 以及alpha或α, 修改wi及b

這裡的alpha或α, 用來對調整的量作一個限制, 因為調整太多, 會找不到最低點, 調整太少會花太多的時間在調整上, 所以alpha或α被稱為學習速率. 一般來說, alpha值大都在1以下, 當然也有使用1以上的情況, 甚至可能是上千. 這個值的設定是隨情況而定的, 也可以說是試出來的.

        w = w-learning_rate*dw
        b = b-learning_rate*db

8. 重複N次步驟3到步驟7, 得到最小的cost, 最適當的wi及b值.

N是模型更新wi及b的次數, 多少次才是對的, 這是不一定的, 因為要看模型的複雜度, alpha值的選擇, 通常有個上限, 因為作得再多次, 結果變化也不大. 模型中所用的方法是數值分析的一種, 基本上, 作的更多次, 會更靠近目標點, 只是更靠近, 並不一定會落在目標點上. 簡單的模型, 可能很快就可以找到目標點, 但在複雜的模型中, 作得太多次可能會更糟糕, 這種情形就叫作over-fitting過度擬合或過適, 因為這裡追求的是訓練組的磨合, 結果可能測試組的結果變差了, 而我們真正要的結果是測試組的結果.

9. 使用該模型, 根據已知最適當的wi及b值, 計算出訓練組資料的預測值

與實際值作比較, 確認訓練後的正確率是否夠好, 不夠好可以調整alpha值及N值, 也有可能是該模型的建構方式無法符合要求, 必須採用不同的模型來重新訓練及測試.

10. 使用該模型, 根據已知最適當的wi及b值, 計算出測試組資料的預測值

與實際值作比較, 確認訓練後, 該模型的正確率是否夠好, 是否可以適用到一般的應用上.

結論: 本文所述的模型因為簡單, 所以在輸入層與輸出層中, 只有一層的wi及b, 所計算出來的訓練組正確率達到100%, 但測試組的正確率卻只有65%, 可以有很多的方式來改善, 比如:

  • 這裡用的梯度下降法是最常用的方法, 但只能在簡單的模型中找到目標點; 在複雜的模型中可能只是找到區域性的目標點, 而不是全域性的目標點.
  • 使用更多層的wi和b, 這代表更復雜的模型, 在很多人工智慧的建模都可以看到, 如下圖.
  • 資料量的保留, 縮減通常會造成資訊的流失
  • 改變不同的演算法, 比如模型中的sigma Σ, sigmoid, cost, 迴歸法等等

Python

輸出結果:

運算次數與cost的對照表
Python
測試組中預測錯誤的七張照片
Python
原照片與經加權/偏移計算的照片比對
Python

附件(程式)

# -*- coding: utf-8 -*-
import os
import urllib.request
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

def load_100_pictures():
    if not os.path.exists('img_align_celeba'):
        os.mkdir('img_align_celeba')
        for img_i in range(1, 101):
            f = '000%03d.jpg' % img_i
            url = 'https://s3.amazonaws.com/cadl/celeb-align/' + f
            print(url, end='\r')
            urllib.request.urlretrieve(url, os.path.join('img_align_celeba', f))
    print('Celeb Net dataset already downloaded')

# 從網站下載100張明星照片, 在到img_align_celeba目錄下, 如果目錄已存在, 就不下載了
load_100_pictures()
# 從目錄中取得所有JPG檔案的檔名(長度100的list)
files = [os.path.join('img_align_celeba', file_i) for file_i in os.listdir('img_align_celeba') if '.jpg' in file_i]

# 自行建立一個陣列, 內容為各照片中明星的性別, 0為男性, 1為女性
# shape從(100,)改為(1,100)
y=np.array([1,1,0,1,1,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,1,0,1,1,1,1,0,1,0,0,1,1,0,0,0,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,1,0,0,1,0,0,0,0,1,0,1,1,1,0,1,1,0,0,0,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1])
y=y.reshape(1,y.shape[0])

# 建立分類標籤內容'Male', 'Female'
classes=np.array(['Male', 'Female'])

# 目標分為兩群, 前80張為訓練用群, 後20張為測試群
y_train=y[:,:80]
y_test=y[:,80:]

# 擷取照片成最大的正方形
def imcrop_tosquare(img):
    if img.shape[0] > img.shape[1]:
        extra = (img.shape[0] - img.shape[1]) // 2
        crop = img[extra:-extra, :]
    elif img.shape[1] > img.shape[0]:
        extra = (img.shape[1] - img.shape[0]) // 2
        crop = img[:, extra:-extra]
    else:
        crop = img
    return crop

# 讀入所有的照片
imgs = []
for file_i in files:
    # 照片格式都是(218, 178, 3), 高218, 寛178, RGB三色/每點
    img = plt.imread(file_i)
    # 裁成(178,178,3), 正方形照片
    square = imcrop_tosquare(img)
    # 以LANCZOS方法來重設大小為(64,64,3),
    # 足以辨識就可以了, 照片太大, 處理時間與記憶體都會佔用太多
    rsz = np.array(Image.fromarray(square).resize((64, 64), resample=Image.LANCZOS))
    # list結果為(100, 64, 64, 3), 100筆, 64x64, RGB三色的照片資料
    imgs.append(rsz)

# 降低資料大小, 避免在邏輯迴歸時, 指數運算造成系統數值溢位錯誤
data = np.array(imgs)/255

# 資料分為兩群, 前80張為訓練用群, 後20張為測試群
train_x_orig=data[:80,:,:,:]
test_x_orig=data[80:,:,:,:]

# 對只有兩種結果的事件, 採用邏輯迴歸法

# 訓練資料80筆, 測試資料20筆, 照片每邊64點
m_train = train_x_orig.shape[0]
m_test = y_test.shape[1]
num_px = train_x_orig.shape[1]

# (80, 64, 64, 3) -> (12288,80), (20,64,64,3) -> (12288,20)
train_x = train_x_orig.reshape(train_x_orig.shape[0],-1).T
test_x = test_x_orig.reshape(test_x_orig.shape[0],-1).T

# Initialize parameters W and b

def initialize_with_zeros(dim):
    # 建立w是一個內容都為0, 點數大小的陣列(1, 點數12288), b為0
    w = np.zeros((1,dim))
    b = 0
    # 確認w及b符合要求
    assert(w.shape == (1, dim))
    assert(isinstance(b, float) or isinstance(b, int))
    return w, b

def sigmoid(z):
    # 建立sigmoid函式, 將輸入值非線性轉換為-1~+1的數值
    s = 1/(1+np.exp(-z))
    return s

def propagate(w, b, X, Y):
    '''
    輸入
    w -- 加權陣列, 對應到一張照片所有的點的三顏色, (點數*3, 1) (12288, 1)
    b -- 偏差, 純量
    X -- 輸入的資料陣列, (點數*3, 訓練用照片數) (12288, 80)
    Y -- 結果卷標0, 1的陣列, (1, 訓練用照片數) (1, 80)

    輸出:
    cost -- 負對數可能值, 是邏輯迴歸法中的成本或誤差值
    dw -- dcost/dw, (點數*3, 1)
    db -- dcost/db, 純量

    '''
    m = X.shape[1]
    # 正向傳遞 (從輸入到成本 X -> cost), A預測值(1, 80), cost = -1/m*sum(y*log(a)+(1-y)*log(1-a)
    A = sigmoid(np.dot(w,X)+b)
    cost = (-1/m)*(np.dot(Y,np.log(A.T))+ np.dot((1-Y),np.log((1-A).T)))
    # 反向傳遞 (找出梯度grads), dZ=A-Y, dw = 1/m*(dZ . XT), db = mean(dZ)
    dw = (1/m)*np.dot((A-Y),X.T)
    db = (1/m)*np.sum((A-Y))
    assert(dw.shape == w.shape)
    assert(db.dtype == float)
    cost = np.squeeze(cost)
    assert(cost.shape == ())
    grads = {"dw": dw,
             "db": db}
    return grads, cost

def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):
    """
    利用梯度下降演算法優化 w, b

    輸入
    w -- 加權陣列, 對應到一張照片所有的點的三顏色, (點數*3, 1) (12288, 1)
    b -- 偏差, 純量
    X -- 所有輸入的資料陣列, (點數*3, 訓練用照片數) (12288, 80)
    Y -- 結果卷標0, 1的陣列, (1, 訓練用照片數) (1, 80)
    num_iterations -- 引數優化運算次數
    learning_rate -- 引數修正學習速率
    print_cost -- 是否每100次運算, 列印成本cost

    輸出
    params -- { } w, b
    grads -- {'dw':dw, 'db':db'} cost對w的導數, cost對b的導數
    costs -- [ ] 所有cost記錄, 供畫圖使用

    """

    costs = []

    for i in range(num_iterations):

        # 按輸入資料, 目標卷標, 模型中的權重及偏移值計算成本Cost及梯度
        grads, cost = propagate(w, b, X, Y)

        # 從grads中取回dw, db
        dw = grads["dw"]
        db = grads["db"]

        # 更新權重及偏差
        w = w-learning_rate*dw
        b = b-learning_rate*db

        # 每100次記錄下cost值
        if i % 100 == 0:
            costs.append(cost)

        # 是否每100次列印cost
        if print_cost and i % 100 == 0:
            print ("Cost after iteration %i: %f" %(i, cost))

    # 畫cost曲線
    plt.rcParams['figure.figsize'] = (10.0, 10.0)
    plt.plot(np.squeeze(costs))
    plt.ylabel('cost')
    plt.xlabel('iterations (per hundreds)')
    plt.title("Learning rate =" + str(learning_rate))
    plt.show()
    params = {"w": w, "b": b}
    grads = {"dw": dw, "db": db}

    return params, grads, costs

def predict(w, b, X):
    '''
    按已優化的 w, b 預測輸入的照片結果

    輸入
    w -- 模型中已優化的權重 (12288, 1)
    b -- 偏差值
    X -- 輸入料陣列 (12288, 照片數)

    輸出
    Y_prediction -- 預測結果
    '''

    m = X.shape[1]
    Y_prediction = np.zeros((1,m))
    #w = w.reshape(X.shape[0], 1)

    # 計算預測值, 並轉成0~1的機率值, 再四捨五入取整數
    A = sigmoid(np.dot(w,X)+b)
    Y_prediction=np.round(A)

    assert(Y_prediction.shape == (1, m))

    return Y_prediction

def model(X_train, Y_train, X_test, Y_test, num_iterations = 2000, learning_rate = 0.5, print_cost = False):
    """
    建立邏輯迴歸模型

    輸入引數
    X_train -- 訓練用輸入的資料陣列, (點數*3, 訓練用照片數) (12288, 80)
    Y_train -- 訓練用結果卷標0, 1的陣列, (1, 訓練用照片數) (1, 80)
    X_test -- 測試用輸入的資料陣列, (點數*3, 測試用照片數) (12288, 20)
    Y_test -- 測試用結果卷標0, 1的陣列, (1, 訓練用照片數) (1, 20)
    num_iterations -- 引數優化運算次數
    learning_rate -- 引數修正學習速率
    print_cost -- 是否每100次運算, 列印成本cost

    輸出:
    d -- { } 有關模型的資訊
    """

    # 初值選定 (1, 12288)
    m_train=X_train.shape[0]
    w, b = initialize_with_zeros(m_train)

    # 梯度下降優化
    parameters, grads, costs = optimize(w, b, X_train, Y_train, num_iterations= num_iterations, learning_rate = learning_rate, print_cost = print_cost)

    # 取出 w, b
    w = parameters["w"]
    b = parameters["b"]

    # 檢查訓練組及測試組
    Y_prediction_test = predict(w, b, X_test)
    Y_prediction_train = predict(w, b, X_train)

    # 列印檢查正確率
    print("train accuracy: {} %".format(100*(1 - np.mean(np.abs(Y_prediction_train - Y_train)) )))
    print("test accuracy: {} %".format(100*(1 - np.mean(np.abs(Y_prediction_test - Y_test)) )))

    d = {"costs": costs,
         "Y_prediction_test": Y_prediction_test,
         "Y_prediction_train" : Y_prediction_train,
         "w" : w,
         "b" : b,
         "learning_rate" : learning_rate,
         "num_iterations": num_iterations}

    return d

d = model(train_x, y_train, test_x, y_test, num_iterations = 1000, learning_rate = 0.005, print_cost = True)

def print_mislabeled_images(classes, X, y, p):
    """
    顯示在測試組判斷錯誤的照片
    X -- 照片資料組
    y -- 正確標籤組
    p -- 預測標籤組
    """
    a = p + y
    mislabeled_indices = np.asarray(np.where(a == 1))
    plt.rcParams['figure.figsize'] = (40.0, 40.0) # set default size of plots
    num_images = len(mislabeled_indices[0])
    for i in range(num_images):
        index = mislabeled_indices[1][i]

        plt.subplot(2, num_images, i + 1)
        plt.imshow(X[:,index].reshape(64,64,3), interpolation='sinc')
        plt.axis('off')
        plt.rc('font', size=10)
        plt.title("Prediction: " + classes[int(p[0,index])] + " \n Class: " + classes[y[0,index]])
    plt.show()

print_mislabeled_images(classes, test_x, y_test, d["Y_prediction_test"])

# 使用sinc函式來重建經過比重後的照片

test=d["w"].T*train_x*255
test=test.T.reshape(80,64,64,3)
plt.rcParams['figure.figsize'] = (10.0, 10.0)
plt.imshow(test[0], interpolation='sinc')

# reconstructed data by others

methods = [None, 'none', 'nearest', 'bilinear', 'bicubic', 'spline16',
           'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric',
           'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos']

# Fixing random state for reproducibility
np.random.seed(19680801)

fig, axes = plt.subplots(3, 6, figsize=(24, 12),
                         subplot_kw={'xticks': [], 'yticks': []})

fig.subplots_adjust(hspace=0.3, wspace=0.05)

for ax, interp_method in zip(axes.flat, methods):
    ax.imshow(test[0], interpolation=interp_method, cmap=None)
    ax.set_title(interp_method)

plt.show()

# compare the reconstructed images vs original.

def montage(images, saveto='montage.png'):
    """Draw all images as a montage separated by 1 pixel borders.
    Also saves the file to the destination specified by `saveto`.
    Parameters
    ----------
    images : numpy.ndarray
        Input array to create montage of.  Array should be:
        batch x height x width x channels.
    saveto : str
        Location to save the resulting montage image.
    Returns
    -------
    m : numpy.ndarray
        Montage image.
    """
    if isinstance(images, list):
        images = np.array(images)
    img_h = images.shape[1]
    img_w = images.shape[2]
    n_plots = int(np.ceil(np.sqrt(images.shape[0])))
    if len(images.shape) == 4 and images.shape[3] == 3:
        m = np.ones(
            (images.shape[1] * n_plots + n_plots + 1,
             images.shape[2] * n_plots + n_plots + 1, 3)) * 0.5
    else:
        m = np.ones(
            (images.shape[1] * n_plots + n_plots + 1,
             images.shape[2] * n_plots + n_plots + 1)) * 0.5
    for i in range(n_plots):
        for j in range(n_plots):
            this_filter = i * n_plots + j
            if this_filter < images.shape[0]:
                this_img = images[this_filter]
                m[1 + i + i * img_h:1 + i + (i + 1) * img_h,
                  1 + j + j * img_w:1 + j + (j + 1) * img_w] = this_img
    #plt.imsave(arr=m, fname=saveto)
    return m

compare = np.concatenate((test[52:54], data[52:54]), axis=0)
compare.shape

plt.imshow(montage(compare,saveto='montage.png'),interpolation='spline36')
plt.show()
plt.imshow(montage(compare,saveto='montage.png'),interpolation='bicubic')
plt.show()

# generate the montage with different interpolations for comparison.

methods = [None, 'none', 'nearest', 'bilinear', 'bicubic', 'spline16',
           'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric',
           'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos']

# Fixing random state for reproducibility
np.random.seed(19680801)

fig, axes = plt.subplots(3, 6, figsize=(24, 12),
                         subplot_kw={'xticks': [], 'yticks': []})

fig.subplots_adjust(hspace=0.3, wspace=0.05)

for ax, interp_method in zip(axes.flat, methods):
    ax.imshow(montage(compare,saveto='montage.png'), interpolation=interp_method, cmap=None)
    ax.set_title(interp_method)

plt.show()

Jason Yang

相關文章