小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Tensorflow實(shí)現(xiàn)卷積神經(jīng)網(wǎng)絡(luò),用于人臉關(guān)鍵點(diǎn)識(shí)別

 印度阿三17 2019-08-07

今年來(lái)人工智能的概念越來(lái)越火,AlphaGo以4:1擊敗李世石更是起到推波助瀾的作用。作為一個(gè)開(kāi)挖掘機(jī)的菜鳥(niǎo),深深感到不學(xué)習(xí)一下deep learning早晚要被淘汰。

既然要開(kāi)始學(xué),當(dāng)然是搭一個(gè)深度神經(jīng)網(wǎng)絡(luò)跑幾個(gè)數(shù)據(jù)集感受一下作為入門(mén)最直觀了。自己寫(xiě)代碼實(shí)現(xiàn)的話(huà)debug的過(guò)程和運(yùn)行效率都會(huì)很憂(yōu)傷,我也不知道怎么調(diào)用GPU… 所以還是站在巨人的肩膀上,用現(xiàn)成的框架吧。粗略了解一下,現(xiàn)在比較知名的有caffe、mxnet、tensorflow等等。選哪個(gè)呢?對(duì)我來(lái)說(shuō)選擇的標(biāo)準(zhǔn)就兩個(gè),第一要容易安裝(想盡快入門(mén)的迫切心情實(shí)在難以忍受一大堆的配置安裝…);第二文檔要齊全(這應(yīng)該是廢話(huà) - -)。這幾個(gè)大名鼎鼎的框架文檔都是比較齊全的,那就看最容易安裝的??戳藥讉€(gè)文檔,tensorflow算是最容易安裝的了?;揪褪?code>pip intall 給定的URL就可以了。安裝方式的文檔可以在tensorflow安裝教程上查看。

tensorflow基本概念與用法

tensorflow直譯過(guò)來(lái)就是張量流。去年google剛推出tensorflow的時(shí)候我就納悶,為什么深度學(xué)習(xí)會(huì)牽扯到張量,以前學(xué)彈塑性力學(xué)的時(shí)候就是一大堆張量看的很煩…不過(guò)還好要理解tensorflow里的tensor完全不用理會(huì)那些。先來(lái)看一下官方文檔的說(shuō)明:

class tf.Tensor

Represents a value produced by an Operation.

A Tensor is a symbolic handle to one of the outputs of an Operation. It does not hold the values of that operation’s output, but instead provides a means of computing those values in a TensorFlow Session.

首先,Tensor代表了執(zhí)行一個(gè)操作(運(yùn)算)所產(chǎn)生的值。其次,一個(gè)Tensor實(shí)例并不會(huì)保存具體的值,而只是代表了產(chǎn)生這些值的運(yùn)算方式。好像有些拗口,也就是說(shuō)假如有一個(gè)加法操作add,令c = add(1,1)。那么c就是一個(gè)tensor實(shí)例了,代表了1 1的結(jié)果,但是它并沒(méi)有存儲(chǔ)2這個(gè)具體的值,它只知道它代表1 1這個(gè)運(yùn)算。從這里也可以看出,tensorflow里的api都是惰性求值,等真正需要知道具體的值的時(shí)候,才會(huì)執(zhí)行計(jì)算,其他時(shí)候都是在定義計(jì)算的過(guò)程。

Tensor可以代表從常數(shù)一直到N維數(shù)組的值。

Flow指的是,指的是tensorflow這套框架里的數(shù)據(jù)傳遞全部都是tensor,也就是運(yùn)算的輸入,輸出都是tensor。

如果你覺(jué)得這篇文章看起來(lái)稍微還有些吃力,或者想要系統(tǒng)地學(xué)習(xí)人工智能,那么推薦你去看床長(zhǎng)人工智能教程。非常棒的大神之作,教程不僅通俗易懂,而且很風(fēng)趣幽默。點(diǎn)擊這里可以查看教程。

常用操作

這里只是簡(jiǎn)單介紹一下在后面定義卷積神經(jīng)網(wǎng)絡(luò)的時(shí)候會(huì)用到的東西。想要了解更詳細(xì)的內(nèi)容還得參考官網(wǎng)上的文檔。

首先import tensorflow as tf,后面的tf就代表tensorflow啦。

常數(shù)

tf.constant 是一個(gè)Operation,用來(lái)產(chǎn)生常數(shù),可以產(chǎn)生scalar與N-D array. a是一個(gè)tensor,代表了由constant這個(gè)Operation所產(chǎn)生的標(biāo)量常數(shù)值的過(guò)程。 b就是代表了產(chǎn)生一個(gè)2*2的array的過(guò)程。

a = tf.constant(3)b = tf.constant(3,shape=[2,2])  
  • 1
  • 2

變量

變量代表了神經(jīng)網(wǎng)絡(luò)中的參數(shù),在優(yōu)化計(jì)算的過(guò)程中需要被改變。tf.Variable當(dāng)然也是一個(gè)Operation,用來(lái)產(chǎn)生一個(gè)變量,構(gòu)造函數(shù)需要傳入一個(gè)Tensor對(duì)象,傳入的這個(gè)Tensor對(duì)象就決定了這個(gè)變量的值的類(lèi)型(float 或 int)與shape。

變量雖然與Tensor有不同的類(lèi)型,但是在計(jì)算過(guò)程中是與Tensor一樣可以作為輸入輸出的。(可以理解為T(mén)ensor的派生類(lèi),但是實(shí)際上可能并不是這樣,我還沒(méi)有看源碼)

變量在使用前都必須初始化。

w = tf.Variable(b)
  • 1

Operation

其實(shí)Operation不應(yīng)該單獨(dú)拿出來(lái)說(shuō),因?yàn)橹暗膖f.constant和tf.Variable都是Op,不過(guò)還是說(shuō)一下常規(guī)的操作,比如tf.matmul執(zhí)行矩陣計(jì)算,tf.conv2d用于卷積計(jì)算,Op的詳細(xì)用法以及其他的Op可以參考api文檔。

tf.matmul(m,n)tf.conv2d(...)
  • 1
  • 2

TensorFlow的計(jì)算由不同的Operation組成,比如下圖
這里寫(xiě)圖片描述

定義了6*(3 5)這個(gè)計(jì)算過(guò)程。6、3、5其實(shí)也是Op,這在前面介紹過(guò)了。

卷積神經(jīng)網(wǎng)絡(luò)用于人臉關(guān)鍵點(diǎn)識(shí)別

寫(xiě)到這里終于要開(kāi)始進(jìn)入正題了,先從CNN做起吧。Tensorflow的tutorial里面有介紹用CNN(卷積神經(jīng)網(wǎng)絡(luò))來(lái)識(shí)別手寫(xiě)數(shù)字,直接把那里的代碼copy下來(lái)跑一遍也是可以的。但是那比較沒(méi)有意思,kaggle上有一個(gè)人臉關(guān)鍵點(diǎn)識(shí)別的比賽,有數(shù)據(jù)集也比較有意思,就拿這個(gè)來(lái)練手了。

定義卷積神經(jīng)網(wǎng)絡(luò)

首先是定義網(wǎng)絡(luò)結(jié)構(gòu),在這個(gè)例子里我用了3個(gè)卷積層,第一個(gè)卷積層用3?33?3的max_pool。參數(shù)ksize定義pool窗口的大小,每個(gè)維度的意義與之前的strides相同,所以實(shí)際上我們?cè)O(shè)置第二個(gè),第三個(gè)維度就可以了。

def max_pool_2x2(x):    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1], padding='SAME')
  • 1
  • 2

定義好產(chǎn)生權(quán)重、卷積、池化的函數(shù)以后就要開(kāi)始組裝這個(gè)卷積神經(jīng)網(wǎng)絡(luò)了。定義之前再定義一下輸入樣本x與對(duì)應(yīng)的目標(biāo)值y_。這里用了tf.placeholder表示此時(shí)的xy_是指定shape的站位符,之后在定義網(wǎng)絡(luò)結(jié)構(gòu)的時(shí)候并不需要真的輸入了具體的樣本,只要在求值的時(shí)候feed進(jìn)去就可以了。激活函數(shù)用relu,api也就是tf.nn.relu。
keep_prob是最后dropout的參數(shù),dropout的目的是為了抗過(guò)擬合。

rmse是損失函數(shù),因?yàn)檫@里的目的是為了檢測(cè)人臉關(guān)鍵點(diǎn)的位置,是回歸問(wèn)題,所以用root-mean-square-error。并且最后的輸出層不需要套softmax,直接輸出y值就可以了。

這樣就組裝好了一個(gè)卷積神經(jīng)網(wǎng)絡(luò)。后續(xù)的步驟就是根據(jù)輸入樣本來(lái)train這些參數(shù)啦。

    x = tf.placeholder("float", shape=[None, 96, 96, 1])    y_ = tf.placeholder("float", shape=[None, 30])    keep_prob = tf.placeholder("float")    def model():        W_conv1 = weight_variable([3, 3, 1, 32])        b_conv1 = bias_variable([32])        h_conv1 = tf.nn.relu(conv2d(x, W_conv1)   b_conv1)        h_pool1 = max_pool_2x2(h_conv1)        W_conv2 = weight_variable([2, 2, 32, 64])        b_conv2 = bias_variable([64])        h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2)   b_conv2)        h_pool2 = max_pool_2x2(h_conv2)        W_conv3 = weight_variable([2, 2, 64, 128])        b_conv3 = bias_variable([128])        h_conv3 = tf.nn.relu(conv2d(h_pool2, W_conv3)   b_conv3)        h_pool3 = max_pool_2x2(h_conv3)        W_fc1 = weight_variable([11 * 11 * 128, 500])        b_fc1 = bias_variable([500])        h_pool3_flat = tf.reshape(h_pool3, [-1, 11 * 11 * 128])        h_fc1 = tf.nn.relu(tf.matmul(h_pool3_flat, W_fc1)   b_fc1)        W_fc2 = weight_variable([500, 500])        b_fc2 = bias_variable([500])        h_fc2 = tf.nn.relu(tf.matmul(h_fc1, W_fc2)   b_fc2)        h_fc2_drop = tf.nn.dropout(h_fc2, keep_prob)        W_fc3 = weight_variable([500, 30])        b_fc3 = bias_variable([30])        y_conv = tf.matmul(h_fc2_drop, W_fc3)   b_fc3        rmse = tf.sqrt(tf.reduce_mean(tf.square(y_ - y_conv)))        return y_conv, rmse
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

訓(xùn)練卷積神經(jīng)網(wǎng)絡(luò)

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

定義好卷積神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)之后,就要開(kāi)始訓(xùn)練。訓(xùn)練首先是要讀取訓(xùn)練樣本。下面的代碼用于讀取樣本。

    import pandas as pd    import numpy as np    TRAIN_FILE = 'training.csv'    TEST_FILE = 'test.csv'    SAVE_PATH = 'model'    VALIDATION_SIZE = 100    #驗(yàn)證集大小    EPOCHS = 100             #迭代次數(shù)    BATCH_SIZE = 64          #每個(gè)batch大小,稍微大一點(diǎn)的batch會(huì)更穩(wěn)定    EARLY_STOP_PATIENCE = 10 #控制early stopping的參數(shù)    def input_data(test=False):        file_name = TEST_FILE if test else TRAIN_FILE        df = pd.read_csv(file_name)        cols = df.columns[:-1]        #dropna()是丟棄有缺失數(shù)據(jù)的樣本,這樣最后7000多個(gè)樣本只剩2140個(gè)可用的。        df = df.dropna()            df['Image'] = df['Image'].apply(lambda img: np.fromstring(img, sep=' ') / 255.0)        X = np.vstack(df['Image'])        X = X.reshape((-1,96,96,1))        if test:            y = None        else:            y = df[cols].values / 96.0       #將y值縮放到[0,1]區(qū)間        return X, y    #最后生成提交結(jié)果的時(shí)候要用到    keypoint_index = {        'left_eye_center_x':0,        'left_eye_center_y':1,        'right_eye_center_x':2,        'right_eye_center_y':3,        'left_eye_inner_corner_x':4,        'left_eye_inner_corner_y':5,        'left_eye_outer_corner_x':6,        'left_eye_outer_corner_y':7,        'right_eye_inner_corner_x':8,        'right_eye_inner_corner_y':9,        'right_eye_outer_corner_x':10,        'right_eye_outer_corner_y':11,        'left_eyebrow_inner_end_x':12,        'left_eyebrow_inner_end_y':13,        'left_eyebrow_outer_end_x':14,        'left_eyebrow_outer_end_y':15,        'right_eyebrow_inner_end_x':16,        'right_eyebrow_inner_end_y':17,        'right_eyebrow_outer_end_x':18,        'right_eyebrow_outer_end_y':19,        'nose_tip_x':20,        'nose_tip_y':21,        'mouth_left_corner_x':22,        'mouth_left_corner_y':23,        'mouth_right_corner_x':24,        'mouth_right_corner_y':25,        'mouth_center_top_lip_x':26,        'mouth_center_top_lip_y':27,        'mouth_center_bottom_lip_x':28,        'mouth_center_bottom_lip_y':29    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

開(kāi)始訓(xùn)練

執(zhí)行訓(xùn)練的代碼如下,save_model用于保存當(dāng)前訓(xùn)練得到在驗(yàn)證集上loss最小的模型,方便以后直接拿來(lái)用。

tf.InteractiveSession()用來(lái)生成一個(gè)Session,(好像是廢話(huà)…)。Session相當(dāng)于一個(gè)引擎,TensorFlow框架要真正的進(jìn)行計(jì)算,都要通過(guò)Session引擎來(lái)啟動(dòng)。

tf.train.AdamOptimizer是優(yōu)化的算法,Adam的收斂速度會(huì)比較快,1e-3是learning rate,這里先簡(jiǎn)單的用固定的。minimize就是要最小化的目標(biāo),當(dāng)然是最小化均方根誤差了。

    def save_model(saver,sess,save_path):        path = saver.save(sess, save_path)        print 'model save in :{0}'.format(path)    if __name__ == '__main__':        sess = tf.InteractiveSession()        y_conv, rmse = model()        train_step = tf.train.AdamOptimizer(1e-3).minimize(rmse)        #變量都要初始化         sess.run(tf.initialize_all_variables())        X,y = input_data()        X_valid, y_valid = X[:VALIDATION_SIZE], y[:VALIDATION_SIZE]        X_train, y_train = X[VALIDATION_SIZE:], y[VALIDATION_SIZE:]        best_validation_loss = 1000000.0        current_epoch = 0        TRAIN_SIZE = X_train.shape[0]        train_index = range(TRAIN_SIZE)        random.shuffle(train_index)        X_train, y_train = X_train[train_index], y_train[train_index]        saver = tf.train.Saver()        print 'begin training..., train dataset size:{0}'.format(TRAIN_SIZE)        for i in xrange(EPOCHS):            random.shuffle(train_index)  #每個(gè)epoch都shuffle一下效果更好            X_train, y_train = X_train[train_index], y_train[train_index]            for j in xrange(0,TRAIN_SIZE,BATCH_SIZE):                print 'epoch {0}, train {1} samples done...'.format(i,j)                train_step.run(feed_dict={x:X_train[j:j BATCH_SIZE],                     y_:y_train[j:j BATCH_SIZE], keep_prob:0.5})            #電腦太渣,用所有訓(xùn)練樣本計(jì)算train_loss居然死機(jī),只好注釋了。            #train_loss = rmse.eval(feed_dict={x:X_train, y_:y_train, keep_prob: 1.0})            validation_loss = rmse.eval(feed_dict={x:X_valid, y_:y_valid, keep_prob: 1.0})            print 'epoch {0} done! validation loss:{1}'.format(i, validation_loss*96.0)            if validation_loss < best_validation_loss:                best_validation_loss = validation_loss                current_epoch = i                save_model(saver,sess,SAVE_PATH)   #即時(shí)保存最好的結(jié)果            elif (i - current_epoch) >= EARLY_STOP_PATIENCE:                print 'early stopping'                break
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

在測(cè)試集上預(yù)測(cè)

下面的代碼用于預(yù)測(cè)test.csv里面的人臉關(guān)鍵點(diǎn),最后的y值要乘以96,因?yàn)橹翱s放到[0,1]區(qū)間了。

    X,y = input_data(test=True)    y_pred = []    TEST_SIZE = X.shape[0]    for j in xrange(0,TEST_SIZE,BATCH_SIZE):        y_batch = y_conv.eval(feed_dict={x:X[j:j BATCH_SIZE], keep_prob:1.0})        y_pred.extend(y_batch)    print 'predict test image done!'    output_file = open('submit.csv','w')    output_file.write('RowId,Location\n')    IdLookupTable = open('IdLookupTable.csv')    IdLookupTable.readline()    for line in IdLookupTable:        RowId,ImageId,FeatureName = line.rstrip().split(',')        image_index = int(ImageId) - 1        feature_index = keypoint_index[FeatureName]        feature_location = y_pred[image_index][feature_index] * 96        output_file.write('{0},{1}\n'.format(RowId,feature_location))    output_file.close()    IdLookupTable.close()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

結(jié)果

用這個(gè)結(jié)構(gòu)的卷積神經(jīng)網(wǎng)絡(luò)訓(xùn)練出來(lái)的模型,在測(cè)試集上預(yù)測(cè)的結(jié)果提交以后的成績(jī)是3.4144,在kaggle的leaderboard上是41名,初試CNN,感覺(jué)還可以了。這只是數(shù)據(jù),還是找一些現(xiàn)實(shí)的照片來(lái)試試這個(gè)模型如何,所以我找了一張anglababy的,標(biāo)識(shí)出來(lái)的關(guān)鍵點(diǎn)感覺(jué)還算靠譜。基于TensorFlow的卷積神經(jīng)網(wǎng)絡(luò)先寫(xiě)到這了,有什么遺漏的想起來(lái)再補(bǔ)充,之后對(duì)深度學(xué)習(xí)更了解了,再寫(xiě)寫(xiě)CNN的原理,bp的推導(dǎo)過(guò)程之類(lèi)的。

這里寫(xiě)圖片描述

來(lái)源:https://www./content-4-380601.html

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多