精华内容
下载资源
问答
  • 常规的基于CNN的图像分类网络如Lenet、Alexnet、VGGnet等都是单分类模型,本文记录在ubuntu16.04下如何对传统的单分类模型进行调整,实现多标签分类的效果,这里主要指的是对固定长度字符串的识别,相同原理可用于...

    常规的基于CNN的图像分类网络如Lenet、Alexnet、VGGnet等都是单分类模型,本文记录在ubuntu16.04下如何对传统的单分类模型进行调整,实现多标签分类的效果,这里主要指的是对固定长度字符串的识别,相同原理可用于验证码识别和车牌识别。

    声明:本文代码主要来自于以下两篇博文:

    下面整理了使用caffe完成多标签分类(multi-label classification)模型训练测试的整个流程,主要分为4个部分:

    如何制作多标签分类数据集;

    修改caffe源代码,实现多标签数据集的转换和读取;

    修改分类模型Alexnet,实现多标签分类;

    模型的训练和测试。

    1.如何制作多标签分类数据集

    制作的数据集图片类似于:

    这里的每张图片中包含4个字符(0-9或者A-Z),通过对代码的简单修改,可以扩展成任意长度。

    首先建立一个名为multi-label-classification的文件夹,下面的子目录/子文件如下:

    其中蓝色的是文件夹,其他颜色的是文件。

    生成多标签字符图片的思路大概是:

    首先确定字符串的长度,即想要生成包含几个标签的图片;

    根据字符串的长度,确定图像的尺寸;比如我生成4个字符的图片,再考虑单个字符和长宽比,字符间的间隙,以及字体的大小,确定4字符图像的长和宽是90x30;

    需要找到一种.ttf格式的字体,这根据实际情况选择合适的字体;

    接下来,需要确定图像要用什么样的背景;比如我随便找了十几种颜色的背景图片(放在../background/文件夹下),部分显示如下,每张都是90x30大小。

    最后考虑需要对字符串图像做什么处理,比如随机旋转,畸变处理,加入噪声,模糊等等,用于增强模型的泛化能力。

    下面是gen_character.py的代码:

    #coding=utf-8

    import PIL

    from PIL import ImageFont

    from PIL import Image

    from PIL import ImageDraw

    import cv2

    import numpy as np

    import os

    from math import *

    chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A","B", "C", "D", "E", "F", "G", "H", "I",

    "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X","Y", "Z"];

    # 引入畸变,将使字符随机地向左或者向右倾斜一个随机的角度(4-10个像素值)

    def distortionRandom(img):

    w = img.shape[1]

    h = img.shape[0]

    pts1 = np.float32([[0, 0], [0, h], [w, 0], [w, h]])

    pos_or_neg = np.random.random_integers(0,1)

    distortion_value = np.random.random_integers(4,10)

    if(pos_or_neg==0):

    pts2 = np.float32([[0, 0], [distortion_value, h], [w-distortion_value, 0], [w, h]])

    else:

    pts2 = np.float32([[distortion_value, 0], [0, h], [w, 0], [w-distortion_value, h]])

    M = cv2.getPerspectiveTransform(pts1, pts2)

    dst = cv2.warpPerspective(img, M, (w,h))

    return dst

    # 在背景图像块中写入一个字符

    def GenCh(f,val):

    img=Image.new("RGB", (16,28),(255,255,255))

    draw = ImageDraw.Draw(img)

    draw.text((2, 0),val.decode('utf-8'),(0,0,0),font=f, align="center")

    A = np.array(img)

    A = cv2.resize(A, (22,28))

    return A

    # 定义一个类GenCharacter,用于生成固定长度多标签图片

    class GenCharacter:

    def __init__(self,font):

    # 初始化所用的字符字体

    self.fontE = ImageFont.truetype(font,28,0)

    # 初始化多标签图片的大小为90x30

    self.img=np.array(Image.new("RGB", (90,30),(255,255,255)))

    # 初始化标签图片所用的背景,这里在./background/文件夹中准备了十几张90x30的不同背景

    # 全部读取到一个list中,生成多标签图片时随机选择某一个背景

    self.bgs = []

    for file in os.listdir("./background/"):

    bg = cv2.resize(cv2.imread("./background/"+file),(90,30))

    self.bgs.append(bg)

    # 将长度为4的字符串写入90x30的图片中

    def draw(self,val):

    offset = 2

    for i in range(4):

    base = offset + i*22

    self.img[0:28, base:base+22]= GenCh(self.fontE,val[i])

    return self.img

    # 生成一张带随机背景的随机字符串

    def generate(self,text):

    if len(text) == 4:

    fg = self.draw(text.decode(encoding="utf-8"))

    fg = cv2.bitwise_not(fg)

    k = np.random.random_integers(0,len(self.bgs)-1)

    com = cv2.bitwise_or(fg,self.bgs[k])

    com = distortionRandom(com)

    com = cv2.bitwise_or(com,self.bgs[k])

    return com

    # 随机生成长度为4的字符串

    def genCharacterString(self):

    CharacterStr = ""

    box = [0,0,0,0]

    for unit,cpos in zip(box,xrange(len(box))):

    CharacterStr += chars[np.random.random_integers(0,35)]

    return CharacterStr

    # 生成指定批次大小的多标签图片,病保存到指定文件夹

    def genBatch(self, batchSize,outputPath):

    if (not os.path.exists(outputPath)):

    os.mkdir(outputPath)

    for i in xrange(batchSize):

    CharacterStr = G.genCharacterString()

    img = G.generate(CharacterStr)

    filename = os.path.join(outputPath, str(i).zfill(6) + '.' + CharacterStr + ".jpg")

    cv2.imwrite(filename, img)

    G = GenCharacter('./font/platechar.ttf')

    G.genBatch(30000,"./data/train")

    G.genBatch(10000,"./data/val")

    直接在/multi-label-classification/文件夹下打开bash,执行

    python ./gen_character.py

    生成30000张训练集图片和10000张验证集图片。

    如何生成train.txt和val.txt文本文件?

    使用过caffe分类模型的同学应该清楚,除了图片文件之外,还需要保存有图片名和对应gt-label的train.txt和val.txt文本文件,写了一个简单的python脚本实现:

    create_train_txt.py:

    #coding=utf-8

    #根据图像名的特点如000001.5GSB.jpg,生成gt-label文件

    import os

    train_src_path = "data/train/"

    train_dst_file = "data/train.txt"

    if __name__ == '__main__':

    train_file = open(train_dst_file, 'w')

    k=0

    for file in os.listdir(train_src_path):

    lines = file

    strs = file.split('.')

    for i in range(4):

    cha = strs[1][i]

    # '0'-'9'对应的ASCII码值是48-57,'A'-'Z'对应的ASCII码值是65-90,

    # 这里为了方便,将'0'-'9'减去48映射到0-9;将'A'-'Z'减去55映射到10-35,

    if ord(cha)>=65:

    num = ord(cha)-55

    else:

    num = ord(cha)-48

    lines+=' '+str(num)

    lines+='\n'

    train_file.writelines(lines)

    k+=1

    train_file.close()

    print('there are %d images in total' % int(k))

    print('done')

    create_train_txt.py文件放在/multi-label-classification/文件夹下,在/multi-label-classification/文件夹下打开bash,执行

    python ./create_train_txt.py

    将在/multi-label-classification/data/下面生成train.txt文件。

    将上面代码中路径名的train改成val,相同的方法,生成val.txt文件。

    比如train.txt文件的部分内容如下:

    接下来,需要将多标签的训练集和验证集转换成LMDB格式,这一步需要对/caffe/tools/convert_imageset.cpp文件做修改,所以这一步留到后面进行。

    2.修改caffe源代码,实现多标签数据集的转换和读取

    下载的caffe源码中有一个/caffe/tools/convert_imageset.cpp文件,使用它可以将图像图像格式的数据集转换成LMDB格式,但它只能处理单标签的数据集,为了处理多标签数据集,需要修改convert_imageset.cpp文件;而convert_imageset.cpp的实现涉及到io.hpp和io.cpp中的函数,于是要修改io.hpp和io.cpp。

    同样,caffe的Data层也只能读取单标签的数据集,为了处理多标签数据集,需要修改data_layer.cpp文件。

    另外,需要在caffe.proto中添加一个参数。

    总的来说,需要修改以下几个文件:

    /caffe/tools/convert_imageset.cpp

    /caffe/include/caffe/util/io.hpp

    /caffe/src/caffe/util/io.cpp

    /caffe/src/caffe/proto/caffe.proto

    /caffe/src/caffe/layers/data_layer.cpp

    原来的代码用/* ... */注释掉,新增的代码用// ...... //包围起来

    修改/caffe/tools/convert_imageset.cpp,在约74行处:

    /*

    std::ifstream infile(argv[2]);

    std::vector<:pair int> > lines;

    std::string line;

    size_t pos;

    int label;

    while (std::getline(infile, line)) {

    pos = line.find_last_of(' ');

    label = atoi(line.substr(pos + 1).c_str());

    lines.push_back(std::make_pair(line.substr(0, pos), label));

    }

    */

    std::ifstream infile(argv[2]);

    std::vector<:pair vector> > > lines;

    std::string filename;

    vector labels(4);

    while (infile >> filename >> labels[0] >> labels[1] >> labels[2] >> labels[3]){

    lines.push_back(std::make_pair(filename, labels));

    }

    ///

    修改/caffe/include/caffe/util/io.hpp。

    在其中新加入/// ..... ///内的两个成员函数声明,不删除原来的任何代码,下面的前两个函数声明是原来文件中就有的,可以看到,原来代码中的label参数是int类型,只能处理单标签字符;新增的两个成员函数就是参考上面两个函数,将const int label参数改成了std::vector labels,以接受多标签字符。

    bool ReadImageToDatum(const string& filename, const int label,

    const int height, const int width, const bool is_color,

    const std::string & encoding, Datum* datum);

    bool ReadFileToDatum(const string& filename, const int label, Datum* datum);

    //

    bool ReadImageToDatum(const string& filename, std::vector labels,

    const int height, const int width, const bool is_color,

    const std::string & encoding, Datum* datum);

    bool ReadFileLabelsToDatum(const string& filename, std::vector labels,

    Datum* datum);

    ///

    修改/caffe/src/caffe/util/io.cpp。

    在ReadImageToDatum()函数实现下面添加下面函数实现,约143行处:

    //

    bool ReadImageToDatum(const string& filename, std::vector labels,

    const int height, const int width, const bool is_color,

    const std::string & encoding, Datum* datum)

    {

    std::cout << filename << " " << labels[0] << " " << labels[1] << " " << labels[2] << " " << labels[3] << std::endl;

    cv::Mat cv_img = ReadImageToCVMat(filename, height, width, is_color);

    if (cv_img.data) {

    if (encoding.size()) {

    if ((cv_img.channels() == 3) == is_color && !height && !width &&

    matchExt(filename, encoding))

    //return ReadFileToDatum(filename, label, datum);

    return ReadFileLabelsToDatum(filename, labels, datum);//ReadFileToDatum -> ReadFileLabelsToDatum

    std::vector buf;

    cv::imencode("." + encoding, cv_img, buf);

    datum->set_data(std::string(reinterpret_cast(&buf[0]),

    buf.size()));

    //datum->set_label(label);

    datum->clear_labels();

    datum->add_labels(labels[0]);

    datum->add_labels(labels[1]);

    datum->add_labels(labels[2]);

    datum->add_labels(labels[3]);

    //

    datum->set_encoded(true);

    return true;

    }

    CVMatToDatum(cv_img, datum);

    //datum->set_label(label);

    datum->clear_labels();

    datum->add_labels(labels[0]);

    datum->add_labels(labels[1]);

    datum->add_labels(labels[2]);

    datum->add_labels(labels[3]);

    //

    return true;

    }

    else {

    return false;

    }

    }

    /

    在ReadFileToDatum()函数实现下面添加下面的函数实现,约209行处:

    //

    bool ReadFileLabelsToDatum(const string& filename, std::vector labels,

    Datum* datum)

    {

    std::streampos size;

    fstream file(filename.c_str(), ios::in | ios::binary | ios::ate);

    if (file.is_open()) {

    size = file.tellg();

    std::string buffer(size, ' ');

    file.seekg(0, ios::beg);

    file.read(&buffer[0], size);

    file.close();

    datum->set_data(buffer);

    //datum->set_label(label);

    datum->clear_labels();

    datum->add_labels(labels[0]);

    datum->add_labels(labels[1]);

    datum->add_labels(labels[2]);

    datum->add_labels(labels[3]);

    //

    datum->set_encoded(true);

    return true;

    }

    else {

    return false;

    }

    }

    ///

    修改/caffe/src/caffe/proto/caffe.proto。

    在下面的源代码中添加一行代码,即添加一个labels,是repeated类型的,以便接受多标签数据集。

    message Datum {

    optional int32 channels = 1;

    optional int32 height = 2;

    optional int32 width = 3;

    // the actual image data, in bytes

    optional bytes data = 4;

    optional int32 label = 5;

    // Optionally, the datum could also hold float data.

    repeated float float_data = 6;

    // If true data contains an encoded image that need to be decoded

    optional bool encoded = 7 [default = false];

    //

    repeated float labels = 8;

    //

    }

    修改/caffe/src/caffe/layers/data_layer.cpp。

    约49行处:

    // label

    /*

    if (this->output_labels_) {

    vector label_shape(1, batch_size);

    top[1]->Reshape(label_shape);

    for (int i = 0; i < this->prefetch_.size(); ++i) {

    this->prefetch_[i]->label_.Reshape(label_shape);

    }

    }

    */

    /

    if (this->output_labels_){

    top[1]->Reshape(batch_size, 4, 1, 1);

    for (int i = 0; i < this->prefetch_.size(); ++i) {

    this->prefetch_[i]->label_.Reshape(batch_size, 4, 1, 1);

    }

    }

    //

    约128行处:

    // Copy label.

    /*

    if (this->output_labels_) {

    Dtype* top_label = batch->label_.mutable_cpu_data();

    top_label[item_id] = datum.label();

    }

    */

    ///

    if (this->output_labels_) {

    Dtype* top_label = batch->label_.mutable_cpu_data();

    for (int i = 0; i < 4; i++)

    top_label[item_id * 4 + i] = datum.labels(i);

    }

    ///

    修改完成,在caffe根目录执行:

    make clean

    make all -j8

    将修改后的caffe重新编译。

    将原始数据集转换成LMDB格式

    修改编译caffe后,就可以使用convert_imageset工具将原始数据集转换成LMDB格式了。

    执行脚本create_train_val_lmdb.sh进行完成数据集转换。

    create_train_val_lmdb.sh内容:

    echo "create train lmdb..."

    /home/ys/caffe/build/tools/convert_imageset \

    --resize_height=227 \

    --resize_width=227 \

    --backend="lmdb" \

    --shuffle \

    /home/ys/caffe/models/multi-label-classification/data/train/ \

    /home/ys/caffe/models/multi-label-classification/data/train.txt \

    /home/ys/caffe/models/multi-label-classification/data/train_lmdb

    echo "done"

    echo "create val lmdb..."

    /home/ys/caffe/build/tools/convert_imageset \

    --resize_height=227 \

    --resize_width=227 \

    --backend="lmdb" \

    --shuffle \

    /home/ys/caffe/models/multi-label-classification/data/val/ \

    /home/ys/caffe/models/multi-label-classification/data/val.txt \

    /home/ys/caffe/models/multi-label-classification/data/val_lmdb

    echo "done"

    文件路径根据自己的实际情况更改。

    3.修改分类模型Alexnet,实现多标签分类

    在/caffe/models/bvlc_alexnet/下有经典的Alexnet模型,其train_val.prototxt模型结构如下:

    alexnet.png

    将其修改后的train_val.prototxt模型结构如下:

    multi-label-alexnet.png

    Data层不改动,在Data层后面新增了一个Slice层,将Data层读取的多标签分解:

    layer {

    name: "slicers"

    type: "Slice"

    bottom: "label"

    top: "label_1"

    top: "label_2"

    top: "label_3"

    top: "label_4"

    slice_param {

    axis: 1

    slice_point: 1

    slice_point: 2

    slice_point: 3

    }

    }

    之后的Conv1层一直到fc6层的Dropout层都不变,然后将后面的fc7层以后的内容改成如下:

    layer {

    name: "fc7_1"

    type: "InnerProduct"

    bottom: "fc6"

    top: "fc7_1"

    param {

    lr_mult: 1

    decay_mult: 1

    }

    param {

    lr_mult: 2

    decay_mult: 0

    }

    inner_product_param {

    num_output: 4096

    weight_filler {

    type: "gaussian"

    std: 0.005

    }

    bias_filler {

    type: "constant"

    value: 0.1

    }

    }

    }

    layer {

    name: "relu7_1"

    type: "ReLU"

    bottom: "fc7_1"

    top: "fc7_1"

    }

    layer {

    name: "drop7_1"

    type: "Dropout"

    bottom: "fc7_1"

    top: "fc7_1"

    dropout_param {

    dropout_ratio: 0.5

    }

    }

    layer {

    name: "fc7_2"

    type: "InnerProduct"

    bottom: "fc6"

    top: "fc7_2"

    param {

    lr_mult: 1

    decay_mult: 1

    }

    param {

    lr_mult: 2

    decay_mult: 0

    }

    inner_product_param {

    num_output: 4096

    weight_filler {

    type: "gaussian"

    std: 0.005

    }

    bias_filler {

    type: "constant"

    value: 0.1

    }

    }

    }

    layer {

    name: "relu7_2"

    type: "ReLU"

    bottom: "fc7_2"

    top: "fc7_2"

    }

    layer {

    name: "drop7_2"

    type: "Dropout"

    bottom: "fc7_2"

    top: "fc7_2"

    dropout_param {

    dropout_ratio: 0.5

    }

    }

    layer {

    name: "fc7_3"

    type: "InnerProduct"

    bottom: "fc6"

    top: "fc7_3"

    param {

    lr_mult: 1

    decay_mult: 1

    }

    param {

    lr_mult: 2

    decay_mult: 0

    }

    inner_product_param {

    num_output: 4096

    weight_filler {

    type: "gaussian"

    std: 0.005

    }

    bias_filler {

    type: "constant"

    value: 0.1

    }

    }

    }

    layer {

    name: "relu7_3"

    type: "ReLU"

    bottom: "fc7_3"

    top: "fc7_3"

    }

    layer {

    name: "drop7_3"

    type: "Dropout"

    bottom: "fc7_3"

    top: "fc7_3"

    dropout_param {

    dropout_ratio: 0.5

    }

    }

    layer {

    name: "fc7_4"

    type: "InnerProduct"

    bottom: "fc6"

    top: "fc7_4"

    param {

    lr_mult: 1

    decay_mult: 1

    }

    param {

    lr_mult: 2

    decay_mult: 0

    }

    inner_product_param {

    num_output: 4096

    weight_filler {

    type: "gaussian"

    std: 0.005

    }

    bias_filler {

    type: "constant"

    value: 0.1

    }

    }

    }

    layer {

    name: "relu7_4"

    type: "ReLU"

    bottom: "fc7_4"

    top: "fc7_4"

    }

    layer {

    name: "drop7_4"

    type: "Dropout"

    bottom: "fc7_4"

    top: "fc7_4"

    dropout_param {

    dropout_ratio: 0.5

    }

    }

    layer {

    name: "fc8_1"

    type: "InnerProduct"

    bottom: "fc7_1"

    top: "fc8_1"

    param {

    lr_mult: 1

    decay_mult: 1

    }

    param {

    lr_mult: 2

    decay_mult: 0

    }

    inner_product_param {

    num_output: 36 #1000->36

    weight_filler {

    type: "gaussian"

    std: 0.01

    }

    bias_filler {

    type: "constant"

    value: 0

    }

    }

    }

    layer {

    name: "fc8_2"

    type: "InnerProduct"

    bottom: "fc7_2"

    top: "fc8_2"

    param {

    lr_mult: 1

    decay_mult: 1

    }

    param {

    lr_mult: 2

    decay_mult: 0

    }

    inner_product_param {

    num_output: 36 #1000->36

    weight_filler {

    type: "gaussian"

    std: 0.01

    }

    bias_filler {

    type: "constant"

    value: 0

    }

    }

    }

    layer {

    name: "fc8_3"

    type: "InnerProduct"

    bottom: "fc7_3"

    top: "fc8_3"

    param {

    lr_mult: 1

    decay_mult: 1

    }

    param {

    lr_mult: 2

    decay_mult: 0

    }

    inner_product_param {

    num_output: 36 #1000->36

    weight_filler {

    type: "gaussian"

    std: 0.01

    }

    bias_filler {

    type: "constant"

    value: 0

    }

    }

    }

    layer {

    name: "fc8_4"

    type: "InnerProduct"

    bottom: "fc7_4"

    top: "fc8_4"

    param {

    lr_mult: 1

    decay_mult: 1

    }

    param {

    lr_mult: 2

    decay_mult: 0

    }

    inner_product_param {

    num_output: 36 #1000->36

    weight_filler {

    type: "gaussian"

    std: 0.01

    }

    bias_filler {

    type: "constant"

    value: 0

    }

    }

    }

    layer {

    name: "accuracy_1"

    type: "Accuracy"

    bottom: "fc8_1"

    bottom: "label_1"

    top: "accuracy_1"

    include {

    phase: TEST

    }

    }

    layer {

    name: "accuracy_2"

    type: "Accuracy"

    bottom: "fc8_2"

    bottom: "label_2"

    top: "accuracy_2"

    include {

    phase: TEST

    }

    }

    layer {

    name: "accuracy_3"

    type: "Accuracy"

    bottom: "fc8_3"

    bottom: "label_3"

    top: "accuracy_3"

    include {

    phase: TEST

    }

    }

    layer {

    name: "accuracy_4"

    type: "Accuracy"

    bottom: "fc8_4"

    bottom: "label_4"

    top: "accuracy_4"

    include {

    phase: TEST

    }

    }

    layer {

    name: "loss_1"

    type: "SoftmaxWithLoss"

    bottom: "fc8_1"

    bottom: "label_1"

    top: "loss_1"

    loss_weight: 0.25

    }

    layer {

    name: "loss_2"

    type: "SoftmaxWithLoss"

    bottom: "fc8_2"

    bottom: "label_2"

    top: "loss_2"

    loss_weight: 0.25

    }

    layer {

    name: "loss_3"

    type: "SoftmaxWithLoss"

    bottom: "fc8_3"

    bottom: "label_3"

    top: "loss_3"

    loss_weight: 0.25

    }

    layer {

    name: "loss_4"

    type: "SoftmaxWithLoss"

    bottom: "fc8_4"

    bottom: "label_4"

    top: "loss_4"

    loss_weight: 0.25

    }

    也就是层之前的单个分支改成了4个分支。后面分别计算loss和accuracy。

    solver.protxt代码:

    net: "train_val.prototxt"

    test_iter: 100

    test_interval: 500

    base_lr: 0.01

    lr_policy: "step"

    gamma: 0.1

    stepsize: 6000

    display: 10

    max_iter: 10000

    momentum: 0.9

    weight_decay: 0.0005

    snapshot: 10000

    snapshot_prefix: "multi-label-classification"

    solver_mode: GPU

    模型修改完成。

    4.模型的训练和测试

    训练模型

    现在,/multi-label-classification/文件夹下有如下内容:

    在/multi-label-classification/文件夹下打开bash,执行

    /home/ys/caffe/build/tools/caffe train --solver solver.prototxt --gpu 0

    开始模型训练,训练好的模型文件保存在了/multi-label-classification/文件夹下。

    测试模型

    在/multi-label-classification/文件夹下打开bash,执行

    /home/ys/caffe/build/tools/caffe test \

    -model train_val.prototxt \

    -weights multi-label-classification_iter_10000.caffemodel \

    -iterations 100

    即可查看训练好的模型的测试效果。

    使用pycaffe可视化测试结果

    参考这篇文章,使用caffe的python接口测试单张图片。

    现在在/multi-label-classification/data/test_images/文件夹下有一张测试图片:

    使用python脚本pycaffe_test.py加载训练好的caffe模型对这张图片进行预测。

    pycaffe_test.py:

    #encoding:utf-8

    import numpy as np

    import sys,os

    import caffe

    import time

    caffe.set_device(0)

    caffe.set_mode_gpu()

    time_begin = time.time()

    # 设置当前的工作环境在caffe下, 根据自己实际情况更改

    caffe_root = '/home/ys/caffe/'

    # 我们也把caffe/python也添加到当前环境

    sys.path.insert(0, caffe_root + 'python')

    os.chdir(caffe_root)#更换工作目录

    # 设置网络结构

    net_file=caffe_root + 'models/multi-label-classification/deploy.prototxt'

    # 添加训练之后的参数

    caffe_model=caffe_root + 'models/multi-label-classification/multi-label-classification_iter_10000.caffemodel'

    # 均值文件

    mean_file=caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy'

    # 这里对任何一个程序都是通用的,就是处理图片

    # 把上面添加的两个变量都作为参数构造一个Net

    net = caffe.Net(net_file,caffe_model,caffe.TEST)

    # 得到data的形状,这里的图片是默认matplotlib底层加载的

    transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})

    # matplotlib加载的image是像素[0-1],图片的数据格式[h,w,c],RGB

    # caffe加载的图片需要的是[0-255]像素,数据格式[c,h,w],BGR,那么就需要转换

    # channel 放到前面

    transformer.set_transpose('data', (2,0,1))

    transformer.set_mean('data', np.load(mean_file).mean(1).mean(1))

    # 图片像素放大到[0-255]

    transformer.set_raw_scale('data', 255)

    # RGB-->BGR 转换

    transformer.set_channel_swap('data', (2,1,0))

    # 加载一张测试图片

    image_file = caffe_root+'models/multi-label-classification/data/test_images/000001.A86I.jpg'

    im=caffe.io.load_image(image_file)

    # 用上面的transformer.preprocess来处理刚刚加载图片

    net.blobs['data'].data[...] = transformer.preprocess('data',im)

    #注意,网络开始向前传播啦

    output = net.forward()

    # 最终的结果: 当前这个图片的属于哪个物体的概率(列表表示)

    output_prob1 = output['prob_1'][0]

    output_prob2 = output['prob_2'][0]

    output_prob3 = output['prob_3'][0]

    output_prob4 = output['prob_4'][0]

    # 找出最大的那个概率

    chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A","B", "C", "D", "E", "F", "G", "H", "I",

    "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X","Y", "Z"];

    print 'test image: ', image_file

    print 'the predicted result is:', chars[output_prob1.argmax()],' ',chars[output_prob2.argmax()],' ',chars[output_prob3.argmax()],' ',chars[output_prob4.argmax()]

    print 'time used: ', round(time.time()-time_begin, 4), 's'

    在/multi-label-classification/文件夹下打开bash,执行

    python ./pycaffe_test.py

    运行结果:

    本文用到的代码在这里。

    展开全文
  • 通过这个分类器,你只需要上传照片,就可以得到小狗的品种,以及更的信息。这就是所谓的「机器学习」,让机器自己去“学习”。我们今天要做的这个分类任务,是一个“监督学习”的过程。监督学习的主要目标是从有...

    d2bbbac4e9fb55232256fe846d9c361e.png

    项目介绍

    小狗分类器可以做什么?通过这个分类器,你只需要上传照片,就可以得到小狗的品种,以及更多的信息。这就是所谓的「机器学习」,让机器自己去“学习”。我们今天要做的这个分类任务,是一个“监督学习”的过程。监督学习的主要目标是从有标签的训练数据中学习模型,以便对未知或未来的数据做出预测。我给大家讲一个例子。
    用“房子的尺寸”预测“房子的价格”
    ca6ef5257bc0b288b988a646b9f41c30.png图片来自(吴恩达-机器学习)

        X-房子的尺寸(小狗的图片)
        Y-房子的价格(小狗的类别)

    如图,我们根据已经有的数据集(图上的坐标),可以拟合出一条近似符合规律的直线。这样,再有新的房子尺寸(1250),我们就可以估算出房子的价格(220k)了。有了这些简单的基础,可以开始搞了。

    效果展示

    训练集的准确率为0.925,但测试集只有0.7说明过拟合了,可以再增加一些图片,或者使用数据增强,来减少过拟合。04561be64856795df18b807775e2d9bb.png测试了两张图片,全都识别对了!93e2d402f6ae17341bc626ea48eb0ea3.png

    编写思路

    整个分类器的实现,可以分为以下几个部分:1 准备数据集我们可以通过爬虫技术,把4类图像(京巴、拉布拉多、柯基、泰迪)保存到本地。总共有840张图片做训练集,188张图片做测试集。2 数据集的预处理1) 统一尺寸为100*100*3(RGB彩色图像)
    # 统一尺寸的核心代码
    img = Image.open(img_path)
    new_img = img.resize((100, 100), Image.BILINEAR)
    new_img.save(os.path.join('./dog_kinds_after/' + dog_name, jpgfile))
    2) 由于数据是自己下载的,需要制作标签(label),可提取图像名称的第一个数字作为类别。(重命名图片)
    kind = 0# 遍历京巴的文件夹
    images = os.listdir(images_path)for name in images:
        image_path = images_path + '/'
        os.rename(image_path + name, image_path + str(kind) +'_' + name.split('.')[0]+'.jpg')
    3)划分数据集840张图片做训练集,188张图片做测试集4)把图片转换为网络需要的类型
    # 只放了训练集的代码,测试集一样操作。ima_train = os.listdir('./train')# 图片其实就是一个矩阵(每一个像素都是0-255之间的数)(100*100*3)# 1.把图片转换为矩阵def read_train_image(filename):
        img = Image.open(
    './train/' + filename).convert('RGB')return np.array(img)
    x_train = []
    # 2.把所有的图片矩阵放在一个列表里 (840, 100, 100, 3)for i in ima_train:
        x_train.append(read_train_image(i))
    x_train = np.array(x_train)# 3.提取kind类别作为标签
    y_train = []
    for filename in ima_train:
        y_train.append(int(filename.split(
    '_')[0]))# 标签(0/1/2/3)(840,)
    y_train = np.array(y_train)
    # 我是因为重命名图片为(1/2/3/4),所以都减了1# 为了能够转化为独热矩阵
    y_train = y_train - 
    1  # 4.把标签转换为独热矩阵# 将类别信息转换为独热码的形式(独热码有利于神经网络的训练)
    y_train = np_utils.to_categorical(y_train)
    y_test = np_utils.to_categorical(y_test)
    print(y_test)
    x_train = x_train.astype(
    'float32')
    x_test = x_test.astype(
    'float32')
    x_train /= 
    255
    x_test /= 
    255print(x_train.shape)  # (840, 100, 100, 3)
    print(y_train.shape)  
    # (840,)

    3 搭建卷积神经网络

    Keras是基于TensorFlow的深度学习库,是由纯Python编写而成的高层神经网络API,也仅支持Python开发。它是为了支持快速实践而对Tensorflow的再次封装,让我们可以不用关注过多的底层细节,能够把想法快速转换为结果。
    # 1.搭建模型(类似于VGG,直接拿来用就行)model = Sequential()# 这里搭建的卷积层共有32个卷积核,卷积核大小为3*3,采用relu的激活方式。# input_shape,字面意思就是输入数据的维度。#这里使用序贯模型,比较容易理解#序贯模型就像搭积木一样,将神经网络一层一层往上搭上去
    model.add(Conv2D(32, (33), activation='relu', input_shape=(1001003)))
    model.add(Conv2D(32, (33), activation='relu'))
    model.add(MaxPooling2D(pool_size=(22)))
    model.add(Dropout(0.25))
    model.add(Conv2D(64, (33), activation='relu'))
    model.add(Conv2D(64, (33), activation='relu'))
    model.add(MaxPooling2D(pool_size=(22)))
    model.add(Dropout(0.25))#dropout层可以防止过拟合,每次有25%的数据将被抛弃
    model.add(Flatten())
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(4, activation='softmax'))
    4 训练训练的过程,就是最优解的过程。ca6ef5257bc0b288b988a646b9f41c30.png

    对上图来说,就是根据数据集,不断的迭代,找到一条最近似的直线(y = kx + b),把参数k,b保存下来,预测的时候直接加载。

    # 编译模型
    sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
    model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])# 一共进行32轮# 也就是说840张图片,每次训练10张,相当于一共训练84次
    model.fit(x_train, y_train, batch_size=10, epochs=32)# 保存权重文件(也就是相当于“房价问题的k和b两个参数”)
    model.save_weights('./dog_weights.h5', overwrite=True)# 评估模型
    score = model.evaluate(x_test, y_test, batch_size=10)
    print(score)
    5 预测此时k、b(参数)和x(小狗的图像)都是已知的了,求k(类别)就完了。
    # 1.上传图片
    name = input('上传图片的名称(例如:XX.jpg)为:')# 2.预处理图片(代码省略)# 3.加载权重文件
    model.load_weights('dog_weights.h5')# 4.预测类别
    classes = model.predict_classes(x_test)[0]
    target = ['京巴''拉布拉多''柯基''泰迪']# 3-泰迪 2-柯基 1-拉布拉多 0-京巴# 5.打印结果
    print("识别结果为:" + target[classes])

    依赖环境

    深度学习框架Keras和TensorFlow2 PIL扩展库(预处理图片)3 Pycharm/Jupyter notebook

    总结

    5cd4a5adebcc1e2f5452cd68dbe1ab19.png

    2cec3ee174fc7f6af634bb72814f2c46.png

    展开全文
  • 通过这个分类器,你只需要上传照片,就可以得到小狗的品种,以及更的信息。这就是所谓的「机器学习」,让机器自己去“学习”。我们今天要做的这个分类任务,是一个“监督学习”的过程。监督学习的主要目标是从有...

    项目介绍

    小狗分类器可以做什么?

    通过这个分类器,你只需要上传照片,就可以得到小狗的品种,以及更多的信息。

    这就是所谓的「机器学习」,让机器自己去“学习”。我们今天要做的这个分类任务,是一个“监督学习”的过程。

    监督学习的主要目标是从有标签的训练数据中学习模型,以便对未知或未来的数据做出预测。

    我给大家讲一个例子。
    用“房子的尺寸”预测“房子的价格”

    248a7d416a0fd4d7ea156b4f9bf424a3.png

    图片来自(吴恩达-机器学习)

    X-房子的尺寸(小狗的图片)
    Y-房子的价格(小狗的类别)

    如图,我们根据已经有的数据集(图上的坐标),可以拟合出一条近似符合规律的直线。

    这样,再有新的房子尺寸(1250),我们就可以估算出房子的价格(220k)了。

    有了这些简单的基础,可以开始搞了。

    效果展示

    训练集的准确率为0.925,但测试集只有0.7

    说明过拟合了,可以再增加一些图片,或者使用数据增强,来减少过拟合。

    23d1a9caf60750db0477f41e8947182e.png

    测试了两张图片,全都识别对了!

    3f67881e9d80d375c725e02467c94dd1.png

    编写思路

    整个分类器的实现,可以分为以下几个部分:

    1 准备数据集

    我们可以通过爬虫技术,把4类图像(京巴、拉布拉多、柯基、泰迪)保存到本地。总共有840张图片做训练集,188张图片做测试集。

    2 数据集的预处理

    1) 统一尺寸为100*100*3(RGB彩色图像)

    # 统一尺寸的核心代码
    img = Image.open(img_path)
    new_img = img.resize((100, 100), Image.BILINEAR)
    new_img.save(os.path.join('./dog_kinds_after/' + dog_name, jpgfile))
    

    2) 由于数据是自己下载的,需要制作标签(label),可提取图像名称的第一个数字作为类别。(重命名图片)

    kind = 0
    
    # 遍历京巴的文件夹
    images = os.listdir(images_path)
    for name in images:
        image_path = images_path + '/'
        os.rename(image_path + name, image_path + str(kind) +'_' + name.split('.')[0]+'.jpg')
    

    3)划分数据集

    840张图片做训练集,188张图片做测试集。

    私信小编01 领取完整项目代码~

    4)把图片转换为网络需要的类型

    # 只放了训练集的代码,测试集一样操作。ima_train = os.listdir('./train')
    
    # 图片其实就是一个矩阵(每一个像素都是0-255之间的数)(100*100*3)# 1.把图片转换为矩阵
    def read_train_image(filename):
        img = Image.open('./train/' + filename).convert('RGB')
        return np.array(img)
    
    x_train = []
    # 2.把所有的图片矩阵放在一个列表里 (840, 100, 100, 3)
    for i in ima_train:
        x_train.append(read_train_image(i))x_train = np.array(x_train)
    # 3.提取kind类别作为标签
    y_train = []
    for filename in ima_train:
        y_train.append(int(filename.split('_')[0]))
    
    # 标签(0/1/2/3)(840,)
    y_train = np.array(y_train)
    
    # 我是因为重命名图片为(1/2/3/4),所以都减了1
    # 为了能够转化为独热矩阵
    y_train = y_train - 1  
    
    # 4.把标签转换为独热矩阵
    # 将类别信息转换为独热码的形式(独热码有利于神经网络的训练)
    y_train = np_utils.to_categorical(y_train)
    y_test = np_utils.to_categorical(y_test)
    print(y_test)
    
    x_train = x_train.astype('float32')
    x_test = x_test.astype('float32')
    
    x_train /= 255
    x_test /= 255print(x_train.shape)  # (840, 100, 100, 3)
    print(y_train.shape)  # (840,)

    3 搭建卷积神经网络

    Keras是基于TensorFlow的深度学习库,是由纯Python编写而成的高层神经网络API,也仅支持Python开发。

    它是为了支持快速实践而对Tensorflow的再次封装,让我们可以不用关注过多的底层细节,能够把想法快速转换为结果。

    # 1.搭建模型(类似于VGG,直接拿来用就行)model = Sequential()
    # 这里搭建的卷积层共有32个卷积核,卷积核大小为3*3,采用relu的激活方式。
    # input_shape,字面意思就是输入数据的维度。
    
    #这里使用序贯模型,比较容易理解
    #序贯模型就像搭积木一样,将神经网络一层一层往上搭上去
    
    model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(100, 100, 3)))
    model.add(Conv2D(32, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    #dropout层可以防止过拟合,每次有25%的数据将被抛弃
    
    model.add(Flatten())
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(4, activation='softmax'))

    4 训练

    训练的过程,就是最优解的过程。

    248a7d416a0fd4d7ea156b4f9bf424a3.png

    对上图来说,就是根据数据集,不断的迭代,找到一条最近似的直线(y = kx + b),把参数k,b保存下来,预测的时候直接加载。

    # 编译模型
    sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
    model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
    
    # 一共进行32轮
    # 也就是说840张图片,每次训练10张,相当于一共训练84次
    model.fit(x_train, y_train, batch_size=10, epochs=32)
    
    
    # 保存权重文件(也就是相当于“房价问题的k和b两个参数”)
    model.save_weights('./dog_weights.h5', overwrite=True)
    # 评估模型
    score = model.evaluate(x_test, y_test, batch_size=10)
    print(score)
    

    5 预测

    此时k、b(参数)和x(小狗的图像)都是已知的了,求k(类别)就完了。

    # 1.上传图片
    name = input('上传图片的名称(例如:XX.jpg)为:')
    
    # 2.预处理图片(代码省略)
    
    # 3.加载权重文件
    model.load_weights('dog_weights.h5')
    
    # 4.预测类别
    classes = model.predict_classes(x_test)[0]
    
    target = ['京巴', '拉布拉多', '柯基', '泰迪']
    # 3-泰迪 2-柯基 1-拉布拉多 0-京巴
    
    # 5.打印结果
    print("识别结果为:" + target[classes])

    依赖环境

    1 深度学习框架Keras和TensorFlow

    2 PIL扩展库(预处理图片)

    3 Pycharm/Jupyter notebook

    展开全文
  • 比如预定义的标签为:categories={cat,dog,panda}image.png分类系统还可以通过概率为图像分配标签。比如狗:95%;猫:4%;熊猫:1%。更重要的是,W×H像素输入图像有三个通道,Red,Green和Blue,分析W...

    什么是图像分类?

    图像分类的核心任务是从预定义的一类图像中为图像分配标签。分析输入图像并返回标签对图像进行分类。标签始终来自一组预定义的可能类别。

    比如预定义的标签为:categories = {cat, dog, panda}

    image.png

    分类系统还可以通过概率为图像分配多个标签。比如狗:95%;猫:4%;熊猫:1%。更重要的是,W×H像素输入图像有三个通道,Red,Green和Blue,分析W×H×3 = N像素图像,并弄清楚如何正确分类图像的内容。

    image.png

    在图像分类中,我们的数据集是图像的集合。因此,每个图像都是数据点。

    image.png

    左边猫,右边狗,电脑看到的是像素矩阵。实际上,计算机并不知道图像中有动物。

    image.png

    上图可描述如下:

    •空间:天空位于图像的顶部,沙/海洋位于底部。

    •颜色:天空是深蓝色,海水浅蓝色,而沙子则是

    棕褐色。

    •纹理:天空具有相对均匀的图案,而沙子非常粗糙。

    需要应用特征提取来量化图像的内容。特征提取是获取输入图像,应用算法和获得特征向量的过程。可使用HOG,LBP或其他传统图像量化方法。也可应用深度学习来自动学习。

    image.png视角:方向/旋转等

    大小

    变形

    遮挡

    照明

    背景

    类内变异

    对内容做出假设:图像以及容忍的变化。最终目标是什么?我们想要建立什么?

    如果采用过于广泛的方法,例如“我想对厨房的每个对象进行分类和检测,除非你有多年构建图像分类器的经验,否则不太可能表现良好。但是,如果你构建问题并使其范围缩小,例如“我想要识别只是炉子和冰箱“,那么你的系统更可能是准确和有效。尽管深度学习和卷积神经网络强大,你仍然应该尽可能地保持项目的范围。ImageNet的图像分类的事实标准的基准数据集:计算算法由我们在日常生活中遇到的1,000个对象组成。

    学习类型

    常见的监督学习算法包括逻辑回归(Logistic Regression),支持向量机(SVM  Support Vector Machine)随机森林(Random Forest)和人工神经网络(Artificial Neural Network)。

    image.png

    无监督学习(有时称为自学式学习)没有与输入数据相关联的标签,因此我们无法更正我们的模型预测。

    用于无监督学习的经典机器学习算法包括主成分分析(PCA  Principle Component Analysis)和k均值聚类( k-means clustering)。对于神经网络,还有自动编码器(Autoencoders),自组织映射(Self-Organizing Map: SOM)和自适应共振理论(Adaptive Resonance Theory)。

    image.png

    半监督学习算法将采用已知的数据,分析它们,并尝试标记每个未标记的数据点。半监督学习在计算机视觉中特别有用,我们根本没有时间或资源来标记每个个人形象。方法有标签传播(label spreading),标签累积(label propagation),梯形网络(ladder network)和共同学习/共同培训(co-learning/co-training)。

    image.png

    深度学习的流程

    思维方式的转变

    0,1,1,2,3,5,8,13,21,34 ......

    当然,我们也可以使用(在极其未经优化的)Python函数中定义此模式

    递归:>>> def fib(n):...     if n == 0:...             return 0...     elif n == 1:...             return 1...     else:...             return fib(n-1) + fib(n-2)... >>> fib(7)13>>> fib(13)233>>> fib(35

    深度学习和图像分类没有定义函数这么简单。没有确定的规则,而是采用数据驱动的方法归类。

    每个类别看起来像然后教我们的算法识别之间的差异

    训练数据集包括:

    1.图像

    2.图像的标签/类别(即狗,猫,熊猫等)

    image.png步骤#1:收集数据集

    图像本身以及与每个图像相关联的标签。例如:categories = dog,cat,panda。此外,每个类别的图像数量应大致相同(即每个类别的相同数量的例子)。步骤2:拆分数据集

    现在我们有了初始数据集,我们需要将它分成两部分:

    1.训练集

    2.测试集

    image.png

    神经网络有需要调整,例如,学习率,衰减,正则化等,称为超参数。注意训练集、调整超参数的验证集和测试集一定要严格分开。步骤3:训练您的网络

    网络了解如何识别标记数据中的每个类别。当模型出错时,如何从这个错误中学习并改进自己。一般来说,我们应用一种梯度下降的方法。步骤#4:评估测试

    除了正确性(ground-truth标签),还有聚合报告,如精度,recall和f-measure,用于量化整个网络的性能。

    在传统的,基于特征的图像分类方法中,在步骤#2和步骤#3之间有特征提取。采用HOG、LBP等算法,基于我们想要编码的图像的特定分量(即形状、颜色、纹理)量化图像的内容,然后继续训练我们的分类器并对其进行评估。

    在构建卷积神经网络时,我们实际上可以跳过特征提取。这是因为CNN是端到端的模型。但训练CNN是非常重要的过程。

    作者:python作业AI毕业设计

    链接:https://www.jianshu.com/p/273ec3b1b988

    展开全文
  • - fc_lamp的日志 - 网易博客简单的python (orc)图片识别(识别京东价格图片) 2012-12-11 23:27:51| 分类: Web技术-Python标签: |字号大中小 订阅网上有很关于python orc 图片识别技术的文章,我这里只是...
  • 这里主要涉及到的技术是图像识别图像识别是指利用计算机对图像进行处理、分析和理解,以识别各种不同模式的目标和对像的技术。机器学习领域一般将此类识别问题转化为分类问题。手写数字识别可以转化为10分类问题,...
  • 使用Python和OpenCV检测图像中的物体并将物体裁剪下来原创 2017年02月18日 21:14:24标签python /opencv /图片24796介绍硕士阶段的毕设是关于昆虫图像分类的,代码写到一半,上周五导师又给我新的昆虫图片数据集...
  • 1 任务介绍手写数字识别是一个多分类问题,共有10个分类,每个手写数字图像的类别标签是0~9中的其中一个数。例如下面这三张图片的标签分别是0,1,2。 本实例利用sklearn来训练一个K最近邻(k-Nearest Neighbor,...
  • 1 任务介绍手写数字识别是一个多分类问题,共有10个分类,每个手写数字图像的类别标签是0~9中的其中一个数。例如下面这三张图片的标签分别是0,1,2。 任务:利用sklearn来训练一个简单的全连接神经网络,即多层...
  • 图像分类是计算机视觉的重要领域,它的目标是将图像分类到预定义的标签。近期,许多研究者提出很不同种类的神经网络,并且极大的提升了分类算法的性能。本文以自己创建的数据集:青春有你2中选手识别为例子,介绍...
  • (1)数据集描述 使用逻辑回归来识别手写...图像在martix X中表示为400维向量(其中有5,000个), 400维“特征”是原始20 x 20图像中每个像素的灰度强度, 类标签在向量y中作为表示图像中数字的数字类。 import nump...
  • 图像分类是计算机视觉的重要领域,它的目标是将图像分类到预定义的标签。近期,许多研究者提出很不同种类的神经网络,并且极大的提升了分类算法的性能。本文以自己创建的数据集:青春有你2中选手识别为例子...
  • scikit-image:一个用于(科学)图像处理的 Python 库。 thumbor:一个小型图像服务,具有剪裁,尺寸重设和翻转功能。 wand:MagickWand 的 Python 绑定。MagickWand 是 ImageMagick 的 C API 。 face_...
  • 图像分类是计算机视觉的重要领域,它的目标是将图像分类到预定义的标签。近期,许多研究者提出很不同种类的神经网络,并且极大的提升了分类算法的性能。本文以自己创建的数据集:青春有你2中选手识别为例子,介绍...
  • 面向对象设计与图像界面上设计一个类发短信类的方法设计一下短信发送邮件类的设计-设计发邮件类的文件引用腾讯营销类的设计消息循环消息回掉函数机制lambda按下按钮标签显示文本文本输入框listcombobox选择列表...
  • AdaBoost(adapt boost),自适应推进算法:Adaboost算法是机器学习中一种比较重要的特征分类算法,已被广泛应用人脸表情识别图像检索等应用中。就目前而言,对Adaboost算法的研究以及应用大多集中于分类问题,在...
  • 图像分类是计算机视觉的重要领域,它的目标是将图像分类到预定义的标签。近期,许多研究者提出很不同种类的神经网络,并且极大的提升了分类算法的性能。本文以自己创建的数据集:青春有你2中选手识别为例子,介绍...
  • 1.图像分类的更tricks(注意力机制 keras,TensorFlow和pytorch 版本等):图像分类比赛tricks:“华为云杯”2019人工智能创新应用大赛 2.大家如果对目标检测比赛比较感兴趣的话,可以看一下我这篇对目标检测比赛...
  • 我试了试,还好我的Python基础和调试能力还不错,基本上代码都调试过一遍,很高大上的 "理论+推导",在我眼中变成了几个 "加减乘除+循环",我想这不就是像我这样的程序员想要的入门教程么? 很程序员说机器学习 ...
  • LBPH特征是从图像中提取的关键点,用于识别分类图像。 在视频中检测到某个人后,我们便会跟踪为该人分配标签的人。 我们已使用个人存储的LBPH功能在其他任何视频中识别它们。 扫描完各种视频后,我们的程序将输出...
  • Demo示例提供丰富的Fine-tune API的使用代码,包括文本分类、序列标注、多标签分类图像分类、检索式问答任务、回归任务、句子语义相似度计算、阅读理解任务等场景的模型迁移示例。 十行代码完成ERNIE工业级...
  • Demo示例提供丰富的Fine-tune API的使用代码,包括文本分类、序列标注、多标签分类图像分类、检索式问答任务、回归任务、句子语义相似度计算、阅读理解任务等场景的模型迁移示例。 十行代码完成ERNIE工业级...
  • Demo示例提供丰富的Fine-tune API的使用代码,包括文本分类、序列标注、多标签分类图像分类、检索式问答任务、回归任务、句子语义相似度计算、阅读理解任务等场景的模型迁移示例。 十行代码完成ERNIE工业级...
  • 情感分析-实体链接等)、word2word:(Python)方便易用的语言词-词对集:62种语言/3,564个语言对、语音识别语料生成工具:从具有音频/字幕的在线视频创建自动语音识别(ASR)语料库、构建医疗实体识别的模型(包含...
  • 我试了试,还好我的Python基础和调试能力还不错,基本上代码都调试过一遍,很高大上的 "理论+推导",在我眼中变成了几个 "加减乘除+循环",我想这不就是像我这样的程序员想要的入门教程么? 很程序员说机器学习 ...
  • 相似性搜索的工作原理:相似性搜索工具可用于识别哪些候选要素与要匹配的一个或个输入要素最相似(或最相异)。相似性的基础是数值属性(感兴趣属性)的指定列表。如果指定了一个以上的要匹配的输入要素,相似性将...
  • 适用于Python、R、Julia、Scala、Go、Javascript和更网站。 PyTorch:具有强大CPU加速功能,包含张量和动态神经网络的Python库。 Recast/Detour:(3D)导航网格生成器和路径查找,主要用于游戏。 TensorFlow:...
  • 软件工程教程

    热门讨论 2012-07-06 23:10:29
    删除操作一旦执行,立即被监听器捕获到,进而在执行 删除操作前执行自定义的函数体,即判断实体有无undeletable标签,有则中断删除操作,无则正常删除。 用例图 关系 关联关系 ;依赖关系 ;泛化关系;关系的...

空空如也

空空如也

1 2
收藏数 29
精华内容 11
关键字:

多标签分类python图像识别

python 订阅