图片分类_svm图片分类 - CSDN
精华内容
参与话题
  • 用Tensorflow实现图片分类+详细注解

    万次阅读 多人点赞 2018-09-21 17:07:04
    使用tensorflow实现花卉分类,训练样本用的是网上的花卉数据集,测试样本是在网上重新下载的各种花的图片,代码如下。   from skimage import io,transform #skimage模块下的io transform(图像的形变与缩放)模块 ...

    使用tensorflow实现花卉分类,训练样本用的是网上的花卉数据集,测试样本是在网上重新下载的各种花的图片,代码如下。

     

    from skimage import io,transform #skimage模块下的io transform(图像的形变与缩放)模块
    import glob  #glob 文件通配符模块
    import os    #os 处理文件和目录的模块
    import tensorflow as tf 
    import numpy as np   #多维数据处理模块
    import time
                          
    #数据集地址
    path='E:/data/flower/flower_photos/'
    #模型保存地址
    model_path='E:/data/flower/model/fc_model.ckpt'
    
    #将所有的图片resize成100*100
    w=100
    h=100
    c=3
    
    
    #读取图片+数据处理                    
    def read_img(path):
        #os.listdir(path) 返回path指定的文件夹包含的文件或文件夹的名字的列表
        #os.path.isdir(path)判断path是否是目录
        #b = [x+x for x in list1 if x+x<15 ]  列表生成式,循环list1,当if为真时,将x+x加入列表b
        cate=[path+x for x in os.listdir(path) if os.path.isdir(path+x)]
        imgs=[]
        labels=[]
        for idx,folder in enumerate(cate):
            #glob.glob(s+'*.py') 从目录通配符搜索中生成文件列表 
            for im in glob.glob(folder+'/*.jpg'):
                #输出读取的图片的名称  
                print('reading the images:%s'%(im))
                #io.imread(im)读取单张RGB图片 skimage.io.imread(fname,as_grey=True)读取单张灰度图片
                #读取的图片 
                img=io.imread(im)
                #skimage.transform.resize(image, output_shape)改变图片的尺寸
                img=transform.resize(img,(w,h))
                #将读取的图片数据加载到imgs[]列表中
                imgs.append(img)
                #将图片的label加载到labels[]中,与上方的imgs索引对应
                labels.append(idx)
       #将读取的图片和labels信息,转化为numpy结构的ndarr(N维数组对象(矩阵))数据信息
        return np.asarray(imgs,np.float32),np.asarray(labels,np.int32)
     #调用读取图片的函数,得到图片和labels的数据集   
    data,label=read_img(path)
    
    
    #打乱顺序
    #读取data矩阵的第一维数(图片的个数)
    num_example=data.shape[0]
    #产生一个num_example范围,步长为1的序列
    arr=np.arange(num_example)
    #调用函数,打乱顺序
    np.random.shuffle(arr)
    #按照打乱的顺序,重新排序
    data=data[arr]
    label=label[arr]
    
    
    #将所有数据分为训练集和验证集
    ratio=0.8
    s=np.int(num_example*ratio)
    x_train=data[:s]
    y_train=label[:s]
    x_val=data[s:]
    y_val=label[s:]
    
    
    #-----------------构建网络----------------------
    #本程序cnn网络模型,共有7层,前三层为卷积层,后三层为全连接层,前三层中,每层包含卷积、激活、池化层
    #占位符设置输入参数的大小和格式
    x=tf.placeholder(tf.float32,shape=[None,w,h,c],name='x')
    y_=tf.placeholder(tf.int32,shape=[None,],name='y_')
    
    def inference(input_tensor, train, regularizer):
        #-----------------------第一层----------------------------
        with tf.variable_scope('layer1-conv1'):
           #初始化权重conv1_weights为可保存变量,大小为5x5,3个通道(RGB),数量为32个
            conv1_weights = tf.get_variable("weight",[5,5,3,32],initializer=tf.truncated_normal_initializer(stddev=0.1))
            #初始化偏置conv1_biases,数量为32个    
            conv1_biases = tf.get_variable("bias", [32], initializer=tf.constant_initializer(0.0))
            #卷积计算,tf.nn.conv2d为tensorflow自带2维卷积函数,input_tensor为输入数据,
            #conv1_weights为权重,strides=[1, 1, 1, 1]表示左右上下滑动步长为1,padding='SAME'表示输入和输出大小一样,即补0
            conv1 = tf.nn.conv2d(input_tensor, conv1_weights, strides=[1, 1, 1, 1], padding='SAME')
            #激励计算,调用tensorflow的relu函数
            relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_biases))
    
        with tf.name_scope("layer2-pool1"):
           #池化计算,调用tensorflow的max_pool函数,strides=[1,2,2,1],表示池化边界,2个对一个生成,padding="VALID"表示不操作。
            pool1 = tf.nn.max_pool(relu1, ksize = [1,2,2,1],strides=[1,2,2,1],padding="VALID")
    #-----------------------第二层----------------------------
        with tf.variable_scope("layer3-conv2"):
             #同上,不过参数的有变化,根据卷积计算和通道数量的变化,设置对应的参数
            conv2_weights = tf.get_variable("weight",[5,5,32,64],initializer=tf.truncated_normal_initializer(stddev=0.1))
            conv2_biases = tf.get_variable("bias", [64], initializer=tf.constant_initializer(0.0))
            conv2 = tf.nn.conv2d(pool1, conv2_weights, strides=[1, 1, 1, 1], padding='SAME')
            relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_biases))
    
        with tf.name_scope("layer4-pool2"):
            pool2 = tf.nn.max_pool(relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')
    #-----------------------第三层----------------------------
            #同上,不过参数的有变化,根据卷积计算和通道数量的变化,设置对应的参数
        with tf.variable_scope("layer5-conv3"):
            conv3_weights = tf.get_variable("weight",[3,3,64,128],initializer=tf.truncated_normal_initializer(stddev=0.1))
            conv3_biases = tf.get_variable("bias", [128], initializer=tf.constant_initializer(0.0))
            conv3 = tf.nn.conv2d(pool2, conv3_weights, strides=[1, 1, 1, 1], padding='SAME')
            relu3 = tf.nn.relu(tf.nn.bias_add(conv3, conv3_biases))
    
        with tf.name_scope("layer6-pool3"):
            pool3 = tf.nn.max_pool(relu3, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')
    #-----------------------第四层----------------------------
            #同上,不过参数的有变化,根据卷积计算和通道数量的变化,设置对应的参数
        with tf.variable_scope("layer7-conv4"):
            conv4_weights = tf.get_variable("weight",[3,3,128,128],initializer=tf.truncated_normal_initializer(stddev=0.1))
            conv4_biases = tf.get_variable("bias", [128], initializer=tf.constant_initializer(0.0))
            conv4 = tf.nn.conv2d(pool3, conv4_weights, strides=[1, 1, 1, 1], padding='SAME')
            relu4 = tf.nn.relu(tf.nn.bias_add(conv4, conv4_biases))
    
        with tf.name_scope("layer8-pool4"):
            pool4 = tf.nn.max_pool(relu4, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')
            nodes = 6*6*128
            reshaped = tf.reshape(pool4,[-1,nodes])
            #使用变形函数转化结构
    #-----------------------第五层---------------------------
        with tf.variable_scope('layer9-fc1'):
            #初始化全连接层的参数,隐含节点为1024个
            fc1_weights = tf.get_variable("weight", [nodes, 1024],
                                          initializer=tf.truncated_normal_initializer(stddev=0.1))
            if regularizer != None: tf.add_to_collection('losses', regularizer(fc1_weights))#正则化矩阵
            fc1_biases = tf.get_variable("bias", [1024], initializer=tf.constant_initializer(0.1))
            #使用relu函数作为激活函数
            fc1 = tf.nn.relu(tf.matmul(reshaped, fc1_weights) + fc1_biases)
             #采用dropout层,减少过拟合和欠拟合的程度,保存模型最好的预测效率
            if train: fc1 = tf.nn.dropout(fc1, 0.5)
    #-----------------------第六层----------------------------
        with tf.variable_scope('layer10-fc2'):
             #同上,不过参数的有变化,根据卷积计算和通道数量的变化,设置对应的参数
            fc2_weights = tf.get_variable("weight", [1024, 512],
                                          initializer=tf.truncated_normal_initializer(stddev=0.1))
            if regularizer != None: tf.add_to_collection('losses', regularizer(fc2_weights))
            fc2_biases = tf.get_variable("bias", [512], initializer=tf.constant_initializer(0.1))
    
            fc2 = tf.nn.relu(tf.matmul(fc1, fc2_weights) + fc2_biases)
            if train: fc2 = tf.nn.dropout(fc2, 0.5)
    #-----------------------第七层----------------------------
        with tf.variable_scope('layer11-fc3'):
             #同上,不过参数的有变化,根据卷积计算和通道数量的变化,设置对应的参数
            fc3_weights = tf.get_variable("weight", [512, 5],
                                          initializer=tf.truncated_normal_initializer(stddev=0.1))
            if regularizer != None: tf.add_to_collection('losses', regularizer(fc3_weights))
            fc3_biases = tf.get_variable("bias", [5], initializer=tf.constant_initializer(0.1))
            logit = tf.matmul(fc2, fc3_weights) + fc3_biases #matmul矩阵相乘
       #返回最后的计算结果
        return logit
    
    #---------------------------网络结束---------------------------
    #设置正则化参数为0.0001
    regularizer = tf.contrib.layers.l2_regularizer(0.0001)
    #将上述构建网络结构引入
    logits = inference(x,False,regularizer)
    
    
    #(小处理)将logits乘以1赋值给logits_eval,定义name,方便在后续调用模型时通过tensor名字调用输出tensor
    b = tf.constant(value=1,dtype=tf.float32)
    logits_eval = tf.multiply(logits,b,name='logits_eval') #b为1
    
    #设置损失函数,作为模型训练优化的参考标准,loss越小,模型越优
    loss=tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=y_)
    #设置整体学习率为α为0.001
    train_op=tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)
    #设置预测精度
    correct_prediction = tf.equal(tf.cast(tf.argmax(logits,1),tf.int32), y_)    
    acc= tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    
    
    #定义一个函数,按批次取数据
    def minibatches(inputs=None, targets=None, batch_size=None, shuffle=False):
        assert len(inputs) == len(targets)
        if shuffle:
            indices = np.arange(len(inputs))
            np.random.shuffle(indices)
        for start_idx in range(0, len(inputs) - batch_size + 1, batch_size):
            if shuffle:
                excerpt = indices[start_idx:start_idx + batch_size]
            else:
                excerpt = slice(start_idx, start_idx + batch_size)
            yield inputs[excerpt], targets[excerpt]
    
    
    #训练和测试数据,可将n_epoch设置更大一些
    
    
    #迭代次数
    n_epoch=10                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
    #每次迭代输入的图片数据
    batch_size=64
    saver = tf.train.Saver(max_to_keep=1)#可以指定保存的模型个数,利用max_to_keep=4,则最终会保存4个模型(
    with tf.Session() as sess:
        #初始化全局参数
        sess.run(tf.global_variables_initializer())
        #开始迭代训练,调用的都是前面设置好的函数或变量
        for epoch in range(n_epoch):
            start_time = time.time()
        
            #training#训练集
            train_loss, train_acc, n_batch = 0, 0, 0
            for x_train_a, y_train_a in minibatches(x_train, y_train, batch_size, shuffle=True):
                _,err,ac=sess.run([train_op,loss,acc], feed_dict={x: x_train_a, y_: y_train_a})
                train_loss += err; train_acc += ac; n_batch += 1
                print("   train loss: %f" % (np.sum(train_loss)/ n_batch))
                print("   train acc: %f" % (np.sum(train_acc)/ n_batch))
        
            #validation#验证集
            val_loss, val_acc, n_batch = 0, 0, 0
            for x_val_a, y_val_a in minibatches(x_val, y_val, batch_size, shuffle=False):
                err, ac = sess.run([loss,acc], feed_dict={x: x_val_a, y_: y_val_a})
                val_loss += err; val_acc += ac; n_batch += 1
                print("   validation loss: %f" % (np.sum(val_loss)/ n_batch))
                print("   validation acc: %f" % (np.sum(val_acc)/ n_batch))
            #保存模型及模型参数   
            if epoch % 2 == 0 :
                 saver.save(sess,model_path,global_step=epoch)
    

           上面的验证精度大约为0.8,可以自己修改模型,提高精度。下面为测试代码,测试图片我下载了好多张,全放在了各个文件夹中,通过遍历文件夹读取图片。

    from skimage import io,transform
    import tensorflow as tf
    import numpy as np
    import os    #os 处理文件和目录的模块
    import glob  #glob 文件通配符模块
    # 此程序作用于进行简单的预测,取5个图片来进行预测,如果有多数据预测,按照cnn.py中,读取数据的方式即可
    
    
    path='E:/data/flower/test_photos/'
    #类别代表字典
    flower_dict = {0:'dasiy',1:'dandelion',2:'roses',3:'sunflowers',4:'tulips'}
    
    w=100
    h=100
    c=3
    
    
    #读取图片+数据处理                    
    def read_img(path):
        #os.listdir(path) 返回path指定的文件夹包含的文件或文件夹的名字的列表
        #os.path.isdir(path)判断path是否是目录
        #b = [x+x for x in list1 if x+x<15 ]  列表生成式,循环list1,当if为真时,将x+x加入列表b
        cate=[path+x for x in os.listdir(path) if os.path.isdir(path+x)]
        imgs=[]
        
        for idx,folder in enumerate(cate):
            #glob.glob(s+'*.py') 从目录通配符搜索中生成文件列表 
            for im in glob.glob(folder+'/*.jpg'):
                #输出读取的图片的名称  
                print('reading the images:%s'%(im))
                #io.imread(im)读取单张RGB图片 skimage.io.imread(fname,as_grey=True)读取单张灰度图片
                #读取的图片 
                img=io.imread(im)
                #skimage.transform.resize(image, output_shape)改变图片的尺寸
                img=transform.resize(img,(w,h))
                #将读取的图片数据加载到imgs[]列表中
                imgs.append(img)
                #将图片的label加载到labels[]中,与上方的imgs索引对应
               # labels.append(idx)
       #将读取的图片和labels信息,转化为numpy结构的ndarr(N维数组对象(矩阵))数据信息
        return np.asarray(imgs,np.float32)
     #调用读取图片的函数,得到图片和labels的数据集   
    data=read_img(path)
    with tf.Session() as sess:
         
         saver = tf.train.import_meta_graph('E:/data/flower/model/fc_model.ckpt-8.meta')
         saver.restore(sess,tf.train.latest_checkpoint('E:/data/flower/model/'))
        # sess:表示当前会话,之前保存的结果将被加载入这个会话
        #设置每次预测的个数
         graph = tf.get_default_graph()
         x = graph.get_tensor_by_name("x:0")
         feed_dict = {x:data}
     
         logits = graph.get_tensor_by_name("logits_eval:0")#eval功能等同于sess(run)
    
         classification_result = sess.run(logits,feed_dict)
    
        #打印出预测矩阵
         print(classification_result)
        #打印出预测矩阵每一行最大值的索引
         print(tf.argmax(classification_result,1).eval())
        #根据索引通过字典对应花的分
         output = []
         output = tf.argmax(classification_result,1).eval()
         for i in range(len(output)):
             print("第",i+1,"朵花预测:"+flower_dict[output[i]])

    参考网址:http://www.bingbig.com/243.html

    展开全文
  • python学习(18)--图片分类

    万次阅读 2017-06-19 10:25:37
    图片分类学习动机.在这一节中我们会引入图片分类为题。这也是从一个合适的集合中分配给图片一个标记的任务。这是计算机视觉的核心问题之一。鉴于它的简单性,有一大批实用应用。更多的是,我们可以在以后的章节中...

    图片分类

    学习动机.

    在这一节中我们会引入图片分类为题。这也是从一个合适的集合中分配给图片一个标记的任务。这是计算机视觉的核心问题之一。鉴于它的简单性,有一大批实用应用。更多的是,我们可以在以后的章节中看到,一些看似分离的计算机视觉任务(例如类别监测,分割)都可以归为图片分类。

    举例

    例如,如下的图片模型可以提取一个图片并给他四种label的可能性(猫,狗,帽子,杯子)。在图片中可以看到,一个图片在计算机中被识别为一个大型的三位数组。例如。猫有248像素宽,400像素高,并且有三种颜色(红,绿,蓝或者有short类型RGB)。因此,图片包含248*400*3个数字,一共297600个数字。每个数字都是一个从0到255整型数据。我们的任务就是把这上百万的数据或称一个标记,例如“猫”。
    例如:猫
    这个任务在图片分类中就是预测一个单独的标记(或者一个标记集合的分布概率来确保我们的置信度)给图片。图片是一个三位的整型数组。每个整型数据都是从0到255,大小是宽*高*3。这三个表达了三种颜色,红绿蓝。

    挑战

    由于这个识别一个视觉概念的任务(例如猫)对于人们来说是没有那么重要。所以,考虑这个方面在计算机视觉算法中是值得的。当我们展示了一系列挑战的时候,记住图片的3维初略表现形式都由很明亮的值:

    • 角度变量Viewpoint variation。一个单独的类型实例可以被摄像机从多种角度展示
    • 规模变量Scale variation。可视化类型经常表现出规模的变化(规模在真实世界中,不仅仅在于图片中的内容)。
    • 变型Deformation。有许多有用的实物并没有网格式的结构并且可能变成其他极端形式。
    • 遮挡Occlusion。 物体有可能被堵住。有时候只展现一部分。
    • 光照条件Illumination conditions。光照的影响在像素级别非常巨大。
    • 背景影响Background clutter。 实物可能混入到环境中去,让我们很难发现和识别。
    • 类内变化Intra-class variation。 类别经常是非常广义的,例如椅子。这里有很多不同类型的物体,每个都有他们自己的展示。
      一个好的图片分类模型必须是对各种变量交叉是不变的,同时保留对类内保持敏感度。
      挑战

    * 数据驱动方法*

    我们怎么样才可以设计一个算法来区分图片到不同的类别呢?不像许多算法例如排序,写一个识别猫的算法是非常不明显的。因此,不同于直接试图明确图片在其中一个类别中,我们实用的方法是取那么不像不是这个类别的:我们准备提供给计算机许多类别的实例并且开发学习算法来观察这些实例并且学习每个类别的可视化展示。这个方法被叫做数据驱动方法。由于它依赖于大量的标记好的图片数据。这里有一个实例:
    这里写图片描述
    一个训练分辨四种类型的例子。实际上我们应该每种类型有成千上万种图片。

    图片分类处理器

    我们看到图片分类的任务就是把一个展示图片的像素数组并且分配一个标记给他。我们完善的处理器可以被描述为如下算法:

    • 输入:我们的输入包含N个图片,每个都标记有K中不同类别。我们可以把数据。我们把这种数据叫做训练集。
    • 学习 : 我们的任务就是用训练集取学习每一个类到底是什么样的。我们把这种方法叫做训练一个分类器或者学习一个模型。
    • 评估 : 最终,我们会通过他们预测新的图片的标记的准确性评估分类器的质量。我们也将对比这些图片的真实标签和预测标签。我们也希望预测是可以赶上真实标签的(我们叫地面实况)。
    展开全文
  • 图片分类-python

    千次阅读 热门讨论 2018-06-22 16:57:53
    目的:做一个简易的图片分类。 使用到的算法:hog、surf+svm 图片集:cifar-10、cifar-100、stl-10、自制图片集 分类完整代码链接 使用说明: 1.cifar-10、cifar-100和stl-10直接解压 2.自制图片集文件夹结构...

    目的:做一个简易的图片分类。
    使用到的算法:hog、surf+svm
    图片集cifar-10、cifar-100stl-10、自制图片集
    这里写图片描述
    分类完整代码链接

    使用说明
    1.cifar-10、cifar-100和stl-10直接解压
    2.自制图片集文件夹结构:
    ├─homemade
    │ ├─标签1
    │ ├─标签2
    │ ├─标签3
    │ ├─标签4
    │ ├─标签5
    │ └─标签6
    每个“标签N”里面是存储的属于该标签的图片,图片名为“标签名+数字”
    自制图片全是百度爬取自己筛选的
    3.依赖库
    文件说明
    categoriesGUI.py:gui界面
    categoriesGUI.spec:用于Pyinstaller生成exe
    config.py:读取配置参数
    modelTrain.py:模型训练
    picCategories.py:图片集分类,利用的是modelTrain.py训练保存的模型
    config/config.cfg:配置参数,部分参数和python中算法的参数相对应

    结果总结
    1.hog是利用梯度变换提取特征,并且缺少旋转和尺度不变性。
    2.surf是SIFT角点检测算法的改进版,速度提升比较大。
    3.相同图片集,对比hog+LinearSVC和surf+LinearSVC,hog效果要好一些(这里不知道为什么)
    4.不同图片集,各类别中的图片数量越多,hog识别效果越好
    5.还可以优化部分分别是:
    a.surf读取图片改为读取每一张图片就进行surf特征提取,在释放掉图片内存,这样可以减小内存。
    b.模型训练采取的是LinearSVC,采取其他的效果应该要好些。
    c.在surf+LinearSVC中使用的是MiniBatchKMeans,速度比kmeans快,效果差距不大
    d.自己调参数,这里可以提高一些识别率。
    6.surf由于提取特征大小不同,所以采用了词袋的方法。

    展开全文
  • 干货——图像分类(上)

    万次阅读 2018-08-29 16:44:33
    这是译自斯坦福CS231n课程笔记image classification notes,由课程教师Andrej Karpathy授权进行翻译。本篇教程由杜客翻译完成。非常...
        

    这是译自斯坦福CS231n课程笔记image classification notes,由课程教师Andrej Karpathy授权进行翻译。本篇教程由杜客翻译完成。非常感谢那些无偿奉献的大师,在此代表所有爱好学习者向您们致敬,谢谢!


    这是斯坦福大学的课程,希望对即将入门DL的您打下基础,还是给已经处在DL届的您们巩固,都希望您们对基础知识有深入的理解。

    随便分享CS231n的网址,有兴趣的朋友可以进一步去了解:http://cs231n.github.io/

    图像分类

    目标这一节我们将介绍图像分类问题。

    图像分类,顾名思义,是一个输入图像,输出对该图像内容分类的描述的问题。它是计算机视觉的核心,实际应用广泛。图像分类的传统方法是特征描述及检测,这类传统方法可能对于一些简单的图像分类是有效的,但由于实际情况非常复杂,传统的分类方法不堪重负。现在,我们不再试图用代码来描述每一个图像类别,决定转而使用机器学习的方法处理图像分类问题。主要任务是给定一个输入图片,将其指派到一个已知的混合类别中的某一个标签。 

    例子在下图中,一个图像分类模型将一个图片分配给四个类别(cat,dog,hat,mug)标签的概率。

    如图所示,图片被表示成一个大的3维数字矩阵。在下面例子中,图像分类的最终目标就是转换这个数字矩阵到一个单独的标签,例如“Cat”。 图片分类的任务是对于一个给定的图片,预测其的类别标签。 

    ——————————————————

    640?wx_fmt=png

    ——————————————————

    困难和挑战对于人来说,识别猫特别简单,首先我们之前就大量接触这类图像,对其对特的特征有深入的认识,所以人类识别是简单的任务,但是对于,计算机视觉算法,那就那难于上青天。

    我们在下面列举了至今计算机视觉领域遇到的困难,也是现在亟待需解决的问题:

    • 刚体&非刚体的变化:不同类型其变化都不一样;

    • 多视角:收集同一个物体图像,获取的角度是多变的;

    • 尺度:在现实生活中,很多物体的尺度都是千变万化;

    • 遮挡:目标物体可能被挡住。有时候只有物体的一小部分是可见的;

    • 光照条件:在像素层面上,光照的影响非常大;

    • 类内差异:一类物体的个体之间有许多不同的对象,每个都有自己的外形。

    ——————————————————

    640?wx_fmt=jpeg——————————————————

    数据驱动方法如何写一个图像分类的算法呢?怎么写一个从图像中认出猫的算法?

    因此,我们采取的方法和教小孩儿看图识物类似:给模型很多图像数据,让其不断去学习,学习到每个类的特征。这就是数据驱动方法

    既然第一步需要将已经做好分类标注的图片作为训练集,下面就看看训练数据集长什么样?如下图:

    ——————————————————

    640?wx_fmt=jpeg

    一共有4个类别的训练集。在实际中,可能有成千上万类别的物体,每个类别都会有百万的图像。

    ——————————————————

    图像分类流程在课程视频中已经学习过,图像分类就是输入一个元素为像素值的数组,然后给它分配一个分类标签。完整流程如下:

    • 输入:输入是包含N个图像的集合,每个图像的标签是K种分类标签中的一种。这个集合称为训练集。

    • 学习:这一步的任务是使用训练集来学习每个类到底长什么样。一般该步骤叫做训练分类器或者学习一个模型

    • 评价:让分类器来预测它未曾见过的图像的分类标签,并以此来评价分类器的质量。我们会把分类器预测的标签和图像真正的分类标签对比。毫无疑问,分类器预测的分类标签和图像真正的分类标签如果一致,那就是好事,这样的情况越多越好。

    Nearest Neighbor分类器

    作为课程介绍的第一个方法,我们来实现一个Nearest Neighbor分类器。虽然这个分类器和卷积神经网络没有任何关系,实际中也极少使用,但通过实现它,可以让读者对于解决图像分类问题的方法有个基本的认识。

    图像分类数据集:CIFAR-10一个非常流行的图像分类数据集是CIFAR-10。这个数据集包含了60000张32X32的小图像。每张图像都有10种分类标签中的一种。这60000张图像被分为包含50000张图像的训练集和包含10000张图像的测试集。在下图中你可以看见10个类的10张随机图片。

    ——————————————————

    640?wx_fmt=jpeg左边:从CIFAR-10数据库来的样本图像。右边:第一列是测试图像,然后第一列的每个测试图像右边是使用Nearest Neighbor算法,根据像素差异,从训练集中选出的10张最类似的图片。

    ——————————————————

    假设现在我们有CIFAR-10的50000张图片(每种分类5000张)作为训练集,我们希望将余下的10000作为测试集并给他们打上标签。Nearest Neighbor算法将会拿着测试图片和训练集中每一张图片去比较,然后将它认为最相似的那个训练集图片的标签赋给这张测试图片。上面右边的图片就展示了这样的结果。请注意上面10个分类中,只有3个是准确的。比如第8行中,马头被分类为一个红色的跑车,原因在于红色跑车的黑色背景非常强烈,所以这匹马就被错误分类为跑车了。

    那么具体如何比较两张图片呢?在本例中,就是比较32x32x3的像素块。最简单的方法就是逐个像素比较,最后将差异值全部加起来。换句话说,就是将两张图片先转化为两个向量640?wx_fmt=png640?wx_fmt=png,然后计算他们的L1距离:

    640?wx_fmt=png

    这里的求和是针对所有的像素。下面是整个比较流程的图例:

    ——————————————————

    640?wx_fmt=png

    以图片中的一个颜色通道为例来进行说明。两张图片使用L1距离来进行比较。逐个像素求差值,然后将所有差值加起来得到一个数值。如果两张图片一模一样,那么L1距离为0,但是如果两张图片很是不同,那L1值将会非常大。

    ——————————————————

    下面,让我们看看如何用代码来实现这个分类器。首先,我们将CIFAR-10的数据加载到内存中,并分成4个数组:训练数据和标签,测试数据和标签。在下面的代码中,Xtr(大小是50000x32x32x3)存有训练集中所有的图像,Ytr是对应的长度为50000的1维数组,存有图像对应的分类标签(从0到9):

    Xtr, Ytr, Xte, Yte = load_CIFAR10('data/cifar10/') # a magic function we provide# flatten out all images to be one-dimensionalXtr_rows = Xtr.reshape(Xtr.shape[0], 32 * 32 * 3) # Xtr_rows becomes 50000 x 3072Xte_rows = Xte.reshape(Xte.shape[0], 32 * 32 * 3) # Xte_rows becomes 10000 x 3072

    现在我们得到所有的图像数据,并且把他们拉长成为行向量了。接下来展示如何训练并评价一个分类器:

    nn = NearestNeighbor() # create a Nearest Neighbor classifier classnn.train(Xtr_rows, Ytr) # train the classifier on the training images and labelsYte_predict = nn.predict(Xte_rows) # predict labels on the test images# and now print the classification accuracy, which is the average number# of examples that are correctly predicted (i.e. label matches)print 'accuracy: %f' % ( np.mean(Yte_predict == Yte) )

    作为评价标准,我们常常使用准确率,它描述了我们预测正确的得分。请注意以后我们实现的所有分类器都需要有这个API:train(X, y)函数。该函数使用训练集的数据和标签来进行训练。从其内部来看,类应该实现一些关于标签和标签如何被预测的模型。这里还有个predict(X)函数,它的作用是预测输入的新数据的分类标签。现在还没介绍分类器的实现,下面就是使用L1距离的Nearest Neighbor分类器的实现套路:

    import numpy as npclass NearestNeighbor(object):
      def __init__(self):
        pass
    
      def train(self, X, y):
        """ X is N x D where each row is an example. Y is 1-dimension of size N """
        # the nearest neighbor classifier simply remembers all the training data
        self.Xtr = X
        self.ytr = y
    
      def predict(self, X):
        """ X is N x D where each row is an example we wish to predict label for """
        num_test = X.shape[0]
        # lets make sure that the output type matches the input type
        Ypred = np.zeros(num_test, dtype = self.ytr.dtype)
    
        # loop over all test rows
        for i in xrange(num_test):
          # find the nearest training image to the i'th test image
          # using the L1 distance (sum of absolute value differences)
          distances = np.sum(np.abs(self.Xtr - X[i,:]), axis = 1)
          min_index = np.argmin(distances) # get the index with smallest distance
          Ypred[i] = self.ytr[min_index] # predict the label of the nearest example
    
        return Ypred

    如果你用这段代码跑CIFAR-10,你会发现准确率能达到38.6%。这比随机猜测的10%要好,但是比人类识别的水平(据研究推测是94%)和卷积神经网络能达到的95%还是差多了。点击查看基于CIFAR-10数据的Kaggle算法竞赛排行榜

    距离选择计算向量间的距离有很多种方法,另一个常用的方法是L2距离,从几何学的角度,可以理解为它在计算两个向量间的欧式距离。L2距离的公式如下:

    640?wx_fmt=png

    换句话说,我们依旧是在计算像素间的差值,只是先求其平方,然后把这些平方全部加起来,最后对这个和开方。在Numpy中,我们只需要替换上面代码中的1行代码就行:

    distances = np.sqrt(np.sum(np.square(self.Xtr - X[i,:]), axis = 1))

    注意在这里使用了np.sqrt,但是在实际中可能不用。因为求平方根函数是一个单调函数,它对不同距离的绝对值求平方根虽然改变了数值大小,但依然保持了不同距离大小的顺序。所以用不用它,都能够对像素差异的大小进行正确比较。如果你在CIFAR-10上面跑这个模型,正确率是35.4%,比刚才低了一点。

    L1和L2比较。比较这两个度量方式是挺有意思的。在面对两个向量之间的差异时,L2比L1更加不能容忍这些差异。也就是说,相对于1个巨大的差异,L2距离更倾向于接受多个中等程度的差异。L1和L2都是在p-norm常用的特殊形式。

    k-Nearest Neighbor分类器

    你可能注意到了,为什么只用最相似的1张图片的标签来作为测试图像的标签呢?这不是很奇怪吗!是的,使用k-Nearest Neighbor分类器就能做得更好。它的思想很简单:与其只找最相近的那1个图片的标签,我们找最相似的k个图片的标签,然后让他们针对测试图片进行投票,最后把票数最高的标签作为对测试图片的预测。所以当k=1的时候,k-Nearest Neighbor分类器就是Nearest Neighbor分类器。从直观感受上就可以看到,更高的k值可以让分类的效果更平滑,使得分类器对于异常值更有抵抗力。

    ——————————————————

    640?wx_fmt=jpeg

    上面示例展示了Nearest Neighbor分类器和5-Nearest Neighbor分类器的区别。例子使用了2维的点来表示,分成3类(红、蓝和绿)。不同颜色区域代表的是使用L2距离的分类器的决策边界。白色的区域是分类模糊的例子(即图像与两个以上的分类标签绑定)。需要注意的是,在NN分类器中,异常的数据点(比如:在蓝色区域中的绿点)制造出一个不正确预测的孤岛。5-NN分类器将这些不规则都平滑了,使得它针对测试数据的泛化(generalization能力更好(例子中未展示)。注意,5-NN中也存在一些灰色区域,这些区域是因为近邻标签的最高票数相同导致的(比如:2个邻居是红色,2个邻居是蓝色,还有1个是绿色)。

    ——————————————————

    在实际中,大多使用k-NN分类器。但是k值如何确定呢?接下来就讨论这个问题。

    图像分类笔记(上)完。

    展开全文
  • 深度学习之图像分类

    千次阅读 2019-05-23 11:49:26
    第一篇CSDN文章,写的不好,还请各位大佬指正。万事开头难,千里之行始于足下! ...示例:我们假定一个可能的类别集categories = {dog, cat, eagle},之后我们提供一张图片(图1)给分类系统:...
  • 图像分类篇系列-1

    千次阅读 2020-10-22 15:23:56
    ● 图像分类的基本流程 ● 自定义CNN模型进行分类,准确率0.84 ● VGG提取特征,并进行分类,准确率0.908 ● 模型堆叠,并进行分类,准确率0.918
  • 图片分类

    2018-05-04 07:42:13
    import os import stat import time import exifread MY_DATE_FORMAT = '%Y%m%d_%H%M%S' SUFFIX_FILTER = ['.jpg', '.png', '.mpg', '.mp4', '.thm', '.bmp', '.jpeg', '.avi', '.mov'] DELETE_FILES = ['thumbs.d...
  • 干货——图像分类(下)

    千次阅读 2018-08-29 16:44:32
    用于超参数调优的验证集首先,来介绍参数和超参数的基本知识。在机器学习或者深度学习领域,参数和超参数是一个常见的问题,个人根据经验给出了一个很狭隘的区分这两种参数的方法。参...
  • CNN图片分类

    万次阅读 2018-08-21 17:13:08
    最近在阅读一些AI项目,写入markdown,持续更新,算是之后也能回想起...image classify(图片分类) CNN classify dogs and cats(猫狗二分类) Tutorial(教程):https://developers.google.com/machine-learning/pra...
  • opencv中的SVM图像分类(二)

    万次阅读 多人点赞 2015-07-30 08:44:57
    原创作品 转载请注明出http://blog.csdn.net/always2015/article/details/47107129
  • 数据说明 该数据集是图片数据,分为训练集85%(Train)和测试集15%(Test)。其中O代表Organic(有机垃圾),R代表Recycle(可回收) 数据来源 数据来源:百度云分享 ...
  • K-means对图像进行分类

    千次阅读 2017-04-26 21:15:27
    matlab利用K-means识别道路区域
  • Crawler/ML:爬虫技术(基于urllib.request库从网页获取图片)+HierarchicalClustering层次聚类算法,实现自动从网页获取图片然后根据图片色调自动分类 目录 一、爬虫下载图片 二、ML智能分类 网上教程太...
  • GIS学习笔记之Arcgis监督分类

    万次阅读 2015-10-25 11:26:14
    1、数据图片需要时TIFF格式的。 2、添加图片,先选择”空间分析工具“,多元分析,Iso聚类,设置时要填好保存路径并复制保存路径,最大分类的填写。 3、再选择”空间分析工具“,多元分析,最大似然法分类,进行...
  • 在单标签图像分类任务中,一般使用top1 accuracy 或者 top5 accuracy 衡量分类的准确性。而多标签图像分类任务的评价方法一般采用的是和信息检索中类似的方法——mAP(mean average precision)。以下是mAP的计算方法...
  • SVM+HOG对图像进行分类(MATLAB实现)

    万次阅读 多人点赞 2017-10-22 10:58:25
    主要完成对多种类型的图像进行分类,1、对图像HOG特征进行提取。2、SVM对提取的特征进行训练。3、预测未知图像。
  • 目标检测

    万次阅读 2012-10-18 20:39:57
    在目标检测方法中,首先利用样本(大约几百幅样本图片)的Haar特征进行分类器训练,得到一个联级的 boosted分类器。训练样本分为正例样本和反例样本,其中正例样本是指待检测目标样本,反例样本指其他 意图片,...
  • 【机器学习】ML分类问题

    万次阅读 2020-01-13 09:38:07
    分类问题中,你要预测的变量 yyy 是离散的值,我们将学习一种叫做逻辑回归 (Logistic Regression) 的算法,这是目前最流行使用最广泛的一种学习算法。 在分类问题中,我们尝试预测的是结果是否属于某一个类(例如...
  • 基于支持向量机的图像分类(下篇:MATLAB实现)

    万次阅读 多人点赞 2020-04-13 12:31:05
    摘要:本文通过图文详细介绍如何利用支持向量机对图像进行分类,经过上篇文章对原理的介绍,这里介绍利用MATLAB编程实现。后续章节将介绍的主要部分有: 图片数据集整理 特征提取 SVM训练与测试 分类结果...
  • 级联分类

    万次阅读 2016-11-22 21:14:25
    1.检测体系:是以现实中很大一副图片作为输入,然后对图片中进行多区域,多尺度的检测,所谓多区域,是要对图片划分多块,对每个块进行检测,由于训练的时候一般图片都是20*20左右的小图片,所以对于大的人脸,还...
1 2 3 4 5 ... 20
收藏数 274,704
精华内容 109,881
关键字:

图片分类