Я создал небольшую программу для классификации пола на основе изображения лица. Я использовал базу данных лиц Йельского университета (175 изображений для мужчин и столько же для самки), преобразовали их в оттенки серого и выровняли гистограммы, поэтому после предварительной обработки изображения выглядят так:
Я запустил следующий код для проверки результатов (он использует SVM и ядро linear):
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