用如题方法实现人脸定位,在训练阶段,我想训练一个弱分类器,对于一个特征模板,我理解的是在一张样本图片的固定位置,固定大小计算一个特征值,其它的样本也是这样子算,最后得到一个特征值数组,从这个数组里面选出一个最佳阈值给分类器。但是如果更改取样的位置和大小,那岂不是有很多的弱分类器吗?难道要从中选一个误差最小的吗?这样子的话运算量太大了
有没有人能说一下具体的训练过程
还有样本权重是用到最后面计算分类误差率的吗?
(解决我的问题即可采纳)
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
训练过程:
Adaboost是一个迭代算法,它会在每一轮选择一个最佳的弱分类器加入到集成中。对于每个弱分类器$h$来说,它的训练过程如下:
对于每个样本,计算其对应的特征值的数组,然后根据特征值数组的阈值进行分类,得到分类结果。
根据分类结果计算加权的分类误差率(权值为上一轮错误分类的样本的权值),然后更新弱分类器的权重和权值分布。
在选取最佳弱分类器的过程中,要考虑不同位置和大小的特征模板,但是不需要对所有的可能性都进行训练。实际上,可以先对样本进行几轮训练,建立一个较好的基础模型,然后根据其表现来选择更具有代表性的特征模板,训练更多的弱分类器。
样本权重:
在Adaboost算法中,样本的权重会随着训练轮数不断更新。具体来说,在每一轮训练之后,错误分类的样本的权重会变得更高,而正确分类的样本权重会变得更低。这样做的目的是让弱分类器更关注容易分类错误的样本,从而提高整体的准确率。
具体实现:
以下是基于python的Adaboost和Haar特征的实现代码:
import numpy as np
import cv2
def Haar_feature(img, x, y, w, h):
# 计算Haar特征
feature = [0]*3 # 三种类型的Haar特征
sum_a = 0
sum_b = 0
sum_c = 0
for i in range(y, y+h):
for j in range(x, x+w):
if i+h <= y+h/2:
sum_a += img[i][j]
elif i >= y+h/2:
sum_c += img[i][j]
else:
sum_b += img[i][j]
area = w * h
feature[0] = (sum_a - sum_b) / area
feature[1] = (sum_b - sum_c) / area
feature[2] = (sum_a - sum_c) / area
return feature
def Adaboost(feature_list, img_list, label_list, T):
# T为训练轮数
N = len(feature_list) # 特征数目
M = len(img_list) # 样本数目
w = [1/M]*M # 样本权重
alpha = [0]*T # 弱分类器的权重
h = [] # 弱分类器
for t in range(T):
error = [0]*N
for i in range(N):
feature = feature_list[i]
y_pred = np.sign(np.dot(w, np.array([feature[j] for j in range(M)])))
y_true = np.array([label_list[j] for j in range(M)])
error[i] = np.sum((y_pred != y_true) * w) / np.sum(w) # 加权分类误差率
min_error = min(error)
if min_error > 0.5: # 如果无法分类,则不再添加弱分类器
break
min_index = error.index(min_error)
h.append(feature_list[min_index])
alpha[t] = np.log((1-min_error) / min_error) / 2 # 弱分类器的权重
for i in range(M):
if label_list[i] == np.sign(np.dot(w, np.array([feature_list[min_index][j] for j in range(M)]))):
w[i] *= np.exp(-alpha[t])
else:
w[i] *= np.exp(alpha[t])
w /= np.sum(w) # 归一化
return [alpha[:t+1], h[:t+1]] # 返回弱分类器的权重和特征
def predict(img, feature, alpha):
# 预测
score = np.sum([alpha[i] * feature[i] for i in range(len(alpha))])
if score > 0:
return 1
else:
return -1
def get_all_feature(img, min_size=40, max_size=150):
# 提取所有特征模板
feature_list = []
w, h = img.shape
for size in range(min_size, max_size+1, 10):
for i in range(0, w-size, 5):
for j in range(0, h-size, 5):
feature_list.append(Haar_feature(img, j, i, size//2, size//2))
feature_list.append(Haar_feature(img, j+size//2, i, size//2, size//2))
feature_list.append(Haar_feature(img, j, i+size//2, size//2, size//2))
return feature_list
其中,Haar_feature
用来计算Haar特征,Adaboost
用于训练并返回弱分类器的权重和特征,predict
用于预测,get_all_feature
用于提取所有特征模板。
使用示例:
以下是使用示例代码,其中,首先将样本图像读入,并根据标签进行标记,然后调用Adaboost
进行训练,然后使用测试集对分类器的性能进行评估。
if __name__ == '__main__':
# 读取样本图像和标签
pos_dir = './data/positive/'
neg_dir = './data/negative/'
pos_list = os.listdir(pos_dir)
neg_list = os.listdir(neg_dir)
img_list = []
label_list = []
for img_name in pos_list:
img = cv2.imread(os.path.join(pos_dir, img_name), 0)
if img is not None and img.shape == (100, 100):
img_list.append(img.ravel())
label_list.append(1)
for img_name in neg_list:
img = cv2.imread(os.path.join(neg_dir, img_name), 0)
if img is not None and img.shape == (100, 100):
img_list.append(img.ravel())
label_list.append(-1)
# 划分训练集和测试集
idx = np.arange(len(img_list))
np.random.shuffle(idx)
train_img = [img_list[i] for i in idx[:500]] # 500个样本用于训练
train_label = [label_list[i] for i in idx[:500]]
test_img = [img_list[i] for i in idx[500:]] # 300个样本用于测试
test_label = [label_list[i] for i in idx[500:]]
# 训练
feature_list = [Haar_feature(np.array(img_list[i], dtype=np.uint8).reshape(100, 100), 0, 0, 100, 100) for i in range(len(img_list))]
alpha, features = Adaboost(feature_list, train_img, train_label, T=100)
# 预测
correct = 0
for i in range(len(test_img)):
feature = Haar_feature(np.array(test_img[i], dtype=np.uint8).reshape(100, 100), 0, 0, 100, 100)
y_pred = predict(np.array(test_img[i], dtype=np.uint8).reshape(100, 100), features, alpha)
if y_pred == test_label[i]:
correct += 1
print('Accuracy:', correct / len(test_img))
其中,样本数据放在./data/positive
和./data/negative
文件夹中。
如果我的回答解决了您的问题,请采纳!