Вопрос по алгоритму ElasticNet, реализованному в Cleverhans

Я пытаюсь использовать алгоритм Elastic-Net, реализованный в Cleverhans, для создания состязательных образцов в задаче классификации. Основная проблема заключается в том, что я пытаюсь использовать его таким образом, чтобы получить более высокую уверенность во время классификации по целевому классу (отличному от исходного), но я не могу достичь хороших результатов. Система, которую я пытаюсь обмануть, - это DNN с выходом softmax для 10 классов.

Например:

  1. Учитывая образец класса 3, я хочу сгенерировать состязательную выборку класса 0.
  2. Используя гиперпараметры по умолчанию, реализованные в ElasticNetMethod cleverhans, я могу получить успешную атаку, поэтому класс, назначенный для состязательной выборки, стал классом 0, но достоверность довольно низкая (около 30%). Это также происходит при использовании разных значений гиперпараметров.
  3. Моя цель - получить более высокую уверенность (не менее 90%).
  4. Для другого алгоритма, такого как FGSM или MadryEtAl, я могу достичь этой цели, создав цикл, в котором алгоритм применяется до тех пор, пока образец не будет классифицирован как целевой класс с достоверностью более 90%, но я не могу применить эту итерацию на алгоритме EAD, потому что на каждом шаге итерации он дает состязательную выборку, сгенерированную на первом шаге, а в следующих итерациях она остается неизменной. (Я знаю, что это может произойти, потому что алгоритм отличается от двух других упомянутых, но я пытаюсь найти решение для достижения своей цели).

Это код, который я на самом деле использую для создания образцов противоборства.

ead_params  = { 'binary_search_steps':9, 'max_iterations':100 , 'learning_rate':0.001, 'clip_min':0,'clip_max':1,'y_target':target}
adv_x = image
founded_adv = False
threshold = 0.9
wrap = KerasModelWrapper(model)
ead = ElasticNetMethod(wrap, sess=sess)

while (not founded_adv):

    adv_x = ead.generate_np(adv_x, **ead_params)
    prediction = model.predict(adv_x).tolist()
    pred_class = np.argmax(prediction[0])
    confidence = prediction[0][pred_class]    

    if (pred_class == 0 and confidence >= threshold):
        founded_adv = True
        

Цикл while может генерировать образец до тех пор, пока целевой класс не будет достигнут с достоверностью более 90%. Этот код действительно работает с FGSM и Madry, но бесконечно работает с EAD.

Версия библиотеки:

Tensorflow: 2.2.0 Keras: 2.4.3 Cleverhans: 2.0.0-451ccecad450067f99c333fc53592201

Кто-нибудь может мне помочь?

Большое спасибо.


comment
Я нашел решение и разместил его здесь.   -  person Lorder    schedule 05.09.2020


Ответы (1)


Для всех, кто заинтересован в этой проблеме, предыдущий код может быть изменен таким образом, чтобы он работал правильно:

ПЕРВОЕ РЕШЕНИЕ:

prediction = model.predict(image)
initial_predicted_class = np.argmax(prediction[0])
ead_params  = { 'binary_search_steps':9, 'max_iterations':100 , 'learning_rate':0.001,'confidence':1, 'clip_min':0,'clip_max':1,'y_target':target}
adv_x = image
founded_adv = False
threshold = 0.9
wrap = KerasModelWrapper(model)
ead = ElasticNetMethod(wrap, sess=sess)

while (not founded_adv):

    adv_x = ead.generate_np(adv_x, **ead_params)
    prediction = model.predict(adv_x).tolist()
    pred_class = np.argmax(prediction[0])
    confidence = prediction[0][pred_class]    

    if (pred_class == initial_pred_class and confidence >= threshold):
        founded_adv = True
    else: 
        ead_params['confidence'] += 1 

Используя параметр достоверности, реализованный в библиотеке. Фактически мы увеличиваем на 1 параметр достоверности, если вероятность целевого класса не увеличивается.

ВТОРОЕ РЕШЕНИЕ:

prediction = model.predict(image)
initial_predicted_class = np.argmax(prediction[0]) 

ead_params   = {'beta':5e-3 , 'binary_search_steps':6, 'max_iterations':10 , 'learning_rate':3e-2, 'clip_min':0,'clip_max':1}
threshold = 0.96
adv_x = image
founded_adv = False
wrap = KerasModelWrapper(model)
ead = ElasticNetMethod(wrap, sess=sess)

while (not founded_adv):

    eps_hyp = 0.5
    new_adv_x = ead.generate_np(adv_x, **ead_params)
    pert = new_adv_x-adv_x
    new_adv_x = adv_x - eps_hyp*pert
    new_adv_x = (new_adv_x - np.min(new_adv_x)) / (np.max(new_adv_x) - np.min(new_adv_x))
    adv_x = new_adv_x
    prediction = model.predict(new_adv_x).tolist()
    pred_class = np.argmax(prediction[0])
    confidence = prediction[0][pred_class]
    print(pred_class)
    print(confidence)


    if (pred_class == initial_predicted_class and confidence >= threshold): 
        founded_adv = True

Во втором решении есть следующая модификация исходного кода:

-Initial_predicted_class - это класс, предсказанный моделью на доброкачественной выборке (0 для нашего примера).

-В параметрах алгоритма (ead_params) мы не вставляем целевой класс.

-Тогда мы можем получить возмущение, заданное алгоритмом вычисления pert = new_adv_x - adv_x, где adv_x - исходное изображение (на первом шаге цикла for), а new_adv_x - это возмущенный образец, сгенерированный алгоритмом.

-Предыдущая операция полезна, потому что оригинальный алгоритм EAD вычисляет возмущение, чтобы максимизировать потери по отношению к классу 0, но в нашем случае мы хотим его минимизировать.

-Таким образом, мы можем вычислить новое возмущенное изображение как new_adv_x = adv_x - eps_hyp * pert (где eps_hyp - это эпсилон-гиперпараметр, который я ввел для уменьшения возмущения), а затем нормализовать новое возмущенное изображение.

-Я тестировал код для большого количества изображений, и уверенность всегда увеличивается, поэтому я думаю, что это может быть хорошим решением для этой цели.

Я думаю, что второе решение позволяет получить более мелкие возмущения.

person Lorder    schedule 06.09.2020