我制作了一个基于人脸图像进行性别分类的小程序。我使用耶鲁人脸数据库(男性 175 张图像,女性相同数量),将它们转换为灰度和均衡直方图,因此预处理后的图像如下所示:
我运行以下代码来测试结果(它使用 SVM 和线性内核):
def run_gender_classifier():
Xm, Ym = mkdataset('gender/male', 1) # mkdataset just preprocesses images,
Xf, Yf = mkdataset('gender/female', 0) # flattens them and stacks into a matrix
X = np.vstack([Xm, Xf])
Y = np.hstack([Ym, Yf])
X_train, X_test, Y_train, Y_test = train_test_split(X, Y,
test_size=0.1,
random_state=100)
model = svm.SVC(kernel='linear')
model.fit(X_train, Y_train)
print("Results:\n%s\n" % (
metrics.classification_report(
Y_test, model.predict(X_test))))
并获得100%的精度!
In [22]: run_gender_classifier()
Results:
precision recall f1-score support
0 1.00 1.00 1.00 16
1 1.00 1.00 1.00 19
avg / total 1.00 1.00 1.00 35
我可以期待不同的结果,但 100% 正确的图像分类对我来说真的很可疑。
此外,当我将内核更改为RBF时,结果变得非常糟糕:
In [24]: run_gender_classifier()
Results:
precision recall f1-score support
0 0.46 1.00 0.63 16
1 0.00 0.00 0.00 19
avg / total 0.21 0.46 0.29 35
这对我来说似乎更奇怪。
所以我的问题是:
- 我的方法或代码有什么错误吗?
- 如果不是,线性核的结果怎么会这么好,而 RBF 的结果怎么会这么差呢?
请注意,逻辑回归我也得到了 100% 正确的结果,而深度信念网络的结果非常差,所以它不是特定于 SVM,而是针对线性和非线性模型。
为了完整起见,这是我用于预处理和制作数据集的代码:
import cv2
from sklearn import linear_model, svm, metrics
from sklearn.cross_validation import train_test_split
def preprocess(im):
im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
im = cv2.resize(im, (100, 100))
return cv2.equalizeHist(im)
def mkdataset(path, label):
images = (cv2.resize(cv2.imread(fname), (100, 100))
for fname in list_images(path))
images = (preprocess(im) for im in images)
X = np.vstack([im.flatten() for im in images])
Y = np.repeat(label, X.shape[0])
return X, Y