Alipy包使用詳解
引入
0.1 主動學習簡介
在諸多實際問題中,未標記數據大量而已標記數據稀缺。由於人類專家的參與,標籤的獲取通常昂貴。因此,通過少量的標籤實例來訓練準確的預測模型至關重要。
主動學習的目的即是:
通過只查詢最有價值的實例來減少人類專家在機器學習系統中註釋實例的比例,並已成功地應用到各種實際任務中。
原文鏈接~~
聲明:此文爲筆者學習Alipy包使用的歷程,絕無半點侵權之意。
0.2 主動學習示例
常規的主動學習過程中,示例查詢和模型更新迭代進行。以下是一個具體的例子:
上述過程僞代碼如下:
輸入:有標籤的訓練集(僅有少量實例)
while:
查詢算法選擇一批被認爲有價值的無標籤數據
oracle根據其已有知識提供一些有監督的信息
新的有標籤實例添加到標記集
更新模型
直到滿足特定的停止標準(如,有限的查詢數量或有限的成本預算)。
0.3 查詢策略及評價
主動學習的研究方向之一是查詢策略。學習者將根據特定的查詢策略選擇一些未標記的數據,並從oracle中查詢其標籤。在主動學習文獻中,各種策略從不同方面進行評估,以此判斷實例對模型改進的有用性。
那如何評估不同算法的性能呢?
通過構造學習曲線的方式直觀有效,如將查詢次數與準確率的關係進行繪製。對於不同的查詢策略,由於會選擇不同的數據進行查詢,將會產生不同的學習曲線。
0.4 Alipy概述
Alipy提供了一個基於模塊的主動學習框架,其目標是用各種工具功能支持實驗實現。這些工具是以低耦合的方式設計的,以便用戶可以根據自己的習慣來編程實驗項目。支持的模塊如下:
序列 | 模塊名 | 功用 |
---|---|---|
1 | alipy.data_manipulate | 數據劃分 |
2 | alipy.query_strategy | 數據查詢策略 |
3 | alipy.index.IndexCollection | 索引管理 |
4 | alipy.metric | 模型性能計算 |
5 | alipy.experiment.state/alipy.experiment.state_io | 保存每次查詢後的中間結果並從斷點恢復程序 |
6 | alipy.experiment.stopping_criteria | 獲取停止標準 |
7 | alipy.experiment.experiment_analyser | 可視化實驗結果 |
8 | alipy.oracle | 提供清潔、噪音或者代價敏感的oracle |
9 | alipy.utils.multi_thread | 多次實驗 |
支持以下算法:
序列 | 算法類型 | 具體算法 |
---|---|---|
1 | 實例選擇 | Uncertainty (SIGIR 1994) , Graph Density (CVPR 2012) , QUIRE (TPAMI 2014)、 |
SPAL (AAAI 2019) , Query By Committee (ICML 1998) , Random | ||
BMDR (KDD 2013) , LAL (NIPS 2017) , Expected Error Reduction (ICML 2001)… | ||
2 | 多標籤數據 | AUDI (ICDM 2013) , QUIRE (TPAMI 2014) , Random |
MMC (KDD 2009) , Adaptive (IJCAI 2013) … | ||
3 | 特徵查詢 | AFASMC (KDD 2018) , Stability (ICDM 2013) , Random |
4 | 不同代價 | AL with Different Costs : HALC (IJCAI 2018) , Random |
Cost performance… | ||
5 | 噪聲oracle | AL with Noisy Oracles : CEAL (IJCAI 2017) , IEthresh (KDD 2009) |
All , Random… | ||
6 | 特殊查詢類型 | AURO (IJCAI 2015) … |
7 | 大規模任務 | Subsampling… |
1 高級封裝
1.1 ToolBox
ToolBox是一個提供所有可用工具類的類,以下說明大致功用。
1.1.1 初始化ToolBox對象:
程序清單1-1: 初始化工具箱
from sklearn.datasets import *
from alipy import ToolBox
import warnings
warnings.filterwarnings("ignore") #忽略警告
def test():
data_set, label_set = load_iris(return_X_y=True) #示例:導入iris數據集;返回實例集合與相應標籤
print("The data set:", data_set)
print("The label set", label_set)
alibox = ToolBox(X=data_set, y=label_set, query_type='AllLabels', saving_path='.')
if __name__ == '__main__':
test()
運行結果(注:載入boston數據時會出現未知錯誤):
...
[5.9 3. 5.1 1.8]]
The label set [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 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2]
引入的sklearn.datasets自帶以下數據集(當然可以自行導入數據集):
數據集名稱 | 導入命令 | 用途 |
---|---|---|
鳶尾花數據集 | load_iris() | 用於分類或聚類任務的數據集 |
手寫數字數據集 | load_digits() | 用於分類任務或者降維任務的數據集 |
乳腺癌數據集 | load_barest_cancer() | 用於二分類任務的數據集 |
糖尿病數據集 | load_diabetes() | 用於迴歸任務的數據集 |
波士頓房價數據集 | load_boston() | 用於迴歸任務的數據集 |
體能訓練數據集 | load-linnerud() | 用於多變量回歸任務的數據集 |
查詢類型有下:
AllLabels | PartLabels | Features |
---|
1.1.2 獲取默認模型
Alipy默認模型爲logistic迴歸模型,相應的獲取、訓練、測試方法如下:
程序清單1-2: 獲取默認模型及預測
from sklearn.datasets import *
from alipy import ToolBox
import warnings
warnings.filterwarnings("ignore") #忽略警告
def test():
data_set, label_set = load_iris(return_X_y=True) #示例:導入iris數據集;返回實例集合與相應標籤
# print("The data set:", data_set)
# print("The label set", label_set)
alibox = ToolBox(X=data_set, y=label_set, query_type='AllLabels', saving_path='.') #一般使用‘AllLabels’
de_model = alibox.get_default_model() #獲取默認模型
de_model.fit(data_set, label_set) #傳入數據及標籤
pred = de_model.predict(data_set) #標籤預測
print(pred)
pred = de_model.predict_proba(data_set) #獲取概率輸出
# print(pred)
if __name__ == '__main__':
test()
運行結果:
[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 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 2 1 1 1
1 1 1 1 1 1 1 1 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2]
1.1.3 劃分數據
ToolBox中有兩種獲取劃分數據的方式:
1)使用alibox.split_AL()並指定參數來劃分,即:
train_ind, test_ind, label_ind, unlabel_ind = alibox.split_AL(test_ratio=0.3, initial_label_rate=0.1, split_count=1)
參數說明:
參數名稱 | 意義 |
---|---|
test_ratio | 測試集比例 |
initial_label_rate | 測試集中帶標籤實例的比例 |
split_count | 劃分次數 |
train_ind | 訓練集 |
test_ind | 測試集 |
label_ind | 訓練集中帶標籤實例 |
unlabel_ind | 訓練集中不帶標籤實例 |
2)方式2與方式1是類似的,需要注意的是返回值均爲索引:
alibox.split_AL(test_ratio=0.3, initial_label_rate=0.1, split_count=10)
train_0, test_0, label_0, unlabel_0 = alibox.get_split(round=0)
train_1, test_1, label_1, unlabel_1 = alibox.get_split(round=1)
1.1.4 創建IndexCollection對象
alipy.index.IndexCollection是一個管理索引的工具類,可通過以下方式創建和使用該類:
程序清單1-3: IndexCollection類使用示例
from sklearn.datasets import *
from alipy import ToolBox
import warnings
warnings.filterwarnings("ignore") #忽略警告
def test1():
data_set, label_set = load_iris(return_X_y=True)
alibox = ToolBox(X=data_set, y=label_set, query_type='AllLabels', saving_path='.')
a = [1, 2, 3]
a_ind = alibox.IndexCollection(a) #這裏的a可以是訓練集索引或者其他
print("index:", a_ind.index) #索引輸出
a_ind.add(10) #添加單個索引;注:索引不會重複
print("add:", a_ind)
a_ind.discard(1) #刪除已有索引
print("discard", a_ind)
a_ind.update([4, 5, 10]) #添加多個元素
print("update", a_ind)
a_ind.difference_update([4, 10]) #刪除多個元素
print("difference_update", a_ind)
運行結果:
index: [1, 2, 3]
add: [1, 2, 3, 10]
discard [2, 3, 10]
update [2, 3, 10, 4, 5]
difference_update [2, 3, 5]
1.1.5 獲得Oracle或Repository 對象
1)獲取clean oracle
clean_oracle = alibox.get_clean_oracle(query_by_example=False, cost_mat=None)
如按特徵查詢:query_by_example=True。
提供一個索引或一個索引列表,以便查詢標籤和相應代價(標籤爲初始化數據集所對應的標籤):
label, cost = clean_oracle.query_by_index([1])
如果在初始化時沒有指定代價,則默認爲1,否則可以設置代價矩陣;代價矩陣的形狀應與標籤矩陣的形狀相同,以便進行代價敏感查詢。
2)獲取 repository
alibox.get_repository(round=0, instance_flag=False)
round即與之前split_count相對應。當然,若要保存當前所選實例的特徵向量則設置:instance_flag=True。
程序清單1-4: clean oracle類使用示例
from sklearn.datasets import *
from alipy import ToolBox
import warnings
warnings.filterwarnings("ignore") #忽略警告
def test2():
data_set, label_set = load_iris(return_X_y=True) #示例:導入iris數據集;返回實例集合與相應標籤
alibox = ToolBox(X=data_set, y=label_set, query_type='AllLabels', saving_path='.') #一般使用‘AllLabels’
clean_oracle = alibox.get_clean_oracle(query_by_example=False, cost_mat=None)
label, cost = clean_oracle.query_by_index([1])
print("label:", label)
print("cost:", cost)
if __name__ == '__main__':
test2()
運行結果:
label: [0]
cost: [1]
1.1.6 獲取State 或 StateIO 對象
alipy.experiment.StateIO用於保存或者載入中間結果,幾個重要功能如下:
1)以文件形式保存中間結果;
2)在任意次迭代中恢復工作臺(標籤集和非標籤集);
3)程序意外退出時從斷點恢復程序;
4)輸出主動學習過程:當前迭代次數、當前平均性能、當前代價等。
對於每一次round,可如下保存:
saver = alibox.get_stateio(round=1) #1作爲示例
可設置相應參數如下:
st = alibox.State(select_index=select_ind, performance=accuracy, cost=cost, queried_label=queried_label) #此處併爲給出select_ind等的定義
saver.add_state(st) #添加參數
saver.save() #保存至文件,默認保存於當前文件夾
1.1.7 獲取預設查詢策略對象
Alipy支持的查詢策略如下:
序號 | 策略名稱 |
---|---|
1 | QueryInstanceQBC |
2 | QueryInstanceUncertainty |
3 | QueryRandom |
4 | QureyExpectedErrorReduction |
5 | QueryInstanceGraphDensity |
6 | QueryInstanceQUIRE |
具體使用如下:
QBCStrategy = alibox.get_query_strategy(strategy_name='QueryInstanceQBC')
注意:QueryInstanceGraphDensity及QueryInstanceQUIRE需要額外指定參數!
1.1.8 計算性能
支持性能計算方法如下:
序號 | 性能計算方法名 |
---|---|
1 | accuracy_score |
2 | roc_auc_score |
3 | get_fps_tps_thresholds |
4 | hamming_loss |
5 | one_error |
6 | coverage_error |
7 | label_ranking_loss |
8 | label_ranking_average_precision_score |
一個具體的例子如下:
程序清單1-5: 性能計算示例
from sklearn.datasets import *
from alipy import ToolBox
import warnings
warnings.filterwarnings("ignore") #忽略警告
def test3():
data_set, label_set = load_iris(return_X_y=True) #示例:導入iris數據集;返回實例集合與相應標籤
alibox = ToolBox(X=data_set, y=label_set, query_type='AllLabels', saving_path='.') #一般使用‘AllLabels’
alibox.split_AL(test_ratio=0.3, initial_label_rate=0.1, split_count=10)
de_model = alibox.get_default_model()
de_model.fit(data_set, label_set)
pred = de_model.predict(data_set)
"""新增"""
acc = alibox.calc_performance_metric(y_true=label_set, y_pred=pred, performance_metric='accuracy_score')
print("accuracy score:", acc)
if __name__ == '__main__':
test3()
運行結果:
accuracy score: 0.96
1.1.9 獲取停止標準
常用停止標準如下:
序號 | 命令名 | 代表意義 |
---|---|---|
1 | None | 默認:沒有未標記實例 |
2 | num_of_queries | 查詢數量 |
3 | cost_limit | 代價限制 |
4 | percent_of_unlabel | 未標記實例比例 |
5 | time_limit | 時間限制 |
一個示例如下:
stopping_criterion = alibox.get_stopping_criterion(stopping_criteria='time_limit', value=1)
for i in range(10):
print(i)
while not stopping_criterion.is_stop():
pass
1.1.10 可視化實驗結果
一個示例如下:
analyser = alibox.get_experiment_analyser(x_axis='time_limit') #設置x軸名稱
analyser.add_method(method_name='QBC', method_result=QBC_result)
analyser.plot_learning_curves() #繪製
1.1.11 最終結果保存
一個示例如下:
alibox.save()
alibox = ToolBox.load('./al_settings.pkl')
1.2 智能實驗
alipy.experiment.AlExperiment是一個封裝了各種工具並實現了主循環的類。以下爲一個具體示例:
程序清單1-6: 一次簡單的實驗
from sklearn.datasets import load_iris
from alipy.experiment.al_experiment import AlExperiment
import warnings
warnings.filterwarnings("ignore") #忽略警告
def test5():
data_set, label_set = load_iris(return_X_y=True)
al = AlExperiment(data_set, label_set, stopping_criteria='num_of_queries', stopping_value=50)
al.split_AL()
al.set_query_strategy(strategy="QueryInstanceUncertainty", measure='least_confident')
al.set_performance_metric('accuracy_score')
al.start_query(multi_thread=True) #開啓多線程
al.plot_learning_curve()
if __name__ == '__main__':
test5()
運行結果:
| 7 | 50 | 00:00:04 | 0.909 ± 0.12 |
| 8 | 50 | 00:00:04 | 0.957 ± 0.04 |
| 9 | 50 | 00:00:04 | 0.698 ± 0.10 |
+-------+-------------------+-------------+--------------------------+
+--------------------------+-------------------+---------------------------+--------------+------------+
| Methods | number_of_queries | number_of_different_split | performance | batch_size |
+--------------------------+-------------------+---------------------------+--------------+------------+
| QueryInstanceUncertainty | 50 | 10 | 0.843 ± 0.08 | 1 |
+--------------------------+-------------------+---------------------------+--------------+------------+
繪製結果:
2 Alipy工具類
接下來詳細講解具體工具類的用途。
2.1 數據操作
alipy.data_manipulate用於管理實驗數據。