Keras深度学习框架可以用来了解深度学习可以用来做什么,下面介绍一些使用Keras来做基础的图像分类的内容,欢迎各位交流。
参考资料:https://morvanzhou.github.io/tutorials/machine-learning/keras/2-3-CNN/
我使用的版本:Python2.7,numpy1.13.1,Theano0.9.0,Keras2.0.6,h5py2.5.0,opencv2.4.13,WIN7系统。
要做图像分类,首先需要有数据集,需要将下载到的图像数据集转化为Keras可以识别的numpy矩阵。需要得到X_train,X_test,y_train,y_test,其中X_train和X_test分别是一个4维矩阵,第一维代表有几幅图像,后三维代表图像数据,y_train和y_test是一维列表,表示对应的图像属于哪一类。
可以下载到的图像数据集一般分为两种,一种是由若干文件夹组成,每个文件夹的名字是该类别的名字,每个文件夹中包含若干图像,这种数据集需要自己划分训练集和测试集;另一种由train文件夹和test文件夹组成,每个文件夹中有一些文件夹,其名字是类别的名字,其中有很多的图像,这种则固定了训练集和测试集。有时候数据集中会有文件来说明图像的名字和对应的标注,但是对于图像分类来说,不需要这些标注也可以提取出需要的numpy矩阵。
这里使用简单的网络对Caltech101数据集进行分类,这里暂时不考虑去除背景类,经过简单的改动后也可对cifar10数据集进行分类。如果需要更高的准确率,需要修改所用的网络。
提取的方法如下:(get_data和get_2data函数分别对应上面说的两种数据集。)
def eachFile(filepath): #将目录内的文件名放入列表中
pathDir = os.listdir(filepath)
out = []
for allDir in pathDir:
child = allDir.decode('gbk') # .decode('gbk')是解决中文显示乱码问题
out.append(child)
return out
def get_data(data_name,train_percentage=0.7,resize=True,data_format=None): #从文件夹中获取图像数据
file_name = os.path.join(pic_dir_out,data_name+str(Width)+"X"+str(Height)+".pkl")
if os.path.exists(file_name): #判断之前是否有存到文件中
(X_train, y_train), (X_test, y_test) = cPickle.load(open(file_name,"rb"))
return (X_train, y_train), (X_test, y_test)
data_format = conv_utils.normalize_data_format(data_format)
pic_dir_set = eachFile(pic_dir_data)
X_train = []
y_train = []
X_test = []
y_test = []
label = 0
for pic_dir in pic_dir_set:
print pic_dir_data+pic_dir
if not os.path.isdir(os.path.join(pic_dir_data,pic_dir)):
continue
pic_set = eachFile(os.path.join(pic_dir_data,pic_dir))
pic_index = 0
train_count = int(len(pic_set)*train_percentage)
for pic_name in pic_set:
if not os.path.isfile(os.path.join(pic_dir_data,pic_dir,pic_name)):
continue
img = cv2.imread(os.path.join(pic_dir_data,pic_dir,pic_name))
if img is None:
continue
img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
if (resize):
img = cv2.resize(img,(Width,Height))
if (data_format == 'channels_last'):
img = img.reshape(-1,Width,Height,1)
elif (data_format == 'channels_first'):
img = img.reshape(-1,1,Width,Height)
if (pic_index < train_count):
X_train.append(img)
y_train.append(label)
else:
X_test.append(img)
y_test.append(label)
pic_index += 1
if len(pic_set) <> 0:
label += 1
X_train = np.concatenate(X_train,axis=0)
X_test = np.concatenate(X_test,axis=0)
y_train = np.array(y_train)
y_test = np.array(y_test)
cPickle.dump([(X_train, y_train), (X_test, y_test)],open(file_name,"wb"))
return (X_train, y_train), (X_test, y_test)
def get_2data(data_name,resize=True,data_format=None): #当数据被分为train和test两个部分时使用
file_name = os.path.join(pic_dir_out,data_name+str(Width)+"X"+str(Height)+".pkl")
if os.path.exists(file_name): #判断之前是否有存到文件中
(X_train, y_train), (X_test, y_test) = cPickle.load(open(file_name,"rb"))
return (X_train, y_train), (X_test, y_test)
data_format = conv_utils.normalize_data_format(data_format)
all_dir_set = eachFile(pic_dir_data)
X_train = []
y_train = []
X_test = []
y_test = []
for all_dir in all_dir_set:
if not os.path.isdir(os.path.join(pic_dir_data,all_dir)):
continue
label = 0
pic_dir_set = eachFile(os.path.join(pic_dir_data,all_dir))
for pic_dir in pic_dir_set:
print pic_dir_data+pic_dir
if not os.path.isdir(os.path.join(pic_dir_data,all_dir,pic_dir)):
continue
pic_set = eachFile(os.path.join(pic_dir_data,all_dir,pic_dir))
for pic_name in pic_set:
if not os.path.isfile(os.path.join(pic_dir_data,all_dir,pic_dir,pic_name)):
continue
img = cv2.imread(os.path.join(pic_dir_data,all_dir,pic_dir,pic_name))
if img is None:
continue
img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
if resize:
img = cv2.resize(img,(Width,Height))
if (data_format == 'channels_last'):
img = img.reshape(-1,Width,Height,1)
elif (data_format == 'channels_first'):
img = img.reshape(-1,1,Width,Height)
if ('train' in all_dir):
X_train.append(img)
y_train.append(label)
elif ('test' in all_dir):
X_test.append(img)
y_test.append(label)
if len(pic_set) <> 0:
labe