20155219付穎卓畢業設計-代碼理解

選擇攻擊在ImageNet數據集上訓練的Inception v3網絡。首先咱們從TF-slim圖像分類庫中加載預先訓練的網絡。

import tensorflow as tf
import tensorflow.contrib.slim as slim
import tensorflow.contrib.slim.nets as nets

tf.logging.set_verbosity(tf.logging.ERROR)
sess = tf.InteractiveSession()

加載預設部分git

設置輸入圖像。使用tf.Variable而不是使用tf.placeholder,這是由於要確保它是可訓練的。當咱們須要時,仍然能夠輸入它。

image = tf.Variable(tf.zeros((299, 299, 3)))

height = 299 width = 299 channels = 3,這是Inception v3模型規定的圖片大小json

接下來,加載Inception v3模型

def inception(image, reuse):
    preprocessed = tf.multiply(tf.subtract(tf.expand_dims(image, 0), 0.5), 2.0)
    arg_scope = nets.inception.inception_v3_arg_scope(weight_decay=0.0)
    with slim.arg_scope(arg_scope):                             #  slim是一種輕量級的tensorflow庫,可使模型的構建,訓練,測試都變得更加簡單。
                                                                #在slim庫中對不少經常使用的函數進行了定義,slim.arg_scope()是slim庫中常常用到的函數之一。
                                                                #定義inception-v3模型結構 inception_v3.ckpt裏只有參數的取值
        logits, _ = nets.inception.inception_v3(                #logits  inception_v3前向傳播獲得的結果
            preprocessed, 1001, is_training=False, reuse=reuse)
        logits = logits[:,1:]                                   # 忽略背景類的影響
        probs = tf.nn.softmax(logits)                           # logits就是神經網絡的輸出 ,轉換到softmax函數以後輸出結果
        
                                                                #用 slim.arg_scope()爲目標函數設置默認參數.
    return logits, probs
    logits, probs = inception(image, reuse=False)

接下來,加載預訓練的權重。從文獻中看到這個Inception v3的top-5的準確率爲93.9%

import tempfile
from urllib.request import urlretrieve
import tarfile
import os
data_dir = tempfile.mkdtemp()
inception_tarball, _ = urlretrieve(
    'http://download.tensorflow.org/models/inception_v3_2016_08_28.tar.gz')
tarfile.open(inception_tarball, 'r:gz').extractall(data_dir)
restore_vars = [
    var for var in tf.global_variables()
    if var.name.startswith('InceptionV3/')
]#使用ckpt文件中提供的參數
saver = tf.train.Saver(restore_vars)
saver.restore(sess, os.path.join(data_dir, 'inception_v3.ckpt'))

#saver()與restore()只是保存了session中的相關變量對應的值,並不涉及模型的結構。
#sess: 保存參數的會話。
#save_path: 保存參數的路徑。
#當從文件中恢復變量時,不須要事先對他們進行初始化,由於「恢復」自身就是一種初始化變量的方法。
#可使用tf.train.latest_checkpoint()來自動獲取最後一次保存的模型。


#**Saver的做用是將咱們訓練好的模型的參數保存下來,以便下一次繼續用於訓練或測試;Restore則是將訓練好的參數提取出來。Saver類訓練完後,是以checkpoints文件形式保存。提取的時候也是從checkpoints文件中恢復變量。Checkpoints文件是一個二進制文件,它把變量名映射到對應的tensor值 。

接下來,編寫一些代碼來顯示圖像,並對它進行分類及顯示分類結果。

import json
import matplotlib.pyplot as plt
imagenet_json, _ = urlretrieve(
    'http://www.anishathalye.com/media/2017/07/25/imagenet.json')
with open(imagenet_json) as f:
    imagenet_labels = json.load(f)#引入圖像的不一樣類別,json文件中保存着inception v3模型訓練的不一樣結果
def classify(img, correct_class=None, target_class=None):
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 8))#創建一個fig對象,創建兩個axis對象(返回它的子圖對象)如,設置 figsize=(21, 12) ,則設置了圖像大小。
    fig.sca(ax1)#畫函數圖像
    p = sess.run(probs, feed_dict={image: img})[0]
    ax1.imshow(img) #進行圖形的分辨
    fig.sca(ax1)
    
    topk = list(p.argsort()[-10:][::-1])
    topprobs = p[topk]
    barlist = ax2.bar(range(10), topprobs)
    if target_class in topk:
        barlist[topk.index(target_class)].set_color('r')
    if correct_class in topk:
        barlist[topk.index(correct_class)].set_color('g')
    plt.sca(ax2)
    plt.ylim([0, 1.1])
    plt.xticks(range(10),
               [imagenet_labels[i][:15] for i in topk],
               rotation='vertical')
    fig.subplots_adjust(bottom=0.2)
    plt.show()
#造成柱狀圖

plt.subplots函數的標註效果:網絡

image

加載示例圖像,並確保它已被正確分類。

import PIL
import numpy as np
img_path, _ = urlretrieve('http://www.anishathalye.com/media/2017/07/25/cat.jpg')
img_class = 281
img = PIL.Image.open(img_path)
big_dim = max(img.width, img.height)
wide = img.width > img.height
new_w = 299 if not wide else int(img.width * 299 / img.height)
new_h = 299 if wide else int(img.height * 299 / img.width)
img = img.resize((new_w, new_h)).crop((0, 0, 299, 299))
img = (np.asarray(img) / 255.0).astype(np.float32)

#對圖像的大小以及格式進行調整,造成適應inception v3模型的格式及大小
classify(img, correct_class=img_class)

輸出結果以下:
imagesession

生成fgsm對抗樣本

給定一個圖像X,神經網絡輸出標籤上的機率分佈爲P(y|X)。當手工製做對抗輸入時,咱們想要找到一個X',使得logP(y'|X')被最大化爲目標標籤y',即輸入將被錯誤分類爲目標類。經過進行約束,要求‖X- X'‖≤ε,咱們能夠確保X'與原始X看起來同樣,但實際卻能夠達成擾亂效果。ide

首先從最簡單的部分開始:編寫一個TensorFlow op進行相應的初始化。

x = tf.placeholder(tf.float32, (299, 299, 3))

x_hat = image 
assign_op = tf.assign(x_hat, x)#把x的值賦給x_hat

接下來,編寫梯度降低步驟,以最大化目標類的成功機率

learning_rate = tf.placeholder(tf.float32, ())
y_hat = tf.placeholder(tf.int32, ())
#tf.placeholder用於定義
labels = tf.one_hot(y_hat, 1000)
loss = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=[labels])
optim_step = tf.train.GradientDescentOptimizer(
    learning_rate).minimize(loss, var_list=[x_hat])

編寫投影步驟,使得對抗樣本在視覺上與原始圖像類似。另外,將其限定爲[0,1]範圍內,用來保持有效的圖像。

epsilon = tf.placeholder(tf.float32, ())

below = x - epsilon
above = x + epsilon
projected = tf.clip_by_value(tf.clip_by_value(x_hat, below, above), 0, 1)
with tf.control_dependencies([projected]):
    project_step = tf.assign(x_hat, projected)#把project的值賦給x_hat

最後,準備合成一個對抗樣本。咱們任意選擇「鱷梨醬」(imagenet class 924)做爲咱們的目標類。

demo_epsilon = 2.0/255.0 #很小的擾動
demo_lr = 1e-1
demo_steps = 100
demo_target = 924 # "guacamole"

# initialization step
sess.run(assign_op, feed_dict={x: img})

# projected gradient descent
for i in range(demo_steps):
    # 梯度降低步驟
    _, loss_value = sess.run(
        [optim_step, loss],
        feed_dict={learning_rate: demo_lr, y_hat: demo_target})#引用demo_lr = 1e-1爲學習率,將y_hat:設置爲demo_target從而開始反向梯度降低
    # project step
    sess.run(project_step, feed_dict={x: img, epsilon: demo_epsilon})#將圖像加入小的擾動
    if (i+1) % 10 == 0:
        print('step %d, loss=%g' % (i+1, loss_value))
    

adv = x_hat.eval() # eval()是程序語言中的函數,功能是獲取返回值,不一樣語言大同小異,函數原型是返回值 = eval( codeString ),若是eval函數在執行時遇到錯誤,則拋出異常給調用者。
相關文章
相關標籤/搜索