目录
一、数据预处理
提供的数据集由两个文件夹组成,一个文件夹是“中”,另一个是“国”。每个图片命名如图所示,我的想法是对每个文件夹中的图片改名,使其成为“标签_序号”格式,方便后续划分数据集时填充标签。此处规定汉字“中”标签为0,汉字“国”标签为1。
1.对文件实现批量改名
def rename(self,path,flag):
# 批量改名,并设置标签,zhong-0 guo-1
filelist = os.listdir(path)
total_num = len(filelist)
i = 0
for item in filelist:
if item.endswith('.bmp'):
src = os.path.join(os.path.abspath(path), item)
dst = os.path.join(os.path.abspath(path), str(flag) + '_' + str(i) + '.bmp')
try:
os.rename(src, dst)
i += 1
except:
continue
print('total %d to rename & converted %d bmp' % (total_num, i))
2.将bmp图片转为numpy向量
对图片样本操作时,首先需要读取数据,将其转化为numpy向量,此处也可转化成数组。
原图:
转为向量:
代码:
def img2vector(self,fileName):
retMat = np.zeros([14700], int)
img = Image.open(fileName, "r")
array = np.array(img.getdata())
for i in range(len(array)): # 遍历文件所有行
for j in range(3):
retMat[i * 3 + j] = array[i][j]
return retMat
设置向量长度为14700的原因是:本文的图片全部为70*70的黑白图片,rgb中有三个变量,14700=70*70*3。
3.划分训练集和测试集
首先规定split_rate=0.25,规定从所有图片中选择四分之一作为测试集,剩下的为训练集。
因为不同标签的数据集在两个文件夹中,可以依次对这两个文件夹进行划分,再进行拼接,得到训练集和测试集。
定义read_data方法,main函数调用时分别读取两个文件夹的数据,返回两个文件夹划分好的训练、测试数据。
def read_data(self,path, split_rate):
#从数据集中随机选取split_rate*nums作为测试集,剩下的作为训练集,split_rate=0.25
fileList = os.listdir(path)
total_num = len(fileList)
dataSet = np.zeros([total_num, 14700], int) # 用于存放所有的数字文件
labels = np.zeros([total_num], str) # 用于存放对应的标签(与神经网络的不同)
for i in range(total_num):
filePath = fileList[i] # 获取文件名称/路径
digit = str(filePath.split('_')[0]) # 通过文件名获取标签
labels[i] = digit # 直接存放数字,并非one-hot向量
dataSet[i] = self.img2vector(path + '/' + filePath) # 读取文件内容
# split_rate*total_num
index = [i for i in range(int(split_rate * total_num))]
index1 = [i for i in range(int(split_rate * total_num), total_num)]
np.random.shuffle(index)
np.random.shuffle(index1)
test_dataSet = dataSet[index]
test_labels = labels[index]
train_dataSet = dataSet[index1]
train_labels = labels[index1]
return train_dataSet, train_labels, test_dataSet, test_labels
if __name__=='__main__':
demo = DataPreProcess()
path = "data_set"
path1 = path + "/guo"
path2 = path + "/zhong"
# demo.rename(path1,1)
# demo.rename(path2,0)
train_dataSet1, train_labels1, test_dataSet1, test_labels1 = demo.read_data(path1,0.25)
train_dataSet2, train_labels2, test_dataSet2, test_labels2 = demo.read_data(path2, 0.25)
二、训练,预测
1.训练
其实很简单,直接调用方法就可以啦。
knn = neighbors.KNeighborsClassifier(algorithm='kd_tree', n_neighbors=8)
# algorithm设置分类器算法为kd_tree,改变n_neighbors的值改变所需要查询的最近邻数目
knn.fit(train_dataSet, train_labels)
2.预测
res = knn.predict(dataSet) # 对测试集进行预测
error_num = np.sum(res != labels) # 统计分类错误的数目
num = len(dataSet) # 测试集的数目
print("Total num:", num, " Wrong num:", \
error_num, " WrongRate:", error_num / float(num))
总结
其实预测很鸡肋,自己画出的图片需要画的粗一点才可以预测出来。