数据读取
给出的数据是mat格式存储的,19*19的灰度值,所以用loadmat就能直接读出
from scipy.io import loadmat
train_data = loadmat('task2/train(Task2)/train_data.mat')
train_label = loadmat('task2/train(Task2)/train_label.mat')
train_data = train_data.get('train_data')
train_label = train_label.get('train_label')
test_data = loadmat('task2/test(Task2)/test_data_2.mat')
test_data = test_data.get('test_data')
增强训练集
给出的训练集只有800个样本,想要在测试集上得到很好的效果是不可能的,所以先对训练集进行增强。
简单看了下训练集和测试集,人脸朝向都是一致的,所以不用做旋转增强,就做了上下翻折和缩放处理。
train_data_crop1 = []
train_data_crop2 = []
train_data_transpose = []
for img in train_data:
img = img.reshape(19,19)
img = np.array(img)
# 缩放
img_1 = img
img_1[0] = 0
img_1[18] = 0
for i in img_1:
i[0] = 0
i[18] = 0
img_crop1 = img_1.reshape(361)
train_data_crop1.append(img_crop1)
img_2 = img
img_2[0] = 0
img_2[1] = 0
img_2[18] = 0
img_2[17] = 0
for i in img_2:
i[0] = 0
i[1] = 0
i[18] = 0
i[17] = 0
img_crop2 = img_2.reshape(361)
train_data_crop2.append(img_crop2)
# 上下翻折
img = Image.fromarray(img)
img_transpose = img.transpose(Image.FLIP_TOP_BOTTOM)
img_transpose = np.array(img_transpose)
img_transpose = img_transpose.reshape(361)
train_data_transpose.append(img_transpose)
train_data_transpose = np.array(train_data_transpose)
train_data_crop1 = np.array(train_data_crop1)
train_data_crop2 = np.array(train_data_crop2)
train_data_enlarge = np.vstack((train_data, train_data_transpose))
train_data_enlarge = np.vstack((train_data_enlarge, train_data_crop1))
train_data_enlarge = np.vstack((train_data_enlarge, train_data_crop2))
train_label_enlarge = train_label
train_label_enlarge = np.vstack((train_label_enlarge, train_label))
train_label_enlarge = np.vstack((train_label_enlarge, train_label))
train_label_enlarge = np.vstack((train_label_enlarge, train_label))
SVM训练
要求是用libsvm进行训练,但是sklearn里面的svm模块更好用,所以就先用sklearn里面的svm训练,找到最佳参数就在换成libsvm。
parameters={'C':np.linspace(0.0001,10,20),'gamma':np.linspace(0.0001 ,5,20)}
svc = svm.SVC(kernel='poly')
model = GridSearchCV(svc, parameters, cv=5, scoring='accuracy', n_jobs=-1)
model.fit(train_data, train_label)
result = model.best_params_
但实际上网格搜索到的参数虽然在训练集和交叉验证上的表现都很好,但是在测试集上表现不尽人意,所以最后还是凑出来c = 0.1, gamma = 0.1 的时候最好。
用libsvm实现
# 数据格式转化
index = []
train = []
test = []
label = []
for i in range(1,362):
index.append(i)
for item in train_data:
data = dict(zip(index, item))
train.append(data)
for item in test_data:
data = dict(zip(index, item))
test.append(data)
for i in train_label:
label.append(i)
# 网格搜索最佳参数
acc = []
C = []
G = []
for i in range(-5,5):
for j in range(-5,5):
c = 10**i
gamma = 10**j
prob = svm_problem(label, train)
param = svm_parameter('-s 0 -t 2 -c '+ str(c) +' -g '+ str(gamma) +' -v 10')
model = svm_train(prob, param)
acc.append(model)
C.append(c)
G.append(gamma)
dir = acc.index(max(acc))
best_c = C[dir]
best_g = G[dir]
accuracy = acc[dir]
# 测试集预测
best_param = svm_parameter('-s 0 -t 2 -c '+str(best_c)+' -g '+str(best_g))
best_model = svm_train(prob, best_param)
p_label, p_acc, p_val = svm_predict([], test, best_model)
print(p_label)
输出
用给出的demo得到测试集标签(代码有点杂)
# coding=utf-8
"""
This is the submission demo for the task 2.
"""
from libsvm.svmutil import svm_predict
import numpy as np
import os
from sklearn import svm
from scipy.io import loadmat
from sklearn.neural_network import MLPClassifier
from PIL import Image
from libsvm.svm import *
from libsvm.svmutil import *
#output task2_result.txt
train_data = loadmat('task2/train(Task2)/train_data.mat')
train_label = loadmat('task2/train(Task2)/train_label.mat')
train_data = train_data.get('train_data')
train_label = train_label.get('train_label')
test_data = loadmat('task2/test(Task2)/test_data_2.mat')
test_data = test_data.get('test_data')
train_data_crop1 = []
train_data_crop2 = []
train_data_transpose = []
for img in train_data:
img = img.reshape(19,19)
img = np.array(img)
# 缩放
img_1 = img
img_1[0] = 0
img_1[18] = 0
for i in img_1:
i[0] = 0
i[18] = 0
img_crop1 = img_1.reshape(361)
train_data_crop1.append(img_crop1)
img_2 = img
img_2[0] = 0
img_2[1] = 0
img_2[18] = 0
img_2[17] = 0
for i in img_2:
i[0] = 0
i[1] = 0
i[18] = 0
i[17] = 0
img_crop2 = img_2.reshape(361)
train_data_crop2.append(img_crop2)
# 上下翻折
img = Image.fromarray(img)
img_transpose = img.transpose(Image.FLIP_TOP_BOTTOM)
img_transpose = np.array(img_transpose)
img_transpose = img_transpose.reshape(361)
train_data_transpose.append(img_transpose)
train_data_transpose = np.array(train_data_transpose)
train_data_crop1 = np.array(train_data_crop1)
train_data_crop2 = np.array(train_data_crop2)
train_data_enlarge = np.vstack((train_data, train_data_transpose))
train_data_enlarge = np.vstack((train_data_enlarge, train_data_crop1))
# train_data_enlarge = np.vstack((train_data_enlarge, train_data_crop2))
train_label_enlarge = train_label
train_label_enlarge = np.vstack((train_label_enlarge, train_label))
train_label_enlarge = np.vstack((train_label_enlarge, train_label))
# train_label_enlarge = np.vstack((train_label_enlarge, train_label))
def store_txt(label,result_txt):
"""
:param label: list of your classification labels
:param result_txt: output file
:return:
"""
with open(result_txt,"w") as w:
for index,result in enumerate(label,1):
w.write(str(index)+" "+str(result)+"\n") # imageID(int)+" "+label(-1\1,int)+"\n"
# example main function
def main():
label = svm_train()
# label = mlp_train()
label[label==0] = -1
store_txt(label,'task2_svm_result.txt')
def svm_train():
# model = svm.SVC(kernel='poly', C=0.1,coef0=3,degree=3,gamma=0.1) #0.797
# model = svm.SVC(kernel='linear') 0.769
# model = svm.SVC(kernel='rbf', C=0.1, gamma=0.01)
# model.fit(train_data_enlarge, train_label_enlarge)
# score = model.score(train_data_enlarge, train_label_enlarge)
prob = svm_problem(train_label_enlarge, train_data_enlarge)
param = svm_parameter('-s 0 -t 2 -c 0.1 -g 0.1')
model = svm_train(prob, param)
p_label, p_acc, p_val = svm_predict([], test_data, model)
# model.fit(train_data, train_label)
# score = model.score(train_data, train_label)
# print(score)
# #Predict Output
# predicted = model.predict(test_data)
return p_label
def mlp_train():
model = MLPClassifier(activation='logistic', solver='lbfgs', alpha=1e-5,hidden_layer_sizes=(5,), random_state=None , batch_size=200)
model.fit(train_data, train_label)
predict = model.predict(test_data)
return predict
if __name__ == "__main__":
main()
最后在网站上提交,0.902准确度,排名第三,还行。
##小道消息老师给出的训练集有4张图片故意给错了,但是因为懒所以懒得去找了