“机械神会在知识之路上指引我们的脚步。”
——来自于技术主教雅菲尔的书《机魂的索伊伦翠绿》
尝试将多个tensorflow弱分类器用AdaBoost的方法连接,以提高分类准确率与代码复用性
赞美 https://blog.csdn.net/guyuealian/article/details/70995333
#=========================================================
#
# AdaBoost分类
#
# 用多个弱分类器组合成一个强分类器
#
#=========================================================
# ;@#@@$|;'`. `
# ;@#############&|:` `
# ;@####################|` `
# ;@####################@@##$: `
# :@#@#########################@!. `
# .%####$;::;$###########################|. `
# .%####| |#############################&: `
# .;%. .%####| |###########$!$##################|. `
# '#@##@$` `%####| |#@@#######%. '$################| `
# `%##########&: `:|#######| .`:%#####%. `$##############@; `
# :############@@#########| .%###############@@$' `
# '$#######################| .|###################@!. `
# `$#############@########%. .|######################$` `
# !##############@|' :@#####&!' .!@#####################&` `
# .%@;. |#############%` ;######@@###$` ;@##################@@&' `
# :####&:|##########@#&: ;@#############$. ;@#&;` |###########&: `
# |########@###########&' :@#############@#$` '#########&' `
# !####################|. :@################@; '#########$` `
# ;@@@#################! :@##################| ;@##########| `
# '$@###############! :@##################@; ;############@: `
# .%############$` :@###################$` `$#@###############%.`
# `$############| :@###################&' |#################@:'
# |#############| :@###################@: '################|:
# `$#############|. :@###################&' |#################$!
# ...`%##############&' :@#################@#%. '$################@%
######################$. :@##################&: |##########$
#######################| :@#################@; ;@#########$
#######################@: :@#################%. :@#########$
########################| ;@#################! !##########$
#@########################| ;@#########@@@@#@#@; `%##########$
# ;@###############$` `::` :@####@@###$:';##&' '###############@%
# .%##############| `$#@@###$;`. ;@@##&|: ;@##@: .%#################$!
# !#############&: `$#######@@@#%. :@@; |####|. ;@#################|'
# .%#############&: :@#@@@##@%' :@##@!` '$#@@%` .%#################@:'
# :$##############&: .::`. :;;#####@%!:;$##@@%. '$#################%.`
# .;@##################| ;@! `#####@@#@#####! '%##@##########&: `
# '&@@###################! `$#! !#########@#@@#| |###########| `
# :@#####################&!'`:!|' '' :@$!####$``;!;' ;@##########$` `
# :@#####################@#@@#| ;&@########| |###########&' `
# `$#@##@|.'%#############@#$` ;@########@$' '%###$' .%###########&: `
# .|$: '$#############%. . ;@#$|#@@#&: `$#####################&' `
# `%###########! .'. |! ;##%:%#&;$##| '$######################&' `
# '$######################|. ;######################%. `
# |########################|. '#################@! `
# %################@@#######| `;:. `$##############@@%` `
# .|##@#####@#%. `:|$@#####| '|###@$ .|@############@@&' `
# :##@@|. .%####| |##########&' `%##@###########@@&: `
# `|@| .%####| |############@@#################&: `
# .$#@@#| |###########################@#%` `
# :|%$&$$&&##########################$' `
# :@#@######################@@#$' `
# :@###################@###$;. `
# :@############@@####@|' `
# ;@#@@########@%;'. `
#
# "There is no truth in flesh, only betrayal."
# "There is no strength in flesh, only weakness."
# "There is no constancy in flesh, only decay."
# "There is no certainty in flesh but death."
# — Credo Omnissiah
#
# x_i ∈ X, y_i ∈ Y:训练输入, t ∈ 训练次数
#
#
# D_t 分发权值向量, 由当前基分类器错误率更新,用于获取该基分类器的训练子集S_i, D_t总和应该为1, 初始分布为1/t
#
#1. 通过训练数据训练出一个最优分类器。
#2. 查看分类器的错误率,把错分类的样本数据提高一定权重,分类正群的样本,降低一定权重。然后按每个数据样本,不同权重来训练新的最优分类器。
#3. 最终投票结果由这些分类器按不同权重来投票决定,其中各分类器的权重,按其预测的准确性来决定。
# 如果正确分类 D更新 D_t+1(i) = D_t(i) * (e^-α) / sum(D) 降低正确样本的权重
# 如果错误分类 D更新 D_t+1(i) = D_t(i) * (e^α) / sum(D) 增加错误样本的权重
# e为常数
#
# ε = ∑(h_t(x_i) ≠ y_i)D_t 基分类器ht的错误率ε 权值D之和
# α = 1/2 * ln(1-ε / ε) 如果某个弱分类器的分类错误率更低,那么根据错误率计算出来的α将更高
#
# h(x) 基分类器 分类假设
#
# H(X) = sign(∑ h_t(x) * α)
# 联合分类器H(X),计算出最终结果
class model_info:
def __init__(self, model_fn, modeTypeName="", modelAccuracy=0, modelAlpha=0):
self.modeTypeName = modeTypeName
self.modelAccuracy = modelAccuracy
self.modelAlpha = modelAlpha
self.model_fn = model_fn
def bulid_nn(inputData, mode):
hidden_size_1 = 10
w_initializer = tf.contrib.layers.xavier_initializer(dtype=tf.float64)
b_initializer = tf.constant_initializer(value=0.0, dtype=tf.float64)
W_1 = tf.get_variable('nn_w1', [inputSize, hidden_size_1], initializer=w_initializer, dtype=tf.float64)
b_1 = tf.get_variable('nn_b1', [hidden_size_1], initializer=b_initializer, dtype=tf.float64)
h_1 = tf.nn.relu(tf.matmul(inputData, W_1) + b_1)
W_2 = tf.get_variable('nn_w2', [hidden_size_1, outputCount], initializer=w_initializer, dtype=tf.float64)
b_2 = tf.get_variable('nn_b2', [outputCount], initializer=b_initializer, dtype=tf.float64)
logits = tf.nn.softmax(tf.matmul(h_1, W_2) + b_2)
return logits
def bulid_svm(inputData, mode):
w_initializer = tf.contrib.layers.xavier_initializer(dtype=tf.float64)
b_initializer = tf.constant_initializer(value=0.0, dtype=tf.float64)
W_1 = tf.get_variable('svm_w1', [inputSize, hidden_size_1], initializer=w_initializer, dtype=tf.float64)
b_1 = tf.get_variable('svm_b1', [hidden_size_1], initializer=b_initializer, dtype=tf.float64)
logit = tf.matmul(inputData, W_1, transpose_b=True) + b_1
return logit, W_1
#前一个基本分类器被错误分类的样本的权值会增大,而正确分类的样本的权值会减小,并再次用来训练下一个基本分类器。同时,在每一轮迭代中,加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数才确定最终的强分类器。
def adaBoostTrainDS(data_set_):
classifierNum = len(classifierArray) #分类器个数
_m = 30 #测试样本总数
#拆除accuracy_set的最后一项,并将拆分后的dataSet作为预测数据
new_data_set = copy.deepcopy(data_set_)
labels_ = new_data_set.pop(LABEL)
testData = new_data_set
D_list_ = np.array([1/_m] * _m)
for t in range(classifierNum): #迭代次数(设置为分类器个数可视为最优值,否则在分类器数量较少情况下会导致alpha 无线趋于零)
#在权值分布D的情况下,再取N个弱分类器h1、h2和h3中误差率最小的分类器作为第t次迭代的基本分类器H_t(x)
#获取ε最小的分类器
model_info, error, errorDataIndexArr = get_minError_model(D_list_, testData, labels_)
#error ε 为错误样本的D总和
for row_ in range(_m):
row_data = testData.loc[[row_]] #每一行的数据
label = np.array([labels_.loc[row_]])
result = np.array(bulid_prediction_models(model_info, row_data))
if result != label:
error = error + D_list_[row_]
errorDataIndexArr.append(row_)
#更新α
alpha = 0.5 * np.log((1.0 - error) / (np.maximum(error, 1e-16)) )
model_info.modelAlpha = alpha
#D更新 用于下一轮迭代
for row_ in range(_m): #更新次数
print("Count =", t, "row =", row_, "Error =", error)
print(model_info.modeTypeName, "α_t =", alpha)
_D = D_list_[row_]
if row_ in errorDataIndexArr:
# 如果错误分类 D更新 D_t+1(i) = D_t(i) * (e^α) / sum(D) 增加错误样本的权重
print("Error")
_D_new = _D * np.exp(alpha)
else:
# 如果正确分类 D更新 D_t+1(i) = D_t(i) * (e^-α) / sum(D) 降低正确样本的权重
print("Correct")
_D_new = _D * np.exp(-alpha)
Z_t = sum(D_list_)
print("Z_t_1 =", sum(D_list_) )
D_list_[row_] = _D_new/Z_t
print("D_t =", _D, "D_t+1 =", D_list_[row_])
print("")
for i in range(len(classifierArray) ):
model_info = classifierArray[i]
print(model_info.modeTypeName, "α_t =", model_info.modelAlpha)
#获取ε最小的分类器
def get_minError_model(D_list, testData, labels):
minErrorModel = None
minErrorModel_errorDataIndexArr = []
minErrorModel_errorValue = 999
size_ = labels.size;
#得到最小error
for i in range(len(classifierArray) ):
model_info = classifierArray[i]
error = 0
errorDataIndexArr = []
for row_ in range(size_):
row_data = testData.loc[[row_]] #每一行的数据
label = np.array([labels.loc[row_]])
result = np.array(bulid_prediction_models(model_info, row_data))
if result != label:
error = error + D_list[row_]
errorDataIndexArr.append(row_)
if error < minErrorModel_errorValue:
minErrorModel = model_info
minErrorModel_errorValue = error
minErrorModel_errorDataIndexArr = errorDataIndexArr
return minErrorModel, minErrorModel_errorValue, minErrorModel_errorDataIndexArr
赞美机魂,赞美万机之神