顯示具有 scikit-learn 標籤的文章。 顯示所有文章
顯示具有 scikit-learn 標籤的文章。 顯示所有文章

2025年11月14日 星期五

Scikit-learn 機器學習筆記索引

學習 AI 已經好多年了, 之前大多集中於深度學習, 反而對最基礎的, 以 Scikit-learn 為中心之機器學習所整理的筆記卻很少, 我想將此做為 2026 年第一季的學習重心, 先把之前寥寥可數的幾篇從深度學習筆記索引中抽離出來以表重視與提醒 : 


~進行中~

參考書籍 :
  1. Python機器學習錦囊妙計
  2. 一行指令學Python : 用機器學習掌握人工智慧
  3. 精通機器學習 : 使用Scikit-Learn, Keras與TensorFlow (2023 第三版)
  4. 學AI真簡單. I, 初探機器學習 : 從認識AI到Kaggle競賽

2023年12月7日 星期四

機器學習筆記 : 用 Scikit-learn 的 make_blobs() 產生模擬資料集

這幾天在讀石川聰彥寫的 "必學! Pyton 資料科學機器學習最強套件" 這本書時, 在第 12 章看到 Scikit-Learn 內建資料集模組 datasets 裡面有一個 make_blobs() 函式可以用來產生隨機的模擬資料集, 我覺得這很好用, 就動手測試看看, 紀錄如下.  



Source : 博客來


make_blobs() 是 sklearn.datasets 模組裡面的函式, 使用前要先匯入 :

from sklearn.datasets import make_blobs   

此函式可傳入 4 個參數來產生隨機的模擬資料集 :

make_blobs(n_samples, n_features, centers [, random_state])

參數說明如下 :
  • n_samples : 欲產生的資料筆數
  • n_features : 特徵 (變數) 個數
  • centers : 資料的群數
  • random_state : 隨機種子
其中 centers 為資料的群數, 即標籤之數量, 例如 centers=2 則標籤為 [0, 1]; 若 centers=4, 則標籤為 [0, 1, 2, 3] 依此類推. random_state 參數可有可無, 指定隨機種子主要是固定亂數產出規則, 使每次產出的結果都一樣 (程式員常用 42, 這是有典故的). 

Python 3.11.3 (C:/Python311/python.exe)
>>> from sklearn.datasets import make_blobs    

先產出 10 筆隨機紀錄來檢視 :

>>> X, y=make_blobs(n_samples=10, n_features=2, centers=2, random_state=0)    

這會產生 10 筆有兩個特徵與兩個資料群的模擬資料集, 傳回值為一個兩元素的 tuple, 第一個元素為特徵資料, 第二元素為標籤資料 :

>>> X        # 特徵資料
array([[ 1.12031365,  5.75806083],
       [-0.49772229,  1.55128226],
       [ 1.9263585 ,  4.15243012],
       [ 2.49913075,  1.23133799],
       [ 3.54934659,  0.6925054 ],
       [ 1.7373078 ,  4.42546234],
       [ 2.91970372,  0.15549864],
       [ 2.84382807,  3.32650945],
       [ 0.87305123,  4.71438583],
       [ 2.36833522,  0.04356792]])
>>> y        # 標籤資料
array([0, 1, 0, 1, 1, 0, 1, 0, 0, 1])

可見因為 centers 參數設為 2, 標籤只有 0, 1 兩種 (即資料分成兩類). 

接著用 500 筆資料來繪分布圖 :
 
>>> from sklearn.datasets import make_blobs  
>>> import matplotlib.pyplot as plt 
>>> X, y=make_blobs(n_samples=10, n_features=2, centers=2)  
>>> X, y=make_blobs(n_samples=500, n_features=2, centers=2, random_state=0)   

檢視特徵資料 (500 筆) :

>>> X  
array([[ 3.79956040e-01,  4.25122003e+00],
       [ 2.23919302e+00,  5.12173900e-01],
       [ 5.76821049e-01,  4.67384322e+00],
       [ 2.70899127e+00,  4.98828843e+00],
       [ 3.01596092e+00,  2.22672651e+00],
       ...... (略) ....

檢視標籤 (500 筆) : : 

>>> y   
array([0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1,
       1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
       1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1,
       ...... (略) ....

繪製兩個特徵的分布圖, 因為橫軸與縱軸都需要一個列向量, 所以要將 500*2 的 X 陣列轉置為 2*500 的陣列, 這樣 X[0] 與 X[1] 就是 1*500 的列向量了 : 

>>> plt.scatter(X.T[0], X.T[1], c=y, cmap='Dark2')   
<matplotlib.collections.PathCollection object at 0x000001CA315F0B10>
>>> plt.grid(True)     
>>> plt.show()     

此處分布圖以 X.T[0] 為 X 軸, X.T[1] 當縱軸, 資料點樣式參數 C 就指定為標籤 y, 這樣同群的資料點樣式就會相同, 色系 cmap 指定為 'Dark2', 結果如下 :




以上測試數據與書中範例相同 (主要是因 randon_state 都設為 0). 

關於 Matplotlib 散布圖函式 scatter() 用法參考 :


2021年10月11日 星期一

機器學習筆記 : 用 scikit-learn 做資料前處理 (一) : 數值資料

今天繼續來測試學習 scikit-learn 的資料前處理 (preprocessing) 功能, 據統計這部分占了資料科學/機器學習任務絕大部分時間. 本系列之前的文章參考 : 

 
機器學習中的資料前處理包含資料清洗 (data wrangling/cleansing) 與資料轉換, 通常先使用 Pandas 套件來做資料清洗, 將原始資料轉成乾淨且格式整齊的結構化資料, 再視任務需要用 scikit-learn 做資料轉換, 然後才能送入機器學習演算法進行運算. 

Scikit-learn 套件定義了用於監督式與非監督式機器學習的類別, 這些類別統稱為估計器 (estimator), 它可分為兩類 : 
  • 轉換器 (transformers) : 用來做資料預處理 (preprocessing)
  • 預測器 (predictors) : 用來透過訓練資料來生成規則
其中轉換器 (transformer) 類別, 都放在 preprocessing 模組內, 且都具有下列三種一致的 API 介面 :
  • fit() : 
  • transform() :
  • fit_transform() : 將 fit() 與 transform() 合而為一.
使用前須先匯入 preprocessing 模組, 然後建立預處理類別之物件, 再呼叫 fit (), transform(), 或 fit_transform() 方法進行處理. 例如要進行最小最大縮放需用到 MinMaxScaler 類別, 呼叫同名建構子即可建立物件 :

from sklearn import preprocessing    
minmaxscaler=preprocessing.MinMaxScaler()      

也可以從 sklearn.preprocessing 模組直接匯入 MinMaxScaler 類別, 這樣使用時就不需要用 preprocessing 去指涉了 :

from sklearn.preprocessing inport MinMaxScaler    
minmaxscaler=MinMaxScaler()       

以下測試主要是針對原始資料中的數值資料 :


1. 資料縮放 (data scalling) :     

有許多演算法假設所有的輸入特徵要比例縮放到 [-1, 1] 或 [0, 1] 的數值區間, 比較常用的縮放方式有兩種 :
  • 最小最大縮放 (min-max-scalling) : 
    以所有樣本最大值與最小值之間距為分母, 計算樣本與最小值之差與間距之比, sklearn 的預處理 preprocessing 模組提供了 MinMaxScaler 類別來處理這種轉換 :



  • 常態分佈標準化 :
    將所有特徵轉換成平均值為0, 標準差為 1 的近似標準常態分布, sklearn 的預處理 preprocessing 模組提供了 StndardScaler 類別來處理這種轉換 :



數學式繪製參考 :



1. 用 MinMaxScaler 類別進行比例縮放 : 

此類別的介面如下 : 

MinMaxScaler(feature_range)

參數 feature_range 為一個表示目標範圍的 tuple 或 list, 呼叫此類別建構子建立 MinMaxScaler 物件後, 再呼叫此物件的 fit_transform() 方法, 並將特徵當參數傳進去即可, 注意, 傳入之特徵必須是 2D 陣列, 否則會出現錯誤訊息, 若特徵不是浮點數會被強制轉換, 例如 :

>>> import numpy as np     
>>> from sklearn.preprocessing import MinMaxScaler     
>>> minmax_scaler=MinMaxScaler(feature_range=(0,1))     
>>> feature=np.array([[100.5], [200.3], [0.0], [80.6], [65.0]])   # 原始特徵 (2D 浮點數)
>>> scaled_feature=minmax_scaler.fit_transform(feature)     # 縮放後的特徵
>>> scaled_feature    
array([[0.50174738],
       [1.        ],
       [0.        ],
       [0.40239641],
       [0.32451323]])

可見每一個特徵都被縮放到 [0, 1] 之間. 也可以縮放到 [-1, 1] 之間, 例如 : 

>>> minmax_scaler=MinMaxScaler(feature_range=(-1,1))   
>>> feature=np.array([[100.5], [200.3], [0.0], [80.6], [65.0]])   # 原始特徵 (2D 浮點數)
>>> scaled_feature=minmax_scaler.fit_transform(feature)     # 縮放後的特徵
>>> scaled_feature    
array([[ 0.00349476],
       [ 1.        ],
       [-1.        ],
       [-0.19520719],
       [-0.35097354]])



2. 用 StandardScaler 類別進行標準常態分佈縮放 : 

此類別的介面如下 : 

StandardScaler()

呼叫此類別建構子建立 StandardScaler 物件後, 再呼叫此物件的 fit_transform() 方法, 並將特徵當參數傳進去即可, 注意, 傳入之特徵必須是 2D 陣列, 否則會出現錯誤訊息, 若特徵不是浮點數會被強制轉換, 例如 :

>>> import numpy as np   
>>> from sklearn.preprocessing import StandardScaler    
>>> standard_scaler=StandardScaler()      
>>> scaled_feature=standard_scaler.fit_transform(feature)      
>>> scaled_feature      
array([[ 0.1727704 ],
       [ 1.70953389],
       [-1.37477198],
       [-0.13365839],
       [-0.37387392]])
>>> np.mean(scaled_feature)        # 平均值近乎 0
-1.1102230246251566e-17
>>> np.std(scaled_feature)             # 標轉差近乎 1
0.9999999999999998

可見轉換後的平均值約是 0, 標準差約 1. 

2021年10月8日 星期五

機器學習筆記 : 初探 scikit-learn 套件

雖然深度學習是機器學習裡最受重視的項目, 但有些任務並不一定要用到深度學習, 利用傳統的機器學習套件 scikit-learn 就能取得很好的表現. 在進入深度學習領域之前先熟悉 scikit-lean 會比較好. 本篇是閱讀下列幾本書關於 scikit-learn 的筆記 : 
其中 No.2 是 No.7 的中譯本. 

Scikit-learn 是一個基於 Numpy 與 Scipy 的 Python 開放原始碼機器學習套件, 它實作了幾乎所有的主流機器學習演算法, 包含分類, 回歸, 分群, 降維, 隨機森林, 支持向量機, KNN, K-means 等, 並提供了資料預處理, 特徵提取, 超參數最佳化, 以及模型評估等所需的函數模組, 自 2007 年發布以來已經成為最受歡迎的機器學習套件之一. 

Scikit-learn 源自 David Cournapeau 的 Google 程式專案比賽作品 scikits.learn, 後來經過其他貢獻者例如 Fabian Pedregosa 等人重寫成為今日之面貌. 其名稱源自於原作者最初是將其視為 Scipy 的機器學習擴充工具箱 (extension toolkit), 參考 :


Scikit-learn 教學文件參考 :


Scikit-learn 套件沒有自訂資料類別, 完全使用 Python 本身的資料結構與 Numpy 陣列, 並在其所有實作的演算法中提供了一致的呼叫介面, 只要修改幾行程式碼即可用來對不同的演算法進行實驗, 因此非常容易使用 (easy to use), . 

Scikit-learn 還自帶了許多資料集, sklearn.datasets 模組提供了 load_xxxx() 函數來載入這些已清理過的玩具資料集 (toy datasets), 讓使用者能馬上用它們來進行測試與學習. 透過 fetch_xxxx() 函數則可以擷取真實資料集 (real datasets), 這樣一來使用者即可專注於演算法而無須花費時間去收集與清洗資料. 不過, Scikit-learn 並不支援分散式運算, 故不適合用來處理超大型資料集. 另一個缺點是它不支援深度學習. 

Scikit-learn 的功能與應用如下 :
  • 資料預處理 (preprocessing)
  • 模型選擇 (model selection)
  • 監督式學習 (supervised learning)
    • 分類 (classification)-離散特徵
    • 回歸 (regressing)-連續特徵
  • 非監督式學習 (unsupervised learning)
    • 分群 (clustering)
    • 降維 (dimensionality reduction)
資料預處理包含資料清洗與資料轉換, 資料清洗主要是將原始資料轉成結構化資料 (通常是指二維表格資料), 包含遺漏值處理與資料整併等, 通常使用 Pandas 套件處理. 資料轉換則是將清洗過的資料轉成適合機器學習演算法操作的格式, 例如尺規 (scale) 轉換或正規化 (normalization) 轉換, 以便演算法能達到最佳表現. 

完成資料預處理後應該對資料進行探索以便選擇一個適合的機器學習模型 (即演算法), 因為不同的任務會因為選擇的機器學習模型而有不同的預測表現. 然後即可用監督式與非監督式學習進行訓練與預測, 這兩個就是 scikit-learn 的預測器功能. Scikit-learn 的 pipeline.Pipeline 類別提供了模組化功能, 可將轉換器與預測器打包成一個任務管線 (pipeline), 並使用預設的初始化參數讓轉換與預測一氣呵成. 

在 Scikit-learn 官網有一張圖清楚地揭示使用 sklearn 進行機器學習專案的路徑 :



Source : Scikit-learn


原圖網址 :


以下是簡單的初步測試 : 


1. 安裝 Scikit-learn :    

在 Windows 下直接用 pip/pip3 指令即可安裝 Scikit-learn :

pip install -U scikit-learn    

在 Ubuntu Linux 可用 apt 指令安裝 : 

$ sudo apt install python-scikits-learn   

也可以直接使用 Google 雲端硬碟上的 Colab 功能, 這樣就完全不用安裝任何套件, 只要用瀏覽器即可馬上進行測試, Google Colab 平台上所有機器學習工具一應俱全, 且是最新版本, 參考 :



2. 匯入 sklearn 套件 : 

雖然安裝時名稱為 scikit-learn, 但此名稱不符合 Python 套件規範, 使用時真正要匯入的套件名稱是 sklean, 可用 __verion__ 屬性檢視版本, 用 __file__ 屬性可檢查 sklearn 的安裝路徑 : 

>>> import sklearn    
>>> sklearn.__version__     
'0.20.2'    
>>> sklearn.__file__   
'C:\\Python37\\lib\\site-packages\\sklearn\\__init__.py'

但實際在使用 scikit-learn 時通常不這樣匯入整個套件, 而是用 from sklearn import xxxx 匯入特定的模組, 例如 : 

from sklearn.preprocessing import PolynomialFeatures 
from sklearn.preprocessing import StandardScaler 
from sklearn.linear_model import LinearRegression 
from sklearn.linear_model import Ridge 
from sklearn.linear_model import LogisticRegression 
from sklearn.svm import SVC 
from sklearn.pipeline import Pipeline 
from sklearn.model_selection import train_test_split 
from sklearn.metrics import mean_squared_error 
from sklearn.metrics import accuracy_score

上面這些就是 scikit-learn 常用的機器學習模組. 


3. 檢視 sklearn 內建的資料集 :   

Scikit-learn 套件的 datasets 模組中內建了非常豐富的資料集, 並提供一致的 load_xxxx() 函數用來載入資料集 xxxx. 以下程式碼用來檢視 datasets 裡面內建了有哪些資料集 : 

>>> from sklearn import datasets     # 匯入 datasets 模組
>>> lists=dir(datasets)                        # dir() 會傳回模組中全部成員名稱之串列
>>> for e in lists:                                  # 用迴圈走訪串列
    if e.startswith('load'):                       # 只顯示 'load' 開頭的成員
        print(e)     
      
load_boston
load_breast_cancer
load_diabetes
load_digits
load_files
load_iris
load_linnerud
load_mlcomp
load_sample_image
load_sample_images
load_svmlight_file
load_svmlight_files
load_wine

可見總共內建了 13 套玩具資料集, 包含知名的鳶尾花 (iris), 波士頓房地產 (boston) 等資料集. 例如呼叫 load_digits() 可載入手寫數字資料集 :

>>> digits=datasets.load_digits()      
>>> digits   
{'data': array([[ 0.,  0.,  5., ...,  0.,  0.,  0.],
       [ 0.,  0.,  0., ..., 10.,  0.,  0.],
       [ 0.,  0.,  0., ..., 16.,  9.,  0.],
       ........
       [ 0.,  0.,  2., ..., 12.,  0.,  0.],
       [ 0.,  0., 10., ..., 12.,  1.,  0.]]), 
  'target': array([0, 1, 2, ..., 8, 9, 8]), 
  'target_names': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), 
  'images': array([[[ 0.,  0.,  5., ...,  1.,  0.,  0.],
        [ 0.,  0., 13., ..., 15.,  5.,  0.],
        [ 0.,  3., 15., ..., 11.,  8.,  0.],
        ...,
>>> digits.data[0]    
array([ 0.,  0.,  5., 13.,  9.,  1.,  0.,  0.,  0.,  0., 13., 15., 10.,
       15.,  5.,  0.,  0.,  3., 15.,  2.,  0., 11.,  8.,  0.,  0.,  4.,
       12.,  0.,  0.,  8.,  8.,  0.,  0.,  5.,  8.,  0.,  0.,  9.,  8.,
        0.,  0.,  4., 11.,  0.,  1., 12.,  7.,  0.,  0.,  2., 14.,  5.,
       10., 12.,  0.,  0.,  0.,  0.,  6., 13., 10.,  0.,  0.,  0.])
>>> digits.target[0]    
0      

另外, 透過 fetch_xxxx() 函數則可以擷取真實資料集 :

>>> for d in m:     
    if d.startswith('fetch'):     
        print(d)    
        
fetch_20newsgroups
fetch_20newsgroups_vectorized
fetch_california_housing
fetch_covtype
fetch_kddcup99
fetch_lfw_pairs
fetch_lfw_people
fetch_mldata
fetch_olivetti_faces
fetch_openml
fetch_rcv1
fetch_species_distributions


4. 檢視 sklearn 前處理函數 :   

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() 來取得 preprocessing 類別的成員, 只顯示一般成員, 例如 :

>>> 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'>

其中 class 為 'type' 者為類別, 'module' 為模組; function 為函式.