深度學習原理與框架-Tensorflow卷積神經網絡-cifar10圖片分類(代碼) 1.tf.nn.lrn(局部響應歸一化操作) 2.random.sample(在列表中隨機選值) 3.tf.one_hot(對標簽進行one_hot編碼)


1.tf.nn.lrn(pool_h1, 4, bias=1.0, alpha=0.001/9.0, beta=0.75) # 局部響應歸一化,使用相同位置的前后的filter進行響應歸一化操作

參數說明:pool_h1表示輸入數據,4表示使用前后幾層進行歸一化操作,bias表示偏移量,alpha和beta表示系數

 

          局部響應的公式 

針對上述公式,做了一個試驗代碼:

# 自己編寫的代碼, 對x的[1, 1, 1, 1]進行局部響應歸一化操作,最后結果是相同的
x = np.array([i for i in range(1, 33)]).reshape([2, 2, 2, 4]) sqr_sum = np.zeros_like(x) sqr_sum[1, 1, 1, 1] = sum(x[1, 1, 1, 0:3] ** 2) print(sqr_sum[1, 1, 1, 1]) z = (x[1, 1, 1, 1] / (0 + sqr_sum[1, 1, 1, 1]*1)) ** 1 print(z)
# 調用的代碼 sess
= tf.Session() y = tf.nn.lrn(input=x, depth_radius=1, bias=0, alpha=1, beta=1) print(sess.run(y[1, 1, 1, 1]))

2.random.sample(np.arange(N), cols*rows) # 從列表n中,挑選出cols*rows個數據

參數說明:np.arange(N) 表示列表,cols*rows表示挑選的數字個數

3.tf.one_hot(X, len(names), axis=-1) # 將一維標簽轉換為one-hot類型

參數說明:X表示輸入的一維標簽,len(names)表示一個數字變成多少個維度,axis表示所在的位置

 

使用Tensorflow卷積神經網絡對cifar10進行分類

數據說明:cifar數據是由data :50000*3072, labels=3072個橫向量組成,類別名為['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']

在下面的操作中,需要使用tf,one_hot(labels, len(names), axis=-1) # 將標簽轉換為one-hot的編碼類型

代碼說明:

代碼由三部分組成:第一部分,數據的讀入和裁剪以及標准化處理

                                第二部分:對W和卷積過程中的卷積結果進行展示

                                第三部分:對圖像卷積參數進行訓練

 

第一部分:模型的讀入和裁剪以及標准化操作

第一步:構建unpickle函數進行數據的讀入

第二步:構建clean函數,

               第一步:改變矩陣的維度為[-1, 3, 32, 32]

               第二步:.mean(1)  對3這個通道求平均值,表示對圖像進行灰度化處理,即RGB三個通道求平均

               第三步:使用[:, 4:28, 4:28] 對圖像進行裁剪

               第四步:.reshape([(len(), -1)]) 將圖像轉換為二維矩陣

               第五步:使用np.mean() 計算圖像的平均值, 並使用.reshape([len(), 1]) 對維度進行重構

               第六步:使用np.std計算圖像的標准差,並使用.reshape([len(), 1]) 對維度進行重構,對於一些標准差較大的值,使用1/sqrt(len()) 代替

               第七步:對圖像減去均值除以標准差來進行標准化操作

第三步:數據的讀入

              第一步:讀入標簽的名字

              第二步:循環,讀取data和labels,將每次讀取的data,使用np.vstack進行豎着串接,對於labels使用np.hstack進行橫着串接

               第三步:使用clean來對數據做預處理,.astype轉換數據的類型

               第四步:返回名字,data和labels

第四步:隨機的圖片展示

              第一步:定義rows和cols的大小

              第二步:使用random.sample(np.arange(N), rows*cols) 從數組中隨機挑選rows*cols個數作為索引值

              第三步:循環,plt.subplot構造子圖,plt.title(name[label[randix[i]]]) 構造題目

              第四步:對圖像進行維度變化,使用plt.imshow()進行作圖操作

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
import pickle
import random

# 設置隨機種子
random.seed(1)

# 第一步:構造unpick用於讀取數據
def unpickle(filename):
    # 打開文件,二進制格式
    f = open(filename, 'rb')
    # 文件的載入,編碼方式為'latin1'
    out = pickle.load(f, encoding='latin1')
    f.close()
    return out
# 第二步:對圖片進行預處理,灰度化,裁剪,標准化
def clean(data):
    # 圖像的維度轉換
    data_reshaped = data.reshape(-1, 3, 32, 32)
    # 進行灰度化處理
    gray_img = data_reshaped.mean(1)
    # 對圖像進行裁剪
    gray_img_crop = gray_img[:, 4:28, 4:28]
    # 將圖像的維度轉換為原來的二維數據
    gray_img_crop = gray_img_crop.reshape([len(gray_img_crop), -1])
    # 求得圖像的均值
    mean = np.mean(gray_img_crop, axis=1)
    # 將均值的維度轉換為2維,以便用於后續的相減操作
    meanT = mean.reshape([len(mean), 1])
    # 求得圖像的標准差
    std = np.std(gray_img_crop, axis=1)
    # 將標准差轉換為2維形式
    stdT = std.reshape([len(std), 1])
    # 如果標准差過大,使用1/np.sqrt(len(stdT)代替)
    adj_std = np.maximum(stdT, 1/np.sqrt(len(stdT)))
    # 進行標准化操作
    normalize = (gray_img_crop - meanT) / adj_std

    return normalize


# 第三步:數據的載入
def load_data(filename):
    # 數據標簽名的讀入
    names = unpickle('{}/batches.meta'.format(filename))['label_names']
    data = []
    labels = []
    for i in range(1, 6):
        # 循環讀取,每一個文件的數據和標簽名
        data_dict = unpickle('{}/data_batch_{}'.format(filename, i))
        if len(data) > 0 :
            # 對數據進行豎着串接
            data = np.vstack((data, data_dict['data']))
            # 對標簽進行橫着串接
            labels = np.hstack((labels, data_dict['labels']))
        else:
            data = data_dict['data']
            labels = data_dict['labels']
    # 對數據進行預處理操作
    data = clean(data)
    # 將數據的類型轉換為np.float32
    data = data.astype(np.float32)
    # 返回標簽名,數據,標簽
    return names, data, labels

names, data, labels = load_data('./cifar-10-batches-py')
print(names)
# 第四步:進行圖像的隨機展示
def show_random_img(names, data, labels):
    # 數據的大小
    N = data.shape[0]
    # 橫和列的個數
    rows, cols = 4, 8
    # 從N個數據列表中,隨機挑選4*8個數據的索引值
    randix = random.sample(range(N), rows*cols)
    plt.figure()
    for i in range(rows * cols):
        # 循環,構造每一個圖的子圖
        plt.subplot(rows, cols, i+1)
        # 獲得單個的索引值
        j = randix[i]
        # 文章名 ,使用標簽對應的類別名
        plt.title(names[labels[j]])
        # 圖像的維度轉換
        img = data[j,:].reshape([24, 24])
        # 圖片的展示
        plt.imshow(img, cmap='Greys_r')
        plt.axis('off')
    plt.tight_layout()
    plt.show()

show_random_img(names, data, labels)

第二部分:選擇一張圖片,作為輸入數據,對卷積過程中的W,conv,pool分別進行展示

第一步:選擇一張圖片,進行維度的變化,使用plt.imshow() 進行圖像的展示

第二步:構造初始參數

                第一步:使用tf.reshape[row_img, [-1, 24, 24, 1]] 對x進行維度的變化

                第二步:構造W和b,同時對x進行卷積,激活和池化操作

                第三步:構造展示卷積層的函數,構造cols和rows進行子圖展示,循環通道數,展示第一張圖片的第i個通道的圖片

                第四步:構造展示W參數的函數,構造cols和rows進行子圖展示,循環filter數,展示第一個通道的第i個filter的圖片

                 第五步:構造執行函數sess,使用sess.run()獲得數組,調用函數進行展示

# 第二部分:進行卷積過程中的圖像展示
# 第一步:隨機選擇一張圖,進行卷積圖和參數圖的演示
row_img = data[4,:]
# 圖像維度的變化
row_img = row_img.reshape([24, 24])
plt.figure()
plt.imshow(row_img, cmap='Greys_r')
plt.show()
# 第二步:將圖片進行維度變換,構造參數,並進行卷積,激活和池化操作
x = tf.reshape(row_img, shape=[-1, 24, 24, 1])
# 卷積的維度為[5, 5, 1, 32] 5和5表示維度,1表示通道數,32表示filter個數
W1 = tf.Variable(tf.random_normal([5, 5, 1, 32]))
# 構造b1參數,維度為[32]
b1 = tf.Variable(tf.random_normal([32]))
# 進行一次卷積操作,strides表示步長
conv = tf.nn.conv2d(x, W1, strides=[1, 1, 1, 1], padding='SAME')
# 加上偏置項b
conv_with_b = tf.add(conv, b1)
# 使用激活函數進行激活
conv_out = tf.nn.relu(conv_with_b)

# 池化操作
k = 2
max_pool = tf.nn.max_pool(conv_out, ksize=[1, k, k, 1], strides=[1, k, k, 1], padding='SAME')

# 第三步:構造函數,進行卷積過程中的圖像展示
def show_conv_img(conv_out, filename=None):
    # rows,cols的大小
    rows, cols = 4, 8
    # 循環,卷積圖像的通道數
    for i in range(conv_out.shape[3]):
        # 選擇第一個圖像的i通道
        img = conv_out[0, :, :, i]
        # 構造子圖
        plt.subplot(rows, cols, i+1)
        # 圖像的展示
        plt.imshow(img, cmap='Greys_r')
        # 關閉坐標軸
        plt.axis('off')
    # 圖像更窄的顯示    
    plt.tight_layout()
    if filename:
        plt.savefig(filename)
    else:
        plt.show()

# 第四步:進行W參數的展示
def show_W(W, filename=None):
    # rows,cols的表示
    rows, cols = 4, 8
    plt.figure()
    # 循環W的filter個數
    for i in range(W.shape[3]):
        # 圖片表示為第1個通道的i個filter
        img = W[:, :, 0, i]
        # 構造子圖
        plt.subplot(rows, cols, i+1)
        plt.imshow(img, cmap='Greys_r')
        plt.axis('off')
    plt.tight_layout()

    if filename:
        plt.savefig(filename)
    else:
        plt.show()
# 第五步:進行卷積圖像和w的展示
with tf.Session() as sess:
    # 變量的初始化操作
    sess.run(tf.global_variables_initializer())
    # 將tf數據類型轉換為數組類型,用於展示, 卷積層的展示
    conv_val = sess.run(conv)
    print('conv:')
    show_conv_img(conv_val)
    # W1參數的展示
    W_val = sess.run(W1)
    print('w:')
    show_W(W_val)
    # 卷積+激活后的圖像展示
    conv_out_val = sess.run(conv_out)
    print('conv_out')
    show_conv_img(conv_out_val)
    # 池化后的圖像展示
    pool_val = sess.run(max_pool)
    print('pool')
    show_conv_img(pool_val)

      

            原始圖像                              w參數                                           第一次卷積                                   激活后                                         池化后 

 

第三部分:進行正式的圖像的訓練操作

第一步:使用tf.placeholder(tf.float32, shape=[None, 24*24])  tf.placeholder(tf.float32, shape=[None, len(names)]) # 構造x和y 

第二步:構造卷積層和全連接層的參數

              第一層卷積:  w:5,5,1,64 b:64 

              第二層卷積:  w: 5,5,64.64 b:64 

              第三層全連接:  w: 6*6*64, 1024 b:1024

              第四層全連接:  w:1024,len(names) b:len(names)

第三步:構造conv函數:用於進行卷積,激活操作

第四步:構造pool函數:用於進行最大值池化操作

第五步:構造model函數:進行卷積和全連接操作

               第一步:使用tf.reshape(x, [None, 28, 28, 1]) 進行矩陣的維度變化

               第二步:進行第一次卷積和池化操作

               第三步:使用tf.nn.lrn對數據進行局部最大值響應

               第四步:進行第二次卷積操作

               第五步:使用tf.nn.lrn對數據進行局部最大值響應

               第六步:進行第二次池化操作

               第七步:改變池化后的矩陣的維度,為[-1, 6*6*64],進行第一次全連接操作

               第八步:進行第二次全連接操作

第六步:將返回的model_op得分,使用tf.reduce_mean(tf.nn.softmax) 構造softmax的損失函數

第七步: 使用tf.nn.Adaoptimer() 自適應梯度下降來進行損失值得降低

第八步:使用tf.equal() 和 tf.reduce_mean 計算accur

第九步:構造sess執行函數,並進行初始化操作

第十步:使用tf.one_hot將標簽轉換為one_hot格式,並使用sess.run將tf格式的標簽重新轉換為數組格式

第十一步:進入循環,設置batch的大小,以及平均准確率為0 

第十二步:使用np.arange(0, len(data), batch_size) 進行一個batch的循環,使用data_batch = data[j:j+batch, :] 獲得一個batch的數據,同理獲得一個標簽的數據

第十三步:將batch數據帶入到sess.run([opt, accr]) 進行梯度下降和准確率的計算,

第十四步:計算平均准確率,並打印

#第三部分: 開始進行正式的模型訓練
# 第一步:使用tf.placeholder()進行輸入數據的初始化
x = tf.placeholder(tf.float32, [None, 24*24])
y = tf.placeholder(tf.float32, [None, len(names)])

# 第二步:構造卷積和全連接的參數
# W1的維度為5,5,1, 64
W1 = tf.Variable(tf.random_normal([5, 5, 1, 64]))
# b1的維度為64
b1 = tf.Variable(tf.random_normal([64]))
# W2的維度為5,5,64,64
W2 = tf.Variable(tf.random_normal([5, 5, 64, 64]))
# b2的維度為64
b2 = tf.Variable(tf.random_normal([64]))
# W3的維度為6*6*64, 1024
W3 = tf.Variable(tf.random_normal([6*6*64, 1024]))
# b3的維度為64
b3 = tf.Variable(tf.random_normal([1024]))
# W_out的維度為1024,10
W_out = tf.Variable(tf.random_normal([1024, len(names)]))
# b_out的維度為10
b_out = tf.Variable(tf.random_normal([len(names)]))
# 第三步:構建卷積和激活層的函數
def conv(x, w, b):

    return tf.nn.relu(tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding='SAME') + b)
# 第四步:構建池化層的函數
def pool(x, k=2):

    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
# 第五步:構建模型,進行卷積和全連接的操作
def model():
    # 進行輸入x的維度變換,以便進行后續的卷積操作
    x_reshapedd = tf.reshape(x, shape=[-1, 24, 24, 1])
    # 進行卷積操作
    conv_h1 = conv(x_reshapedd, W1, b1)
    # 進行池化操作
    pool_h1 = pool(conv_h1)
    # 進行非極大值抑制操作
    norm1 = tf.nn.lrn(pool_h1, 4, bias=1.0, alpha=0.001/9.0, beta=0.75)
    # 進行第二次卷積操作
    conv_h2 = conv(norm1, W2, b2)
    # 進行非極大值抑制操作
    norm2 = tf.nn.lrn(conv_h2, 4, bias=1.0, alpha=0.001/9.0, beta=0.75)
    # 進行池化操作
    pool_h2 = pool(norm2)
    # 重構池化層后的矩陣維度,為了進行全連接操作
    fc1_input = tf.reshape(pool_h2, [-1, 6*6*64])
    # 進行第一次全連接操作
    fc_h1 = tf.nn.relu(tf.matmul(fc1_input, W3) + b3)
    # 進行第二次全連接操作
    fc_out = tf.matmul(fc_h1, W_out) + b_out

    return fc_out
# 第六步:獲得得分,使用tf.nn.softmax_cross獲得softmax的損失值
model_op = model()
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=model_op, labels=y))
# 第七步:使用自適應損失值優化器,進行損失值的下降
train_op = tf.train.AdamOptimizer(0.001).minimize(cost)
# 第八步:使用tf.equal和tf.reduce_mean求出准確度
correct_pred = tf.equal(tf.argmax(model_op, 1), tf.argmax(y, 1))
accur = tf.reduce_mean(tf.cast(correct_pred, 'float'))

batch_size = 50
# 第九步:構造sess,並進行初始化
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    # 第十步:對標簽使用one-hot編碼,並使用sess.run()轉換回數據類型
    train_labels = tf.one_hot(labels, len(names), axis=-1)
    train_labels = sess.run(train_labels)
    for j in range(1000):
        # 第十一步:設置batchsize大小,即average的平均值為0
        average = 0
        batch_num = 0
        for i in range(0, len(data), batch_size):
            # 第十二步:使用data[i:i+batch_size, :] 獲得batch數據和batch標簽值
            train_data = data[i:i+batch_size, :]
            train_label = train_labels[i:i+batch_size, :]
            # 第十三步:將batch數據和標簽值帶入,用於進行損失值的降低和准確率的計算
            _, accurracy = sess.run([train_op, accur], feed_dict={x:train_data, y:train_label})
            average += accurracy
            batch_num += 1
        # 第十四步:求出平均准確率並打印    
        average /= batch_num
        print('epoch average accurracy %g'%(average, ))

                           迭代的結果

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM