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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

动手学PaddlePaddle(3):猫脸识别

發(fā)布時(shí)間:2023/12/10 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动手学PaddlePaddle(3):猫脸识别 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

你將學(xué)會(huì):

  • 預(yù)處理圖片數(shù)據(jù)

  • 利用PaddlePaddle框架實(shí)現(xiàn)Logistic回歸模型:

在開始練習(xí)之前,簡(jiǎn)單介紹一下圖片處理的相關(guān)知識(shí):

圖片處理

由于識(shí)別貓問題涉及到圖片處理知識(shí),這里對(duì)計(jì)算機(jī)如何保存圖片做一個(gè)簡(jiǎn)單的介紹。在計(jì)算機(jī)中,圖片被存儲(chǔ)為三個(gè)獨(dú)立的矩陣,分別對(duì)應(yīng)圖中的紅、綠、藍(lán)三個(gè)顏色通道,如果圖片是64*64像素的,就會(huì)有三個(gè)64*64大小的矩陣,要把這些像素值放進(jìn)一個(gè)特征向量中,需要定義一個(gè)特征向量X,將三個(gè)顏色通道中的所有像素值都列出來。如果圖片是64*64大小的,那么特征向量X的長(zhǎng)度就是64*64*3,也就是12288。這樣一個(gè)長(zhǎng)度為12288的向量就是Logistic回歸模型的一個(gè)訓(xùn)練數(shù)據(jù)。


目錄

1 - 引用庫(kù)

2 - 數(shù)據(jù)預(yù)處理

3 - 構(gòu)造reader

4 - 訓(xùn)練過程

4.1 獲取訓(xùn)練數(shù)據(jù)

4.2配置網(wǎng)絡(luò)結(jié)構(gòu)和損失函數(shù)

4.3 設(shè)置優(yōu)化方法

4.4 定義訓(xùn)練場(chǎng)所

4.5設(shè)置訓(xùn)練主循環(huán)

5 - 預(yù)測(cè)階段

6 - 總結(jié)


1 - 引用庫(kù)

import sys import numpy as npimport lr_utils import matplotlib.pyplot as pltimport paddle import paddle.fluid as fluidfrom paddle.utils.plot import Ploter %matplotlib inline

2 - 數(shù)據(jù)預(yù)處理

這里簡(jiǎn)單介紹數(shù)據(jù)集及其結(jié)構(gòu)。數(shù)據(jù)集以hdf5文件的形式存儲(chǔ),包含了如下內(nèi)容:

  • 訓(xùn)練數(shù)據(jù)集:包含了m_train個(gè)圖片的數(shù)據(jù)集,數(shù)據(jù)的標(biāo)簽(Label)分為cat(y=1)和non-cat(y=0)兩類。
  • 測(cè)試數(shù)據(jù)集:包含了m_test個(gè)圖片的數(shù)據(jù)集,數(shù)據(jù)的標(biāo)簽(Label)同上。

單個(gè)圖片數(shù)據(jù)的存儲(chǔ)形式為(num_x, num_x, 3),其中num_x表示圖片的長(zhǎng)或?qū)?#xff08;數(shù)據(jù)集圖片的長(zhǎng)和寬相同),數(shù)字3表示圖片為三通道(RGB)。

需要注意的是,為了方便,添加“_orig”后綴表示該數(shù)據(jù)為原始數(shù)據(jù),之后需要對(duì)數(shù)據(jù)做進(jìn)一步處理。未添加“_orig”的數(shù)據(jù)則表示之后不需要再對(duì)該數(shù)據(jù)作進(jìn)一步處理。

# 調(diào)用load_dataset()函數(shù),讀取數(shù)據(jù)集 train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = lr_utils.load_dataset()# 圖片示例 # 可觀察到索引為“23”的圖片應(yīng)為“non-cat” index = 19 plt.imshow(train_set_x_orig[index]) print ("y = " + str(train_set_y[:, index]) + ", it's a '" + classes[np.squeeze(train_set_y[:, index])].decode("utf-8") + "' picture.")

獲取數(shù)據(jù)后的下一步工作是獲得數(shù)據(jù)的相關(guān)信息,如訓(xùn)練樣本個(gè)數(shù) m_train、測(cè)試樣本個(gè)數(shù) m_test 和圖片的長(zhǎng)度或?qū)挾?num_x,使用 numpy.array.shape 來獲取數(shù)據(jù)的相關(guān)信息

m_train = train_set_x_orig.shape[0] m_test = test_set_x_orig.shape[0] num_px = train_set_x_orig.shape[1]print ("訓(xùn)練樣本數(shù): m_train = " + str(m_train)) print ("測(cè)試樣本數(shù): m_test = " + str(m_test)) print ("圖片高度/寬度: num_px = " + str(num_px)) print ("圖片大小: (" + str(num_px) + ", " + str(num_px) + ", 3)") print ("train_set_x shape: " + str(train_set_x_orig.shape)) print ("train_set_y shape: " + str(train_set_y.shape)) print ("test_set_x shape: " + str(test_set_x_orig.shape)) print ("test_set_y shape: " + str(test_set_y.shape)) 訓(xùn)練樣本數(shù): m_train = 209 測(cè)試樣本數(shù): m_test = 50 圖片高度/寬度: num_px = 64 圖片大小: (64, 64, 3) train_set_x shape: (209, 64, 64, 3) train_set_y shape: (1, 209) test_set_x shape: (50, 64, 64, 3) test_set_y shape: (1, 50)

接下來需要對(duì)數(shù)據(jù)作進(jìn)一步處理,為了便于訓(xùn)練,可以先忽略圖片的結(jié)構(gòu)信息,將包含圖像長(zhǎng)、寬和通道數(shù)信息的三維數(shù)組壓縮成一維數(shù)組,圖片數(shù)據(jù)的形狀將由(64, 64, 3)轉(zhuǎn)化為(64 * 64 * 3, 1)。

# 定義維度 DATA_DIM = num_px * num_px * 3# 轉(zhuǎn)換數(shù)據(jù)形狀train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0], -1) test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0], -1)print ("train_set_x_flatten shape: " + str(train_set_x_flatten.shape)) print ("train_set_y shape: " + str(train_set_y.shape)) print ("test_set_x_flatten shape: " + str(test_set_x_flatten.shape)) print ("test_set_y shape: " + str(test_set_y.shape))

?

在開始訓(xùn)練之前,還需要對(duì)數(shù)據(jù)進(jìn)行歸一化處理。圖片采用紅、綠、藍(lán)三通道的方式來表示顏色,每個(gè)通道的單個(gè)像素點(diǎn)都存儲(chǔ)著一個(gè) 0-255 的像素值,所以圖片的歸一化處理十分簡(jiǎn)單,只需要將數(shù)據(jù)集中的每個(gè)像素值除以 255 即可,但需要注意的是計(jì)算結(jié)果應(yīng)為 float 類型。

train_set_x = train_set_x_flatten.astype('float32') / 255 test_set_x = test_set_x_flatten.astype('float32') / 255

為了方便后續(xù)的測(cè)試工作,添加了合并數(shù)據(jù)集和標(biāo)簽集的操作,使用 numpy.hstack 實(shí)現(xiàn) numpy 數(shù)組的橫向合并。

train_set = np.hstack((train_set_x, train_set_y.T)) test_set = np.hstack((test_set_x, test_set_y.T))

經(jīng)過上面的實(shí)驗(yàn),需要記住:

對(duì)數(shù)據(jù)進(jìn)行預(yù)處理的一般步驟是:

  • 了解數(shù)據(jù)的維度和形狀等信息,例如(m_train, m_test, num_px, ...)
  • 降低數(shù)據(jù)緯度,例如將數(shù)據(jù)維度(num_px, num_px, 3)轉(zhuǎn)化為(num_px * num_px * 3, 1)
  • 數(shù)據(jù)歸一化

3 - 構(gòu)造reader

構(gòu)造read_data()函數(shù),來讀取訓(xùn)練數(shù)據(jù)集train_set或者測(cè)試數(shù)據(jù)集test_set。它的具體實(shí)現(xiàn)是在read_data()函數(shù)內(nèi)部構(gòu)造一個(gè)reader(),使用yield關(guān)鍵字來讓reader()成為一個(gè)Generator(生成器),注意,yield關(guān)鍵字的作用和使用方法類似return關(guān)鍵字,不同之處在于yield關(guān)鍵字可以構(gòu)造生成器(Generator)。雖然我們可以直接創(chuàng)建一個(gè)包含所有數(shù)據(jù)的列表,但是由于內(nèi)存限制,我們不可能創(chuàng)建一個(gè)無限大的或者巨大的列表,并且很多時(shí)候在創(chuàng)建了一個(gè)百萬數(shù)量級(jí)別的列表之后,我們卻只需要用到開頭的幾個(gè)或幾十個(gè)數(shù)據(jù),這樣造成了極大的浪費(fèi),而生成器的工作方式是在每次循環(huán)時(shí)計(jì)算下一個(gè)值,不斷推算出后續(xù)的元素,不會(huì)創(chuàng)建完整的數(shù)據(jù)集列表,從而節(jié)約了內(nèi)存使用。

# 讀取訓(xùn)練數(shù)據(jù)或測(cè)試數(shù)據(jù) def read_data(data_set):"""一個(gè)readerArgs:data_set -- 要獲取的數(shù)據(jù)集Return:reader -- 用于獲取訓(xùn)練數(shù)據(jù)集及其標(biāo)簽的生成器generator"""def reader():"""一個(gè)readerArgs:Return:data[:-1], data[-1:] -- 使用yield返回生成器(generator),data[:-1]表示前n-1個(gè)元素組成的list,也就是訓(xùn)練數(shù)據(jù),data[-1]表示最后一個(gè)元素,也就是對(duì)應(yīng)的標(biāo)簽"""for data in data_set:### START CODE HERE ### (≈ 1 lines of code)yield data[:-1], data[-1]### END CODE HERE ###return reader test_array = [[1,1,1,1,0],[2,2,2,2,1],[3,3,3,3,0]]print("test_array for read_data:") for value in read_data(test_array)():print(value)test_array for read_data: ([1, 1, 1, 1], 0) ([2, 2, 2, 2], 1) ([3, 3, 3, 3], 0)

4 - 訓(xùn)練過程

4.1 獲取訓(xùn)練數(shù)據(jù)

關(guān)于參數(shù)的解釋如下:

paddle.reader.shuffle(read_data(data_set), buf_size=BUF_SIZE) 表示從read_data(data_set)這個(gè)reader中讀取了BUF_SIZE大小的數(shù)據(jù)并打亂順序paddle.batch(reader(), batch_size=BATCH_SIZE) 表示從reader()中取出BATCH_SIZE大小的數(shù)據(jù)進(jìn)行一次迭代訓(xùn)練BATCH_SIZE= 32# 設(shè)置訓(xùn)練reader train_reader = paddle.batch(paddle.reader.shuffle(read_data(train_set), buf_size=500),batch_size=BATCH_SIZE)#設(shè)置測(cè)試 reader test_reader = paddle.batch(paddle.reader.shuffle(read_data(test_set), buf_size=500),batch_size=BATCH_SIZE)

4.2配置網(wǎng)絡(luò)結(jié)構(gòu)和損失函數(shù)

Logistic 回歸模型結(jié)構(gòu)相當(dāng)于一個(gè)只含一個(gè)神經(jīng)元的神經(jīng)網(wǎng)絡(luò),如下圖所示,只包含輸入數(shù)據(jù)以及輸出層,不存在隱藏層,所以只需配置輸入層(input)、輸出層(predict)和標(biāo)簽層(label)即可。

#配置輸入層、輸出層、標(biāo)簽層 x = fluid.layers.data(name='x', shape=[DATA_DIM], dtype='float32') y_predict = fluid.layers.fc(input=x, size=2, act='softmax') y = fluid.layers.data(name='y', shape=[1], dtype='int64') #定義損失函數(shù) cost = fluid.layers.cross_entropy(input=y_predict, label=y) avg_loss = fluid.layers.mean(cost) acc = fluid.layers.accuracy(input=y_predict, label=y)

接下來,我們寫三個(gè)語句分別來獲取:

  • ①全局主程序main program。該主程序用于訓(xùn)練模型。
  • ②全局啟動(dòng)程序startup_program。該程序用于初始化。
  • ③測(cè)試程序test_program。用于模型測(cè)試。
startup_program = fluid.default_startup_program() main_program = fluid.default_main_program()#克隆main_program得到test_program #有些operator在訓(xùn)練和測(cè)試之間的操作是不同的,例如batch_norm,使用參數(shù)for_test來區(qū)分該程序是用來訓(xùn)練還是用來測(cè)試 #該api不會(huì)刪除任何操作符,請(qǐng)?jiān)赽ackward和optimization之前使用 test_program = fluid.default_main_program().clone(for_test=True)

4.3 設(shè)置優(yōu)化方法

這里選擇Adam優(yōu)化算法:

optimizer = fluid.optimizer.Adam(learning_rate=0.001) optimizer.minimize(avg_loss) print("optimizer is ready")

4.4 定義訓(xùn)練場(chǎng)所

# 使用CPU訓(xùn)練 use_cuda = False place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()#創(chuàng)建執(zhí)行器和保存路徑 exe = fluid.Executor(place) save_dirname="recognize_cat_inference.model"train_prompt = "Train cost" cost_ploter = Ploter(train_prompt)# 將訓(xùn)練過程繪圖表示 def event_handler_plot(ploter_title, step, cost):cost_ploter.append(ploter_title, step, cost)cost_ploter.plot()

還可以定義一個(gè)train_test()函數(shù),作用是:使用測(cè)試集數(shù)據(jù),來測(cè)試訓(xùn)練效果。

def train_test(train_test_program, train_test_feed, train_test_reader):# 將分類準(zhǔn)確率存儲(chǔ)在acc_set中acc_set = []# 將平均損失存儲(chǔ)在avg_loss_set中avg_loss_set = []# 將測(cè)試 reader yield 出的每一個(gè)數(shù)據(jù)傳入網(wǎng)絡(luò)中進(jìn)行訓(xùn)練for test_data in train_test_reader():acc_np, avg_loss_np = exe.run(program=train_test_program,feed=train_test_feed.feed(test_data),fetch_list=[acc, avg_loss])acc_set.append(float(acc_np))avg_loss_set.append(float(avg_loss_np))# get test acc and loss# 獲得測(cè)試數(shù)據(jù)上的準(zhǔn)確率和損失值acc_val_mean = np.array(acc_set).mean()avg_loss_val_mean = np.array(avg_loss_set).mean()# 返回平均損失值,平均準(zhǔn)確率return avg_loss_val_mean, acc_val_meanfeeder = fluid.DataFeeder(place=place, feed_list=[x, y]) exe.run(startup_program)

4.5設(shè)置訓(xùn)練主循環(huán)

構(gòu)建一個(gè)循環(huán)來進(jìn)行訓(xùn)練,直至訓(xùn)練完成,把模型保存到 params_dirname 。

exe.run(fluid.default_startup_program())PASS_NUM = 150 epochs = [epoch_id for epoch_id in range(PASS_NUM)]lists = []step = 0 for epoch_id in epochs:for step_id, data in enumerate(train_reader()):metrics = exe.run(main_program,feed=feeder.feed(data),fetch_list=[avg_loss,acc])#我們可以把訓(xùn)練結(jié)果打印輸出,也可以用畫圖展示出來if step % 10 == 0: #每訓(xùn)練10次,繪制一次曲線event_handler_plot(train_prompt, step, metrics[0])step += 1# 測(cè)試每個(gè)epoch的分類效果avg_loss_val, acc_val = train_test(train_test_program=test_program,train_test_reader=test_reader,train_test_feed=feeder)print("Test with Epoch %d, avg_cost: %s, acc: %s" %(epoch_id, avg_loss_val, acc_val))lists.append((epoch_id, avg_loss_val, acc_val))# 保存訓(xùn)練好的模型參數(shù)用于預(yù)測(cè) if save_dirname is not None:fluid.io.save_inference_model(save_dirname, ["x"], [y_predict], exe)# 選擇效果最好的pass best = sorted(lists, key=lambda list: float(list[1]))[0] print('Best pass is %s, testing Avgcost is %s' % (best[0], best[1])) print('The classification accuracy is %.2f%%' % (float(best[2]) * 100))


5 - 預(yù)測(cè)階段

#指定預(yù)測(cè)的作用域 inference_scope = fluid.core.Scope() with fluid.scope_guard(inference_scope):# 使用 fluid.io.load_inference_model 獲取 inference program,# feed_target_names 用于指定需要傳入網(wǎng)絡(luò)的變量名# fetch_targets 指定希望從網(wǎng)絡(luò)中fetch出的變量名[inference_program, feed_target_names,fetch_targets] = fluid.io.load_inference_model(save_dirname, exe)# 將feed構(gòu)建成字典 {feed_target_name: feed_target_data}# 結(jié)果將包含一個(gè)與fetch_targets對(duì)應(yīng)的數(shù)據(jù)列表# 我們可以實(shí)現(xiàn)批量預(yù)測(cè),通過一個(gè)循環(huán),每次預(yù)測(cè)一個(gè)mini_batchfor mini_batch in test_reader():test_x = np.array([data[0] for data in mini_batch]).astype("float32")test_y = np.array([data[1] for data in mini_batch]).astype("int64")# 真實(shí)進(jìn)行預(yù)測(cè)mini_batch_result = exe.run(inference_program,feed={feed_target_names[0]: test_x},fetch_list=fetch_targets)# 打印預(yù)測(cè)結(jié)果mini_batch_result = np.argsort(mini_batch_result) #找出可能性最大的列標(biāo),升序排列mini_batch_result = mini_batch_result[0][:, -1] #把這些列標(biāo)拿出來print('預(yù)測(cè)結(jié)果:%s'%mini_batch_result)# 打印真實(shí)結(jié)果 label = test_y # 轉(zhuǎn)化為 labelprint('真實(shí)結(jié)果:%s'%label)#計(jì)數(shù)label_len = len(label)right_counter = 0for i in range(label_len):if mini_batch_result[i] == label[i]:right_counter += 1ratio = (right_counter/label_len)print("準(zhǔn)確率為:%.2f%%"%(ratio*100)) 預(yù)測(cè)結(jié)果:[1 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 1 1 1 1 0 0 1 1 0 1 0 1 1 1 1 0] 真實(shí)結(jié)果:[0 1 1 1 0 1 1 0 0 0 0 1 0 1 0 1 1 1 1 0 1 0 1 1 1 0 1 1 1 1 1 0] 預(yù)測(cè)結(jié)果:[0 0 0 1 1 1 1 0 1 1 1 1 0 1 1 0 1 1] 真實(shí)結(jié)果:[1 1 0 1 1 0 1 0 1 1 1 1 0 1 1 0 1 1] 準(zhǔn)確率為:83.33%

6 - 總結(jié)

通過這個(gè)練習(xí)應(yīng)該記住:

至此Logistic回歸模型的訓(xùn)練工作完成,在使用PaddlePaddle進(jìn)行模型配置和訓(xùn)練的過程中不用考慮參數(shù)的初始化、成本函數(shù)、激活函數(shù)、梯度下降、參數(shù)更新和預(yù)測(cè)等具體細(xì)節(jié);只需要簡(jiǎn)單地配置網(wǎng)絡(luò)結(jié)構(gòu)和trainer即可,并且PaddlePaddle提供了許多接口來改變學(xué)習(xí)率、成本函數(shù)、批次大小等許多參數(shù)來改變模型的學(xué)習(xí)效果,使用起來更加靈活,方便測(cè)試,在之后的練習(xí)中,會(huì)對(duì)PaddlePaddle更加熟悉。

總結(jié)

以上是生活随笔為你收集整理的动手学PaddlePaddle(3):猫脸识别的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。