CNN提取图片特征,之后用SVM分类

https://blog.csdn.net/qq_27756361/article/details/80479278

先用CNN提取特征,之后用SVM分类,平台是TensorFlow 1.3.0-rc0,python3.6 

这个是我的一个小小的测试,下面这个链接是我主要参考的,在实现过程中,本来想使用vgg16或者VGG19做迁移来提取特征,但是担心自己的算力不够,还有就是UCI手写数据集本来就是一个不大的数据集,使用vgg16或vgg19有点杀鸡用牛刀的感觉。于是放弃做迁移。

我的代码主要是基于下面链接来的。参考链接点击打开链接

这个代码主要是,通过一个CNN网络,在网络的第一个全连接层也就h_fc1得到的一个一维的256的一个特征向量,将这个特征向量作为的svm的输入。主要的操作是在代码行的140-146.    同时代码也实现了CNN的过程(读一下代码就知道)。

如果你要是知道你的CNN的结构,然后就知道在全连接层输出的其实就是一个特征向量。直接用这个特征向量简单处理输入到svm中就可以。

具体的参考论文和代码数据集等,百度网盘

CNN卷积层简介

CNN,有两个卷积(5*5)池化层(2*2的maxPooling),然后两个全连接层h_fc1和h_fc2,我只使用第一个全连接层h_fc1就提取了特征。

然后中间的激活函数使用的是relu函数,同时为了防止过拟合使用了dropout的技巧。然后这个代码中其实是实现了完整的CNN的的预测的,损失使用交叉熵,优化器使用了AdamOptimizer。

图片大小的变化:

最后从全连接层提取的256维的向量。输入svm。

 

SVM分类

SVM采用的是RBF核(高斯核),C取0.9

也可以尝试线性核,我试了一下效果差不多,但是没有高斯核分类效率好。

流程和实验设计

 

流程:整理训练网络的数据,对样本进行处理 -> 建立卷积神经网络-> 将数据代入进行训练 -> 保存训练好的模型(从全连接层提取特征) -> 把数据代入模型获得特征向量 -> 用特征向量代替原本的输入送入SVM训练 -> 测试时同样将h_fc1转换为特征向量之后用SVM预测,获得结果。

使用留出法样本处理和评价:

1.将原样本随机地分为两半。一份为训练集,一份为测试集

2.重复1过程十次,得到十个训练集和十个对应的测试集

3.取十份训练集中的一份和其对应的测试集。代入到CNN和SVM中训练。

4.依次取训练集和测试集,则可完成十次第一步。

5.将十次的表现综合评价,十次验证取平均值,计算正确率、准确率、召回率、F1值。比如 F1 分数 , 用于测量不均衡数据的精度. 

 

 
  1. # coding=utf8

  2. import random

  3.  
  4. import numpy as np

  5. import tensorflow as tf

  6. from sklearn import svm

  7. from sklearn import preprocessing

  8. import time

  9.  
  10. start = time.clock()

  11.  
  12. right0 = 0.0  # 记录预测为1且实际为1的结果数

  13. error0 = 0  # 记录预测为1但实际为0的结果数

  14. right1 = 0.0  # 记录预测为0且实际为0的结果数

  15. error1 = 0  # 记录预测为0但实际为1的结果数

  16.  
  17. for file_num in range(10):

  18.     # 在十个随机生成的不相干数据集上进行测试,将结果综合

  19.     print('testing NO.%d dataset.......' % file_num)

  20.     ff = open('digit_train_' + file_num.__str__() + '.data')

  21.     rr = ff.readlines()

  22.     x_test2 = []

  23.     y_test2 = []

  24.     

  25.     for i in range(len(rr)):

  26.         x_test2.append(list(map(int, map(float, rr[i].split(' ')[:256]))))

  27.         y_test2.append(list(map(int, rr[i].split(' ')[256:266])))

  28.     ff.close()

  29.     # 以上是读出训练数据

  30.     ff2 = open('digit_test_' + file_num.__str__() + '.data')

  31.     rr2 = ff2.readlines()

  32.     x_test3 = []

  33.     y_test3 = []

  34.     for i in range(len(rr2)):

  35.         x_test3.append(list(map(int, map(float, rr2[i].split(' ')[:256]))))

  36.         y_test3.append(list(map(int, rr2[i].split(' ')[256:266])))

  37.     ff2.close()

  38.     # 以上是读出测试数据

  39.  
  40.     sess = tf.InteractiveSession()

  41.     # 建立一个tensorflow的会话

  42.  
  43.     # 初始化权值向量

  44.     def weight_variable(shape):

  45.         initial = tf.truncated_normal(shape, stddev=0.1)

  46.         return tf.Variable(initial)

  47.  
  48.  
  49.     # 初始化偏置向量

  50.     def bias_variable(shape):

  51.         initial = tf.constant(0.1, shape=shape)

  52.         return tf.Variable(initial)

  53.  
  54.  
  55.     # 二维卷积运算,步长为1,输出大小不变

  56.     def conv2d(x, W):

  57.         return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

  58.  
  59.  
  60.     # 池化运算,将卷积特征缩小为1/2

  61.     def max_pool_2x2(x):

  62.         return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

  63.  
  64.     # 给x,y留出占位符,以便未来填充数据

  65.     x = tf.placeholder("float", [None, 256])

  66.     y_ = tf.placeholder("float", [None, 10])

  67.     # 设置输入层的W和b

  68.     W = tf.Variable(tf.zeros([256, 10]))

  69.     b = tf.Variable(tf.zeros([10]))

  70.     # 计算输出,采用的函数是softmax(输入的时候是one hot编码)

  71.     y = tf.nn.softmax(tf.matmul(x, W) + b)

  72.     # 第一个卷积层,5x5的卷积核,输出向量是32维

  73.     w_conv1 = weight_variable([5, 5, 1, 32])

  74.     b_conv1 = bias_variable([32])

  75.     x_image = tf.reshape(x, [-1, 16, 16, 1])

  76.     # 图片大小是16*16,,-1代表其他维数自适应

  77.     h_conv1 = tf.nn.relu(conv2d(x_image, w_conv1) + b_conv1)

  78.     h_pool1 = max_pool_2x2(h_conv1)

  79.     # 采用的最大池化,因为都是1和0,平均池化没有什么意义

  80.  
  81.     # 第二层卷积层,输入向量是32维,输出64维,还是5x5的卷积核

  82.     w_conv2 = weight_variable([5, 5, 32, 64])

  83.     b_conv2 = bias_variable([64])

  84.  
  85.     h_conv2 = tf.nn.relu(conv2d(h_pool1, w_conv2) + b_conv2)

  86.     h_pool2 = max_pool_2x2(h_conv2)

  87.  
  88.     # 全连接层的w和b

  89.     w_fc1 = weight_variable([4 * 4 * 64, 256])

  90.     b_fc1 = bias_variable([256])

  91.     # 此时输出的维数是256维

  92.     h_pool2_flat = tf.reshape(h_pool2, [-1, 4 * 4 * 64])

  93.     h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, w_fc1) + b_fc1)

  94.     # h_fc1是提取出的256维特征,很关键。后面就是用这个输入到SVM中

  95.  
  96.     # 设置dropout,否则很容易过拟合

  97.     keep_prob = tf.placeholder("float")

  98.     h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

  99.  
  100.     # 输出层,在本实验中只利用它的输出反向训练CNN,至于其具体数值我不关心

  101.     w_fc2 = weight_variable([256, 10])

  102.     b_fc2 = bias_variable([10])

  103.  
  104.     y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, w_fc2) + b_fc2)

  105.     cross_entropy = -tf.reduce_sum(y_ * tf.log(y_conv))

  106.     # 设置误差代价以交叉熵的形式

  107.     train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

  108.     # 用adma的优化算法优化目标函数

  109.     correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))

  110.     accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

  111.     sess.run(tf.global_variables_initializer())

  112.     for i in range(3000):

  113.         # 跑3000轮迭代,每次随机从训练样本中抽出50个进行训练

  114.         batch = ([], [])

  115.         p = random.sample(range(795), 50)

  116.         for k in p:

  117.             batch[0].append(x_test2[k])

  118.             batch[1].append(y_test2[k])

  119.         if i % 100 == 0:

  120.             train_accuracy = accuracy.eval(feed_dict={x: batch[0], y_: batch[1], keep_prob: 1.0})

  121.             # print "step %d, train accuracy %g" % (i, train_accuracy)

  122.         train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.6})

  123.         # 设置dropout的参数为0.6,测试得到,大点收敛的慢,小点立刻出现过拟合

  124.  
  125.     print("test accuracy %g" % accuracy.eval(feed_dict={x: x_test3, y_: y_test3, keep_prob: 1.0}))

  126.     # def my_test(input_x):

  127.     #     y = tf.nn.softmax(tf.matmul(sess.run(x), W) + b)

  128.     

  129.     for h in range(len(y_test2)):

  130.         if np.argmax(y_test2[h]) == 7:

  131.             y_test2[h] = 1

  132.         else:

  133.             y_test2[h] = 0

  134.     for h in range(len(y_test3)):

  135.         if np.argmax(y_test3[h]) == 7:

  136.             y_test3[h] = 1

  137.         else:

  138.             y_test3[h] = 0

  139.     # 以上两步都是为了将源数据的one hot编码改为1和0,我的学号尾数为7

  140.     x_temp = []

  141.     for g in x_test2:

  142.         x_temp.append(sess.run(h_fc1, feed_dict={x: np.array(g).reshape((1, 256))})[0])

  143.     # 将原来的x带入训练好的CNN中计算出来全连接层的特征向量,将结果作为SVM中的特征向量

  144.     x_temp2 = []

  145.     for g in x_test3:

  146.         x_temp2.append(sess.run(h_fc1, feed_dict={x: np.array(g).reshape((1, 256))})[0])

  147.  
  148.     clf = svm.SVC(C=0.9, kernel='linear')  #linear kernel

  149. #    clf = svm.SVC(C=0.9, kernel='rbf')   #RBF kernel

  150.     # SVM选择了RBF核,C选择了0.9

  151. #    x_temp = preprocessing.scale(x_temp)  #normalization

  152.     clf.fit(x_temp, y_test2)

  153.     

  154.     print('svm testing accuracy:')

  155.     print(clf.score(x_temp2,y_test3))

  156.     for j in range(len(x_temp2)):

  157.         # 验证时出现四种情况分别对应四个变量存储

  158.         #这里报错了,需要对其进行reshape(1,-1)

  159.         if clf.predict(x_temp2[j].reshape(1,-1))[0] == y_test3[j] == 1:

  160.             right0 += 1

  161.         elif clf.predict(x_temp2[j].reshape(1,-1))[0] == y_test3[j] == 0:

  162.             right1 += 1

  163.         elif clf.predict(x_temp2[j].reshape(1,-1))[0] == 1 and y_test3[j] == 0:

  164.             error0 += 1

  165.         else:

  166.             error1 += 1

  167.     

  168. accuracy = right0 / (right0 + error0)  # 准确率

  169. recall = right0 / (right0 + error1)  # 召回率

  170. print('svm right ratio ', (right0 + right1) / (right0 + right1 + error0 + error1))

  171. print ('accuracy ', accuracy)

  172. print ('recall ', recall)

  173. print ('F1 score ', 2 * accuracy * recall / (accuracy + recall))  # 计算F1值

  174.  
  175. end = time.clock()

  176. print("time is :")

  177. print(end-start)

使用CNN之后用SVM分类。这个操作有很多。比如RCNN(Regions with CNN features)用于目标检测的网络的一系列的算法【SPP-Net】。基本就是CNN之后svm。

 

参考文献

[1] Deep Learning using Linear Support Vector Machines, ICML 2013

[2] How transferable are features in deep neural networks?, Jason Yosinski,1 Jeff Clune,2 Yoshua Bengio, NIPS 2014

[3] CNN Features off-the-shelf: an Astounding Baseline for Recognition, Ali Sharif Razavian Hossein Azizpour Josephine Sullivan Stefan Carlsson CVAP, KTH (Royal Institute of Technology). CVPR 2014

主要参考第一篇,具体的论文我把论文放到百度网盘中了:

https://pan.baidu.com/s/1Ghh4nfjfBKDyA47fc6M4JQ

有相同的CNN之后使用SVM的一些GitHub的开源代码:

https://github.com/Fdevmsy/Image_Classification_with_5_methods

https://github.com/efidalgo/AutoBlur_CNN_Features

https://github.com/tomrunia/TF_FeatureExtraction

  • 4
    点赞
  • 114
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
matlabcnn-svm图像分类是一种基于深度学习和支持向量机技术的图像分类方法。该方法的实施流程可以分为三个主要步骤。 首先,需要使用MATLAB中的CNN(卷积神经网络)工具箱来构建和训练一个卷积神经网络。卷积神经网络是一种深度学习算法,通过多层卷积层、池化层和全连接层来学习图像的特征表示。在这个步骤中,我们可以使用MATLAB提供的各种预训练的卷积神经网络模型,也可以根据任务的需求自定义网络结构。通过在大规模图像数据集上进行训练,网络会学习到更高层次的图像特征。 第二步是使用训练好的卷积神经网络提取图像的特征向量。将每个图像输入到网络中,通过网络的前向传播,获取隐藏层的激活值。这些激活值可以被视为图像在卷积神经网络中经过多层变换得到的高级特征表示,可以明显区分不同类别的图像。 最后一步是将提取特征向量输入到SVM(支持向量机)分类器中进行分类。支持向量机是一种经典的监督学习算法,可以根据特征向量的分布性质来学习一个边界,将不同类别的特征向量区分开来。通过在训练集上学习支持向量机模型的参数,并使用该模型对测试集中的图像进行分类,可以得到图像的预测结果。 总结来说,matlabcnn-svm图像分类是一个结合了卷积神经网络和支持向量机的图像分类方法。通过使用MATLAB中的CNN工具箱构建和训练卷积神经网络,提取图像特征向量,并将其输入到支持向量机分类器中,可以实现对图像的准确分类

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值