有用請點贊,沒用請差評。
歡迎分享本文,轉載請保留出處。
?
?目前程序的訓練部分分類器部分沒有問題,但是最后的predict部分還存在點問題,一直沒有找出來,等有時間了再來修改吧。
采用的數據集:github:https://github.com/Tomator01/-Machine-Learning
?
# -*- coding:utf-8 -*-
# AdaBoost算法
# author:Tomator
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
import cv2
import time
import math
class AdaBoost(object):
def __init__(self, epsilon=0.0):
# 暫時沒有加上epsilon,也可以加上
self.epsilon = epsilon # 分類誤差率閾值
self.w = None # 樣本的權值,每加入一個基本分類器都要重新計算
self.N = None
self.alpha = [] # 基本分類器前面的系數
def init_param(self, X_data):
# 初始化參數,包括權值和所有可能的弱分類器
self.N = X_data.shape[0] #訓練數據樣本數
self.features_n=X_data.shape[1] #特征維度數
self.w = np.ones(self.N) / self.N # 初始化權值
self.M = 10 #最大弱分類器數目
self.classifier = [] # (維度,分類器),針對當前維度的分類器
def _Z_(self,index,classifier,X_data,y_data):
'''
公式8.5
Z是規范化因子
'''
Z = 0
for i in range(self.N):
Z += self._w_(index,classifier,i,X_data,y_data)
return Z
def _w_(self,index,classifier,i,X_data,y_data):
return self.w[i] * math.exp(-self.alpha[-1] * y_data[i] * classifier.predict(X_data[i][index]))
def cal_alpha(self, err):
# 計算基本分類器前的系數
return 1.0 / 2 * math.log((1 - err) / err)
def cal_weight(self, X_data, y_data,best_classifier,Z):
# 更新每個樣本權重
for i in range(self.N):
self.w[i] = (self.w[i]*self._w_(best_classifier[1], best_classifier[2], i,X_data,y_data)) / Z
return self.w
# 訓練
def fit(self, X_data, y_data):
# 初始化
self.init_param(X_data)
# print("features_n",self.features_n)
for m in range(self.M): # 逐步添加基本分類器
best_classifier = (100000, None, None) # (誤差率,針對的特征維度位置,分類器)
for i in range(self.features_n):
classifier=Sign(X_data[:,i], y_data,self.w) #尋找每一維度的最優弱分類器,X_data[:,i]數據向量的某一維度的數據
error_score=classifier.train() #返回最小誤差率
#選出誤差率最小的弱分類器
if error_score < best_classifier[0]:
best_classifier = (error_score,i,classifier)
# print("training index:",best_classifier[1],m)
# 將每一次的弱分類的對象存放在self.classifier中
self.classifier.append(best_classifier[1:])
# 計算弱分類器Gm(x)前的系數
if best_classifier[0]==0:
print("error is zero")
self.alpha.append(100)
else:
alpha = self.cal_alpha(best_classifier[0])
self.alpha.append(alpha) # 基本分類器前面的系數
print("error:", best_classifier[0], " alpha:", self.alpha[-1])
# Z是規范化因子
Z=self._Z_(best_classifier[1],best_classifier[2],X_data,y_data)
# 更新權值
self.w=self.cal_weight(X_data, y_data,best_classifier,Z)
print("train over")
return
def predict(self, X):
# 預測
result = 0.0
# 循環每一個分類器
for i in range(self.M):
# index為每一個弱分類器的分類維度坐標
index = self.classifier[i][0]
# print("classifier index: %d"%index)
# 每一個弱分類器的分類器對象
classifier = self.classifier[i][1]
# 公式8.7
result += self.alpha[i]*classifier.predict(X[index])
if result>=0:
return 1
return -1
#閾值分類器只能分類單一維度的特征,而通常情況下我們的特征都是多維的,假設特征有n維,我們針對每一維特征求一個分類器,選取這些分類器中分類誤差率最低的分類器作為本輪的分類器,將其特征坐標與分類器一起存入G(x)中。
class Sign(object):
'''
閾值分類器
有兩種方向,
1)x
v y=1
v 是閾值軸
因為是針對已經二值化后的MNIST數據集,所以v的取值只有2個 {0,1,},
y為label,取值為(1,0),對應于標簽化后取值為(1,-1),
'''
def __init__(self,features,labels,w):
self.X = features # 訓練數據特征
self.Y = labels # 訓練數據的標簽
self.N = len(labels) # 訓練數據大小
self.w = w # 訓練數據權值分布
self.indexes = [0,1] # 閾值軸可選范圍
def _train_less_than_(self):
'''
尋找(x
< error_score:
index = i
error_score = score
return index,error_score
def _train_more_than_(self):
'''
尋找(x>v y=1)情況下的最優v
'''
index = -1
error_score = 1000000
for i in self.indexes:
score = 0
for j in range(self.N):
if self.X[j]>=i:
# 對應與laebl為1
if self.Y[j] !=1 :
score += self.w[j]
else:
# 對應與laebl為0
if self.Y[j] != -1:
score += self.w[j]
if score < error_score:
index = i
error_score = score
return index,error_score
def train(self):
less_index,less_score = self._train_less_than_()
more_index,more_score = self._train_more_than_()
if less_score < more_score:
self.is_less = True
self.index = less_index
return less_score
else:
self.is_less = False
self.index = more_index
return more_score
def predict(self,feature):
# 通過弱分類進行預測
if self.is_less == True:
if feature<=self.index:
return 1
else:
return -1
else:
if feature >= self.index:
return 1
else:
return -1
# 圖像二值化
def binaryzation(img):
#注意如果機器是老版本的opencv.cv2此處寫法會有不同
cv_img = img.astype(np.uint8)
cv2.threshold(cv_img,50,1,cv2.THRESH_BINARY_INV,cv_img)
return cv_img
def binaryzation_features(trainset):
features = []
for img in trainset:
img = np.reshape(img,(28,28))
cv_img = img.astype(np.uint8)
img_b = binaryzation(cv_img)
features.append(img_b)
features = np.array(features)
features = np.reshape(features,(-1,784))
return features
if __name__ == "__main__":
raw_data = pd.read_csv('D://python3_anaconda3//學習//機器學習//機器學習數據集//MNIST數據集——兩類label//train_binary.csv', header=0,engine='python')
data = raw_data.values
imags = data[0::, 1::]
features = binaryzation_features(imags)
labels = data[::, 0]
# 劃分訓練集、測試集
x_train_vector, x_test_vector,x_train_label,x_test_label = train_test_split(features,labels, test_size=0.3, random_state=0)
# print(x_train_label.shape,x_test_vector.shape,x_train_label.shape,x_test_label.shape)
adaboost=AdaBoost()
adaboost.fit(x_train_vector,x_train_label)
score=0
test_nums=x_test_vector.shape[0]
x_test_label = map(lambda x: 2 * x - 1, x_test_label)
for vector,label in zip(x_test_vector,x_test_label):
pred=adaboost.predict(vector)
if pred != label:
score+=1
print("accuracy score is :%f"%(1-score/test_nums))
以上是訓練結果,可以看出每次的弱分類器的錯誤率都在呈指數逐漸降低,相反的是每個弱分類器前的系數是在相應的變大,與adaboost的理論符合,證明train部分是對的。準確率只有為0.895,不夠好。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
