1. 集成學習
顧名思義,就是將多個單一模型進行組合,最后形成一個更好的模型的過程。之所以組合多個單一學習器,是因為很多時候單一學習器的效果不夠理想,多個模型組合可以互幫互助,各取所長,從而能夠更好的完成任務。集成學習一般的結構是先學習單一的學習器,之后通過某種策略將其組合在一起。
(a)首先應該保證分類器之間的差異性,如果分類器都相同,那么組合的出來的結果是不會有變化的。
(b)每個個體分類器的精度必須大于0.5,如果個體分類器的精度低于0.5,那集成之后的精度低于規模的增大而降低。但如果精度是大于0.5的,最后的分類結果會趨于1。
根據個體學習器的生成方式,目前的集成學習方法大致可以分成兩類:第一類是單個學習器之間有著很強的依賴關系,需要以串行的序列化的方式生成,代表方法:。方法中也有很多分類:、GBDT等等。第二類就是個體學習器之間不存在很強的依賴關系,學習器可以并行生成,代表方法: 和 。
2. 和
2.1
又稱為套袋法:
每次從樣本集合中有放回地抽取n個值iris數據集分類器代碼,一共抽取k輪,形成k個訓練集合,訓練集合之間彼此獨立。對于分類問題,k個訓練器可以訓練出k個模型,從而產生k個結果,對于回歸問題,取均值作為預測結果。
2.2
每次從樣本集合中有放回地抽取n個值,一共抽取k輪,形成k個訓練集合,訓練集合之間彼此獨立。對于分類問題,k個訓練器可以訓練出k個模型,從而產生k個結果,對于回歸問題,取均值作為預測結果。
梯度提升的方法則是使用代價函數對上一輪訓練的損失函數f的偏導數來擬合殘差。
2.3 和的區別
是每次從樣本集中有放回地抽取n個樣本,抽取k次,形成k個樣本集合,樣本集合之間相互獨立;
則是訓練集合保持不變iris數據集分類器代碼,每次變化的是訓練集中樣例的權重。
使用的是均勻采樣,每個樣例權重相等;
根據上一輪結果調整權重,錯誤率越大權重越大。
所有的預測函數權重相同;
預測函數權重不同,預測誤差小的權重越大。
各個預測函數可以并行生成;
只能順序生成,因為后一個預測要用到上一個結果。
2.4 樣本權值和模型權值
會減小在上一輪正確樣本的權重,增大錯誤樣本的權重(因為正確樣本殘差小,錯誤樣本殘差大。組合模型的時候會將錯誤率高的模型賦予低的權重,將錯誤率低的模型賦予高的權重,有助于增加組合后模型準確率。
3. 組合模型方式
3.1 平均法
(a)簡單平均
將所有的個體學習器的數值型輸出求平均。
(b)加權平均
各個學習器有自身的權重,根據權重來進行加權平均,代表算法:。
3.2 學習法
當訓練數據很多時,更加強大的結合策略就是學習法,也就是通過另一個學習器來進行組合。典型代表是。把個體學習器稱之為初級學習器,用于結合的學習器稱為次級學習器或者元學習器。
先從初始訓練集訓練出初級學習器,然后生成一個新的數據集來訓練次級學習器。新的數據集是以初級學習器的輸出作為樣例,初始樣本的標記被當做樣例標記。
4. 算法
4.1 核心思想
4.2 前向分步算法
簡單來說就是從前向后,每次只學習一個基函數,最后通過基函數的線性組合,去逼近優化目標函數。
4.3 算法步驟
的實現(iris數據集)
import os
import numpy as np
import pandas as pd
from sklearn.cross_validation import train_test_split
from sklearn.datasets import load_iris
def load_data():
? ?iris = load_iris()#導入數據
? ?#轉換為dataframe
? ?df = pd.DataFrame(iris.data,columns=iris.feature_names)
? ?df['label'] = iris.target#導入標簽
? ?#把0和1類拿出來
? ?df.columns = ['sepal length','sepal width','petal length','petal width','label']#重命名列名
? ?data = np.array(df.iloc[:100,[0,1,-1]])#前100行為分類為0和1兩類
? ?#把為0的變成-1
? ?for i in range(len(data)):
? ? ? ?if data[i,-1]==0:#把0類的轉換為-1類
? ? ? ? ? ?data[i,-1] = -1
? ?return data[:,0:2],data[:,-1]

X,y = load_data()#導入數據
train_x,test_x,train_x,train_y = train_test_split(X,y,test_size=0.2,random_state=2333)#劃分訓練集和測試集
#定義Adaboost類
class Adaboost(object):
? ?def __init__(self,n_estimators=1,learning_rate = 0):
? ?'''
? ?n_estimators 分類器個數
? ?learning_rate 步長
? ?'''
? ? ? ?self.n_estimate = n_estimators
? ? ? ?self.learning_rate = learning_rate
? ?def init_data(self,X,y):
? ?'''
? ?X:屬性
? ?y:標簽
? ?'''
? ? ? ?self.M,self.N = X.shape#屬性一共有M行N列
? ? ? ?self.X = X#訓練屬性
? ? ? ?self.y = y#標簽數據
? ? ? ?self.w = [1.0/self.M]*self.M#初始化權重為1/M
? ? ? ?self.alpha = []
? ? ? ?self.clf_set = []#模型參數集合
? ?def _alpha(self,error):#誤差越大 alpha值越小
? ? ? ?return 0.5*np.log((1-error)/error)
? ?def _Z(self, weights, a, clf):
? ?'''

? ?a:各個分類器的權重
? ?weights:權重
? ?clf:compare_array
? ?'''
? ? ? ?return sum([weights[i]*np.exp(-1*a*self.y[i]*clf[i]) for i in range(self.M)])
? ?def _w(self, a, clf, Z):#相當于給權重w做了一層softmax 歸一化
? ?'''
? ?a:各個分類器的權重
? ?weights:權重
? ?clf:compare_array
? ?誤分類self.y[i]*clf[i]=1權重增大 正確分類self.y[i]*clf[i]=-1權重變小
? ?'''
? ? ? ?for i in range(self.M):
? ? ? ? ? ?self.w[i] = self.w[i]*np.exp(-1*a*self.y[i]*clf[i])/ Z
? ?#具體算法
? ?def G(self,feature,label,weights):#每次更新的是w
? ? ? ?#求出屬性列中的最大值和最小值
? ? ? ?f_min = min(feature)
? ? ? ?f_max = max(feature)
? ? ? ?#在屬性列上迭代的次數
? ? ? ?n_step = (f_max-f_min+self.learning_rate)//self.learning_rate
? ? ? ?error = 10000.0#定義為無窮大
? ? ? ?best_v = 0.0#表示屬性中最好分類點的值
? ? ? ?direct,compare_array = None,None
? ? ? ?#direct表示優化方向
? ? ? ?#compare_array表示該方向對應的c_o_positive or c_o_negative數組
? ? ? ?for i in range(1,int(n_step)):
? ? ? ? ? ?v = f_min+self.learning_rate*i#每次增加的步長為learning_rate

? ? ? ? ? ?if v not in feature:#如果v不存在屬性列中
? ? ? ? ? ? ? ?c_o_positive = np.array([1 if feature[k] > v else -1 for k in range(len(feature))])#大于v的label置為1 小于v的置為-1
? ? ? ? ? ? ? ?#print([weights[k] for k in range(len(feature)) if c_o_positive[k]!=label[k]])
? ? ? ? ? ? ? ?error_positive = sum([weights[k] for k in range(len(feature)) if c_o_positive[k]!=label[k]])#記錄不等于label的weight并求和
? ? ? ? ? ? ? ?c_o_negative = np.array([-1 if feature[k] > v else 1 for k in range(len(feature))])#同上 但反向
? ? ? ? ? ? ? ?error_negative = sum([weights[k] for k in range(len(feature)) if c_o_negative[k]!=label[k]])
? ? ? ? ? ? ? ?if error_positive < error_negative:#如果正向誤差小于反向誤差
? ? ? ? ? ? ? ? ? ?weight_error = error_positive#記錄誤差
? ? ? ? ? ? ? ? ? ?_compare_array = c_o_positive
? ? ? ? ? ? ? ? ? ?direct = 'positive'
? ? ? ? ? ? ? ?else:
? ? ? ? ? ? ? ? ? ?weight_error = error_negative
? ? ? ? ? ? ? ? ? ?_compare_array = c_o_negative
? ? ? ? ? ? ? ? ? ?direct = 'negative'
? ? ? ? ? ? ? ?if weight_error < error:
? ? ? ? ? ? ? ? ? ?error = weight_error#記錄誤差
? ? ? ? ? ? ? ? ? ?best_v = v#記錄最佳分類值
? ? ? ? ? ? ? ? ? ?compare_array = _compare_array#記錄label
? ? ? ?return best_v,error,compare_array,direct
? ?def _G(self,x,v,direct):
? ? ? ?if direct=='positive':
? ? ? ? ? ?return 1 if x > v else -1
? ? ? ?else:
? ? ? ? ? ?return -1 if x>x else -1
? ?def fit(self,X,y):
? ? ? ?self.init_data(X,y)#初始化類內參數
? ? ? ?for i in range(self.n_estimate):#迭代次數
? ? ? ? ? ?best_clf_error,best_v,clf_result = 100000,None,None

? ? ? ? ? ?#單個屬性
? ? ? ? ? ?for j in range(self.N):#在屬性列上迭代
? ? ? ? ? ? ? ?feature = self.X[:,j]#
? ? ? ? ? ? ? ?v,error,compare,direct = self.G(feature,self.y,self.w)
? ? ? ? ? ? ? ?if error0 else -1
? ?def score(self,X_test,y_test):#打分函數(比較簡單)
? ? ? ?count = 0
? ? ? ?for i in range(len(X_test)):
? ? ? ? ? ?feature = X_test[i]
? ? ? ? ? ?if self.predict(feature) == y_test[i]:
? ? ? ? ? ? ? ?count += 1
? ? ? ?return count/len(X_test)