日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > Caffe >内容正文

Caffe

caffe data层_Caffe实现多标签输入,添加数据层(data layer)

發布時間:2024/9/30 Caffe 235 豆豆
生活随笔 收集整理的這篇文章主要介紹了 caffe data层_Caffe实现多标签输入,添加数据层(data layer) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

因為之前遇到了sequence learning問題(CRNN),里面涉及到一張圖對應多個標簽。Caffe源碼本身是不支持多類標簽數據的輸入的。

如果之前習慣調用腳本create_imagenet.sh,將原始數據轉換成lmdb數據格式,在這里就會遇到坑。我們去看convert_imageset源碼,我們就會發現它是把最后一個空格前面的當作輸入,最后一個空格之后的當作標簽,那當然無法多標簽啊。

通常解決辦法

換框架,換一個能支持多標簽分類問題的,例如mxnet,但我覺得你既然選擇用Caffe來解決問題,估計也不會換。

HDF5+Slice Layer實現,因為Caffe中要求一個hdf5文件大小不超過2GB,所以文件如果較大的話,需要生成多個hdf5文件,所以需要用到Slice Layer。 參考生成hdf5文件用于多標簽訓練

用兩個data的輸入(兩個LMDB),一個只輸出圖片,一個只輸出標簽,這種方法相對前面兩種要難一些.

其實我個人總結的是,數據層的添加可以考慮用python,因為比較簡單、快,也不會影響效率,計算層的添加還是需要用C++來寫的。

本文解決方案

我采用的方案就是用python將數據轉換成lmdb格式,然后在prototxt中定義采用python module的方式,去讀取之前轉換的lmdb數據。

具體步驟

1. 前期數據準備

前期的數據準備和單分類一樣,只不過現在我們有多個標簽了,那么我就在train.txt和val.txt中,用空格將多個標簽分隔開。例如 image1.jpg label1 label2 label3 label4

2. 數據轉lmdb格式

#!/usr/bin/python

# -*- coding: utf-8 -*-

import numpy as np

import lmdb

import sys, os

import caffe

from skimage import io

import cv2

import random

train_path = 'train.txt' # 訓練集標簽

val_path = 'val.txt' # 驗證集標簽

train_lmdb = '/path/to/your/data_train_lmdb' # 生成lmdb格式訓練集數據的路徑,到目錄級別就可以了

val_lmdb = '/path/to/your/data_val_lmdb' # 生成lmdb格式驗證集數據的路徑,到目錄級別就可以了

# 加載train.txt

def load_txt(txt, shuffle):

if txt == None:

print "txtpath!!!"

exit(0)

if not os.path.exists(txt):

print "the txt is't exists"

exit(0)

# 將數據按行存入list中

file_content = []

with open(txt, 'r') as fr:

for line in fr.readlines():

line = line.strip()

file_content.append([_ for _ in line.split(' ')])

# shuffle數據

if shuffle:

random.shuffle(file_content)

return file_content

if __name__ == '__main__':

content = []

# 這里定義了要處理的文件目錄,因為我們有train data 和 val data,所以我們需要把val_path和val_lmdb改成train_path和train_lmdb再執行一次這個腳本。

content = load_txt(val_path, True)

env = lmdb.Environment(val_lmdb, map_size=int(1e12))

with env.begin(write=True) as txn:

for i in range(len(content)):

pic_path = content[i][0]

# 采用skimage庫的方式來讀文件

img_file = io.imread(pic_path, as_grey=True)

# 如果采用opencv的方式來讀文件,那么下面也要改成mat轉string的方式

#img_file = cv2.imread(pic_path, 0)

data = np.zeros(( img_file.shape[0], img_file.shape[1]), dtype=np.uint8)

data = img_file

# 因為lmdb是鍵值數據庫,所以我們采用將鍵和值都設置為字符串格式

str_id = "image-%09d" %(i)

cv2.imencode('.jpg', data)

txn.put(str_id.encode('ascii'), cv2.imencode('.jpg', data)[1].tostring())

# 這里的多標簽采用的是空格分隔,到時候讀lmdb數據庫的時候,也用空格解析就可以了

multi_labels = ""

for _ in content[i][1:len(content[i])]:

multi_labels += _

multi_labels += " "

multi_labels += content[i][-1]

# 鍵和值都是字符串格式

str_id = "label-%09d" %(i)

#txn.put(str_id.encode('ascii'), multi_labels)

txn.put(str_id, multi_labels)

#txn.put(str_id, multi_labels)

str_id = "num-samples"

txn.put(str_id, str(len(content)))

#txn.put(str_id.encode('ascii'), str(len(content)))

print str(len(content))

分別設置train和val執行這個腳本兩次,得到的就是兩個目錄,里面包含lmdb格式的訓練集和驗證集,這就回到了我們熟悉的方式,因為之前直接調用自帶腳本得到的結果也是這樣。

3. 定義dataLayer

這步的作用就是,在prototxt會定義input是采用這個dataLayer將數據讀入的。

具體做法將上一步生成的lmdb數據讀出來就可以了。

我們先來看看官方給的python接口格式。

# 這是一個lossLayer的例子

import caffe

import numpy as np

class EuclideanLossLayer(caffe.Layer):

"""

Compute the Euclidean Loss in the same manner as the C++ EuclideanLossLayer

to demonstrate the class interface for developing layers in Python.

"""

# 設置參數

def setup(self, bottom, top):

# check input pair

if len(bottom) != 2:

raise Exception("Need two inputs to compute distance.")

def reshape(self, bottom, top):

# check input dimensions match

if bottom[0].count != bottom[1].count:

raise Exception("Inputs must have the same dimension.")

# difference is shape of inputs

self.diff = np.zeros_like(bottom[0].data, dtype=np.float32)

# loss output is scalar

top[0].reshape(1)

# 前向計算方式

def forward(self, bottom, top):

self.diff[...] = bottom[0].data - bottom[1].data

top[0].data[...] = np.sum(self.diff**2) / bottom[0].num / 2.

# 反向傳播方式

def backward(self, top, propagate_down, bottom):

for i in range(2):

if not propagate_down[i]:

continue

if i == 0:

sign = 1

else:

sign = -1

bottom[i].diff[...] = sign * self.diff / bottom[i].num

那么我們知道接口長什么樣以后,我們就開始依葫蘆畫瓢了。別急,先來看看prototxt怎么定義參數的,因為到時候這個決定了我們要向data Layer中傳入什么參數。先看看官方接口

4. 定義prototxt

message PythonParameter {

optional string module = 1;

optional string layer = 2;

// This value is set to the attribute `param_str` of the `PythonLayer` object

// in Python before calling the `setup()` method. This could be a number,

// string, dictionary in Python dict format, JSON, etc. You may parse this

// string in `setup` method and use it in `forward` and `backward`.

optional string param_str = 3 [default = '']; # 這里比較關鍵,也就是我們通過這個參數,來決定如何讀取lmdb數據的

// DEPRECATED

optional bool share_in_parallel = 4 [default = false];

}

我給一個實例代碼

layer {

name: "data"

type: "Python"

top: "data"

top: "label"

include {

phase: TRAIN

}

python_param {

module: "dataLayer"

layer: "CRNNDataLayer"

param_str: "{'data' : '/path/to/your/data_train_lmdb', 'batch_size' : 128}"

}

}

我們可以看到它會去調用dataLayer這個python模塊,那么就需要定義dataLayer,具體實現如下。

import sys

import caffe

from caffe import layers as L, params as P

from caffe.coord_map import crop

import numpy as np

import os

import cv2

import lmdb

import random

import timeit

import os

class CRNNDataLayer(caffe.Layer):

def setup(self, bottom, top):

params = eval(self.param_str)

# 讀prototxt中的參數

self.lmdb = lmdb.open(params['data']).begin(buffers=True).cursor()

# 這個是生成lmdb數據的時候,定義的樣本的總個數

c=self.lmdb.get('num-samples')

# print '['+str(c)+']'

self.max_num = int(str(c))

self.batch_size = int(params['batch_size'])

# two tops: data and label

if len(top) != 2:

raise Exception("Need to define two tops: data and label.")

# data layers have no bottoms

if len(bottom) != 0:

raise Exception("Do not define a bottom.")

def reshape(self, bottom, top):

# load image + label image pair

start = timeit.timeit()

self.data,self.label = self.load_data()

end = timeit.timeit()

# print 'time used for reshape',end-start

# reshape tops to fit (leading 1 is for batch dimension)

top[0].reshape(*self.data.shape)

top[1].reshape(*self.label.shape)

def forward(self, bottom, top):

# assign output

top[0].data[...] = self.data

top[1].data[...] = self.label

# 因為是data layer,所以不需要定義backward

def backward(self, top, propagate_down, bottom):

pass

def load_data(self):

# 采用隨機讀入的方式

rnd = random.randint(0,self.max_num-self.batch_size-1)

# 先初始化一個多維數組,用于存放讀入的數據,在這里設置batch size, channel, height, width

img_list= np.zeros((self.batch_size, channel, height, width),

dtype = np.float32)

# 先初始化一個多維數組,用于存放標簽數據,設置batch size, label size(每張圖對應的標簽的個數)

label_seq = np.ones((self.batch_size, label_size), dtype = np.float32)

j = 0

i = 0

# print 'loading data ...'

while i < self.batch_size:

# rnd = random.randint(0,self.max_num-self.batch_size-1)

imageKey = 'image-%09d' % (rnd + j)

labelKey = 'label-%09d' % (rnd + j)

try:

img_array = np.asarray(bytearray(self.lmdb.get(imageKey)), dtype=np.uint8)

#imgdata = cv2.imdecode(img_array, 0)

imgdata = cv2.imdecode(np.fromstring(img_array, np.uint8), cv2.CV_LOAD_IMAGE_GRAYSCALE)

# 設置resize的width和height

image = cv2.resize(imgdata, width,height))

image = (image - 128.0)/128

img_list[i] = image

label = str(self.lmdb.get(labelKey))

#numbers = np.array(map(lambda x: float(ascii2label(ord(x))), label))

label_list = label.split(" ")

label_list = [int(_) for _ in label_list]

# 這里把標簽依次放入數組中

label_seq[i, :len(label_list)] = label_list

i+=1

except Exception as e:

print e

j+=1

# print 'data loaded'

return img_list,label_seq

5. 重新編譯caffe

因為我們添加了一個python module,那么我們要在環境變量中,設置這個module,不然會出現找不到的情況。

vim ~/.bash_profile

export PYTHONPATH=$PYTHONPATH:(添加dataLayer.py所在目錄)

source ~/.bash_profile

編譯

WITH_PYTHON_LAYER=1 make && make pycaffe

大功告成

本人親測以上方式是可行的。

總結

以上是生活随笔為你收集整理的caffe data层_Caffe实现多标签输入,添加数据层(data layer)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日美毛片| 俺去射 | 欧美亚洲日本国产 | 国产亚洲色婷婷久久99精品91 | 国产aaaaa毛片 | 精品一区二区三区免费视频 | 国产99久久久国产精品成人免费 | 午夜免费视频网站 | 日韩在线第三页 | 国产亚洲精品自拍 | 国产又粗又猛又爽又黄的视频小说 | 能免费看18视频网站 | 齐天大性床战铁扇公主 | 久久久无码精品亚洲无少妇 | 大学生一级一片全黄 | 丁香午夜 | 亚洲欧洲国产精品 | 古装做爰无遮挡三级视频 | 男人天堂综合网 | 色乱码一区二区三区在线男奴 | 97超碰在线免费观看 | 黄色图片小说 | a级黄毛片 | 午夜视频观看 | 日韩在线一区二区三区四区 | 亚洲av永久纯肉无码精品动漫 | 亚洲视频免费在线播放 | 人人妻人人爽欧美成人一区 | 青青草视频在线观看免费 | 一级黄色大片视频 | 久久精品无码毛片 | 日韩精品一区二区三区久久 | 啪在线视频| a级片免费看 | 国产视频亚洲 | 色偷偷视频 | 国产激情片 | 美女的胸给男人玩视频 | 一级黄色片免费播放 | 老熟妇高潮一区二区三区 | 亚洲精品国产精品乱码不66 | 亚洲区一区二 | 女人天堂网 | 五十路熟母 | 日本一二三区不卡 | 美女视频免费在线观看 | 丰满人妻一区二区三区免费视频 | 边啃奶头边躁狠狠躁 | 老司机激情影院 | 福利亚洲| 欧美裸体网站 | av色欲无码人妻中文字幕 | av资源吧首页 | 亚洲国产天堂av | 久久av网址 | 台湾佬中文字幕 | 色涩久久 | 伊人久久综合 | 久久久穴 | 69视频免费 | 亚洲视频一二三 | 亚洲国内在线 | 成人在线观看网 | 人妻互换一二三区激情视频 | 国产人人爽| 91av免费观看 | 午夜爽爽影院 | 国产精品一线二线 | 一区二区网站 | 午夜污 | 久久久久99精品成人片试看 | av片一区二区三区 | 欧洲做受高潮欧美裸体艺术 | 午夜av福利 | 日韩成年视频 | 自拍偷拍亚洲一区 | 啪啪综合 | 黄色的网站在线 | 午夜偷拍福利视频 | 黄色片在线免费看 | 一色桃子juy758在线播放 | 蜜臀av免费在线观看 | 伊人成年综合网 | 朝桐光在线观看 | 久久一区二区精品 | xxx在线视频 | 国内精品免费 | 91.xxx.高清在线 | 少妇高潮一区二区三区69 | 毛片一级在线观看 | 亚洲精品av在线 | 天天综合网国产 | 免费操片 | 国产小视频免费 | 亚洲精品在线不卡 | 波多野结衣绝顶大高潮 | xxxxxxxx黄色片 | 亚洲情侣在线 | 影音先锋欧美资源 |