修改了攻击方式,使其在全连接层模型上的效果更显著
This commit is contained in:
parent
e3d153646f
commit
2edab9976a
|
@ -39,13 +39,15 @@ def model_train(X_train, X_test, Y_train, Y_test):
|
||||||
# 编译模型
|
# 编译模型
|
||||||
model.compile(
|
model.compile(
|
||||||
optimizer='SGD',
|
optimizer='SGD',
|
||||||
loss=loss_fn)
|
loss=loss_fn,
|
||||||
|
metrics=[tf.keras.metrics.MeanAbsolutePercentageError()]
|
||||||
|
)
|
||||||
|
|
||||||
# 定义学习率指数递减的函数
|
# 定义学习率指数递减的函数
|
||||||
def lr_schedule(epoch):
|
def lr_schedule(epoch):
|
||||||
initial_learning_rate = 0.01
|
initial_learning_rate = 0.01
|
||||||
decay_rate = 0.1
|
decay_rate = 0.1
|
||||||
decay_steps = 1500
|
decay_steps = 2000
|
||||||
new_learning_rate = initial_learning_rate * \
|
new_learning_rate = initial_learning_rate * \
|
||||||
decay_rate ** (epoch / decay_steps)
|
decay_rate ** (epoch / decay_steps)
|
||||||
return new_learning_rate
|
return new_learning_rate
|
||||||
|
@ -58,11 +60,12 @@ def model_train(X_train, X_test, Y_train, Y_test):
|
||||||
tensorboard_callback = TensorBoard(log_dir=log_dir, histogram_freq=1)
|
tensorboard_callback = TensorBoard(log_dir=log_dir, histogram_freq=1)
|
||||||
|
|
||||||
# 训练模型,添加 TensorBoard 回调
|
# 训练模型,添加 TensorBoard 回调
|
||||||
model.fit(X_train, Y_train, epochs=1000,
|
model.fit(X_train, Y_train, epochs=6000,
|
||||||
callbacks=[tensorboard_callback, lr_scheduler], batch_size=256)
|
callbacks=[tensorboard_callback, lr_scheduler], batch_size=256)
|
||||||
|
|
||||||
loss = model.evaluate(X_test, Y_test)
|
loss, mape = model.evaluate(X_test, Y_test)
|
||||||
print("Test loss:", loss)
|
print("Test loss:", loss,)
|
||||||
|
print("test mape:", mape)
|
||||||
|
|
||||||
# 保存模型
|
# 保存模型
|
||||||
keras.models.save_model(model, 'model')
|
keras.models.save_model(model, 'model')
|
||||||
|
|
Binary file not shown.
|
@ -10,48 +10,61 @@ def craft_adv(X, Y, gamma, learning_rate, model, loss_fn, md = 0):
|
||||||
elif md == 1:
|
elif md == 1:
|
||||||
Y_test_tensor = tf.convert_to_tensor(Y, dtype=tf.float64)
|
Y_test_tensor = tf.convert_to_tensor(Y, dtype=tf.float64)
|
||||||
|
|
||||||
# 使用GradientTape计算梯度
|
# 初始化更新后的数据集
|
||||||
with tf.GradientTape() as tape:
|
X_train_updated = []
|
||||||
tape.watch(X_test_tensor)
|
|
||||||
predictions = model(X_test_tensor)
|
|
||||||
loss = loss_fn(Y_test_tensor, predictions)
|
|
||||||
|
|
||||||
# 计算关于输入的梯度
|
for i in range(X_test_tensor.shape[0]):
|
||||||
gradients = tape.gradient(loss, X_test_tensor)
|
# 对每个样本使用GradientTape
|
||||||
|
with tf.GradientTape() as tape:
|
||||||
|
# 监视当前样本
|
||||||
|
current_sample = X_test_tensor[i:i+1]
|
||||||
|
tape.watch(current_sample)
|
||||||
|
|
||||||
# 平坦化梯度以便进行处理
|
# 对当前样本进行预测并计算损失
|
||||||
flattened_gradients = tf.reshape(gradients, [-1])
|
predictions = model(current_sample)
|
||||||
|
loss = loss_fn(Y_test_tensor[i:i+1], predictions)
|
||||||
|
|
||||||
# 选择最大的γ * |X|个梯度
|
# 计算关于输入的梯度
|
||||||
num_gradients_to_select = int(gamma * tf.size(flattened_gradients, out_type=tf.dtypes.float32))
|
gradients = tape.gradient(loss, current_sample)
|
||||||
print(num_gradients_to_select)
|
|
||||||
top_gradients_indices = tf.argsort(flattened_gradients, direction='DESCENDING')[:num_gradients_to_select]
|
|
||||||
|
|
||||||
# 创建新的梯度张量,初始值为原始梯度
|
# 平坦化梯度以便进行处理
|
||||||
updated_gradients = tf.identity(flattened_gradients)
|
flattened_gradients = tf.reshape(gradients, [-1])
|
||||||
|
|
||||||
# 创建布尔掩码,用于选择特定梯度
|
# 选择最大的γ * |X|个梯度
|
||||||
mask = tf.ones_like(updated_gradients, dtype=bool)
|
num_gradients_to_select = int(gamma * tf.size(flattened_gradients, out_type=tf.dtypes.float32))
|
||||||
mask = tf.tensor_scatter_nd_update(mask, tf.expand_dims(top_gradients_indices, 1), tf.zeros_like(top_gradients_indices, dtype=bool))
|
top_gradients_indices = tf.argsort(flattened_gradients, direction='DESCENDING')[:num_gradients_to_select]
|
||||||
|
|
||||||
# 应用掩码更新梯度
|
# 创建新的梯度张量,初始值为原始梯度
|
||||||
updated_gradients = tf.where(mask, tf.zeros_like(updated_gradients), updated_gradients)
|
updated_gradients = tf.identity(flattened_gradients)
|
||||||
|
|
||||||
# 将梯度恢复到原始形状
|
# 创建布尔掩码,用于选择特定梯度
|
||||||
updated_gradients = tf.reshape(updated_gradients, tf.shape(gradients))
|
mask = tf.ones_like(updated_gradients, dtype=bool)
|
||||||
|
mask = tf.tensor_scatter_nd_update(mask, tf.expand_dims(top_gradients_indices, 1), tf.zeros_like(top_gradients_indices, dtype=bool))
|
||||||
|
|
||||||
# 应用学习率到梯度
|
# 应用掩码更新梯度
|
||||||
scaled_gradients = (learning_rate * 700) * updated_gradients
|
updated_gradients = tf.where(mask, tf.zeros_like(updated_gradients), updated_gradients)
|
||||||
# 更新X_test_tensor
|
|
||||||
X_train_updated = tf.add(X_test_tensor, scaled_gradients)
|
# 将梯度恢复到原始形状
|
||||||
X_train_updated = X_train_updated.numpy()
|
updated_gradients = tf.reshape(updated_gradients, tf.shape(gradients))
|
||||||
|
|
||||||
|
# 应用学习率到梯度
|
||||||
|
scaled_gradients = learning_rate * updated_gradients
|
||||||
|
|
||||||
|
# 更新当前样本
|
||||||
|
current_sample_updated = tf.add(current_sample, scaled_gradients)
|
||||||
|
|
||||||
|
# 将更新后的样本添加到列表中
|
||||||
|
X_train_updated.append(current_sample_updated.numpy())
|
||||||
|
|
||||||
|
# 将列表转换为张量
|
||||||
|
X_train_updated = tf.concat(X_train_updated, axis=0)
|
||||||
|
|
||||||
# 评估更新后的模型
|
# 评估更新后的模型
|
||||||
if md == 1:
|
if md == 1:
|
||||||
loss = model.evaluate(X_train_updated, Y)
|
loss, mape = model.evaluate(X_train_updated, Y)
|
||||||
print(f"Accuracy gamma: {gamma},learning:{learning_rate}", loss)
|
print(f"Accuracy gamma: {gamma},learning:{learning_rate}", loss)
|
||||||
|
|
||||||
return X_train_updated, loss
|
return X_train_updated, loss, mape
|
||||||
elif md == 0:
|
elif md == 0:
|
||||||
loss, accuracy = model.evaluate(X_train_updated, Y)
|
loss, accuracy = model.evaluate(X_train_updated, Y)
|
||||||
print(f"Accuracy gamma: {gamma},learning:{learning_rate},accuracy{accuracy}" )
|
print(f"Accuracy gamma: {gamma},learning:{learning_rate},accuracy{accuracy}" )
|
||||||
|
|
|
@ -14,8 +14,6 @@ md = int(input())
|
||||||
X_train, X_test, Y_train, Y_test = data_format(
|
X_train, X_test, Y_train, Y_test = data_format(
|
||||||
'data/archive/PowerQualityDistributionDataset1.csv', md=md)
|
'data/archive/PowerQualityDistributionDataset1.csv', md=md)
|
||||||
|
|
||||||
print(X_test.shape)
|
|
||||||
|
|
||||||
# 设置随机种子以确保重现性
|
# 设置随机种子以确保重现性
|
||||||
np.random.seed(7)
|
np.random.seed(7)
|
||||||
np.random.shuffle(X_test)
|
np.random.shuffle(X_test)
|
||||||
|
@ -46,9 +44,9 @@ for gamma in [0.05, 0.1, 0.2, 0.4]:
|
||||||
accuracy_list = []
|
accuracy_list = []
|
||||||
for learning_rate in [0.1, 0.2, 0.3, 0.4, 0.5]:
|
for learning_rate in [0.1, 0.2, 0.3, 0.4, 0.5]:
|
||||||
if md == 1:
|
if md == 1:
|
||||||
x_adv, loss = craft_adv(
|
x_adv, loss, mape = craft_adv(
|
||||||
X_test, Y_test, gamma, learning_rate, model, loss_fn, md = 1)
|
X_test, Y_test, gamma, learning_rate, model, loss_fn, md = 1)
|
||||||
accuracy_list.append(1 - loss*100)
|
accuracy_list.append(100 - mape)
|
||||||
elif md == 0:
|
elif md == 0:
|
||||||
x_adv, accuracy = craft_adv(
|
x_adv, accuracy = craft_adv(
|
||||||
X_test, Y_test, gamma, learning_rate, model, loss_fn)
|
X_test, Y_test, gamma, learning_rate, model, loss_fn)
|
||||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,16 @@
|
||||||
|
#build the NN models: RNN module
|
||||||
|
import tensorflow
|
||||||
|
|
||||||
|
from keras.models import Sequential
|
||||||
|
from keras.layers import Dense, Dropout, Activation, Flatten
|
||||||
|
|
||||||
|
def dnn_model(input_dim):
|
||||||
|
model = Sequential()
|
||||||
|
model.add(Dense(128, input_dim=input_dim))
|
||||||
|
model.add(Dropout(0.2))
|
||||||
|
model.add(Dense(32))
|
||||||
|
model.add(Activation('relu'))
|
||||||
|
model.add(Dense(16))
|
||||||
|
model.add(Activation('relu'))
|
||||||
|
model.add(Dense(4,init='normal', activation='softmax'))
|
||||||
|
return model
|
|
@ -0,0 +1 @@
|
||||||
|
This is the code example for attacking a normal Neural Networks with adversarial inputs.
|
|
@ -0,0 +1,133 @@
|
||||||
|
import tensorflow as tf
|
||||||
|
import keras
|
||||||
|
from keras.optimizers import SGD
|
||||||
|
from Neural_Net_Module import dnn_model
|
||||||
|
import csv
|
||||||
|
from numpy import shape
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
batch_size=32
|
||||||
|
nb_epoch=15
|
||||||
|
eps=0.5
|
||||||
|
gamma=80
|
||||||
|
|
||||||
|
def scaled_gradient(x, y, predictions):
|
||||||
|
#loss: the mean of loss(cross entropy)
|
||||||
|
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=predictions, labels=y))
|
||||||
|
grad, = tf.gradients(loss, x)
|
||||||
|
signed_grad = tf.sign(grad)
|
||||||
|
return grad, signed_grad
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if keras.backend.image_dim_ordering() != 'tf':
|
||||||
|
keras.backend.set_image_dim_ordering('tf')
|
||||||
|
|
||||||
|
sess = tf.Session()
|
||||||
|
keras.backend.set_session(sess)
|
||||||
|
|
||||||
|
|
||||||
|
with open('normal.csv', 'r') as csvfile:
|
||||||
|
reader = csv.reader(csvfile)
|
||||||
|
rows = [row for row in reader]
|
||||||
|
rows=np.array(rows, dtype=float)
|
||||||
|
data=rows
|
||||||
|
label=np.zeros((200,1))
|
||||||
|
with open('sag.csv', 'r') as csvfile:
|
||||||
|
reader = csv.reader(csvfile)
|
||||||
|
rows = [row for row in reader]
|
||||||
|
rows=np.array(rows, dtype=float)
|
||||||
|
data=np.concatenate((data, rows))
|
||||||
|
labels=np.ones((200,1))
|
||||||
|
label=np.concatenate((label, labels))
|
||||||
|
with open('distortion.csv', 'r') as csvfile:
|
||||||
|
reader = csv.reader(csvfile)
|
||||||
|
rows = [row for row in reader]
|
||||||
|
rows=np.array(rows, dtype=float)
|
||||||
|
data=np.concatenate((data, rows))
|
||||||
|
labels=2*np.ones((200,1))
|
||||||
|
label=np.concatenate((label, labels))
|
||||||
|
with open('impulse.csv', 'r') as csvfile:
|
||||||
|
reader = csv.reader(csvfile)
|
||||||
|
rows = [row for row in reader]
|
||||||
|
rows=np.array(rows, dtype=float)
|
||||||
|
data=np.concatenate((data, rows))
|
||||||
|
labels=3*np.ones((200,1))
|
||||||
|
label=np.concatenate((label, labels))
|
||||||
|
label=label.reshape(-1,1)
|
||||||
|
label=keras.utils.to_categorical(label, num_classes=None)
|
||||||
|
print("Input label shape", shape(label))
|
||||||
|
print("Input data shape", shape(data))
|
||||||
|
|
||||||
|
index = np.arange(len(label))
|
||||||
|
np.random.shuffle(index)
|
||||||
|
label = label[index]
|
||||||
|
data = data[index]
|
||||||
|
|
||||||
|
trX=data[:600]
|
||||||
|
trY=label[:600]
|
||||||
|
teX=data[600:]
|
||||||
|
teY=label[600:]
|
||||||
|
|
||||||
|
x = tf.placeholder(tf.float32, shape=(None, 1000))
|
||||||
|
y = tf.placeholder(tf.float32, shape=(None, 4))
|
||||||
|
|
||||||
|
model = dnn_model(input_dim=1000)
|
||||||
|
predictions = model(x)
|
||||||
|
sgd = SGD(lr=0.0001, decay=1e-6, momentum=0.9, nesterov=True)
|
||||||
|
model.compile(loss=keras.losses.categorical_crossentropy,
|
||||||
|
optimizer=keras.optimizers.Adadelta(),
|
||||||
|
metrics=['accuracy'])
|
||||||
|
|
||||||
|
model.fit(trX, trY, batch_size=batch_size, epochs=nb_epoch, shuffle=True) # validation_split=0.1
|
||||||
|
# model.save_weights('dnn_clean.h5')
|
||||||
|
score = model.evaluate(teX, teY, verbose=0)
|
||||||
|
print('Test loss:', score[0])
|
||||||
|
print('Test accuracy:', score[1])
|
||||||
|
|
||||||
|
|
||||||
|
with sess.as_default():
|
||||||
|
adv_sample=[]
|
||||||
|
counter = 0
|
||||||
|
# Initialize the SGD optimizer
|
||||||
|
grad, sign_grad = scaled_gradient(x, y, predictions)
|
||||||
|
for q in range(200):
|
||||||
|
if counter % 50 == 0 and counter > 0:
|
||||||
|
print("Attack on samples" + str(counter))
|
||||||
|
X_new_group=np.copy(teX[counter])
|
||||||
|
gradient_value, signed_grad = sess.run([grad, sign_grad], feed_dict={x: X_new_group.reshape(-1,1000),
|
||||||
|
y: teY[counter].reshape(-1,4),
|
||||||
|
keras.backend.learning_phase(): 0})
|
||||||
|
saliency_mat = np.abs(gradient_value)
|
||||||
|
saliency_mat = (saliency_mat > np.percentile(np.abs(gradient_value), [gamma])).astype(int)
|
||||||
|
X_new_group = X_new_group + np.multiply(eps * signed_grad, saliency_mat)
|
||||||
|
adv_sample.append(X_new_group)
|
||||||
|
'''print("Ground truth", teY[counter])
|
||||||
|
print(model.predict(teX[counter].reshape(-1, 1000)))
|
||||||
|
print(model.predict(X_new_group.reshape(-1,1000)))
|
||||||
|
plt.plot(teX[counter])
|
||||||
|
plt.show()
|
||||||
|
plt.plot(X_new_group.reshape(-1,1),'r')
|
||||||
|
plt.show()'''
|
||||||
|
|
||||||
|
|
||||||
|
counter+=1
|
||||||
|
adv_sample=np.array(adv_sample, dtype=float).reshape(-1,1000)
|
||||||
|
score=model.evaluate(adv_sample, teY, verbose=0)
|
||||||
|
print('Test loss:', score[0])
|
||||||
|
print('Test accuracy:', score[1])
|
||||||
|
|
||||||
|
teY_pred=np.argmax(model.predict(teX, batch_size=32), axis=1)
|
||||||
|
adv_pred=np.argmax(model.predict(adv_sample, batch_size=32), axis=1)
|
||||||
|
'''with open('test_true.csv', 'w') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(np.argmax(teY, axis=1).reshape(-1, 1))
|
||||||
|
|
||||||
|
with open('test_pred.csv', 'w') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(teY_pred.reshape(-1, 1))
|
||||||
|
|
||||||
|
with open('test_adversary.csv', 'w') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(adv_pred.reshape(-1, 1))'''
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
import numpy as np
|
||||||
|
import csv
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
|
||||||
|
def voltage_sag(signal, level):
|
||||||
|
x=np.linspace(4*np.pi, 10*np.pi, 300)
|
||||||
|
y=level*np.sin(x)
|
||||||
|
signal[200:500]=y
|
||||||
|
return signal
|
||||||
|
|
||||||
|
def voltage_distortion(signal, level):
|
||||||
|
noise=np.random.normal(loc=0, scale=level, size=np.shape(signal))
|
||||||
|
signal+=noise
|
||||||
|
#plt.plot(signal)
|
||||||
|
#plt.show()
|
||||||
|
|
||||||
|
return signal
|
||||||
|
|
||||||
|
|
||||||
|
def voltage_impulse(signal, level):
|
||||||
|
noise=np.random.normal(loc=0, scale=level, size=np.shape(signal))
|
||||||
|
signal[400:420]+=noise[400:420]
|
||||||
|
#plt.plot(signal)
|
||||||
|
#plt.show()
|
||||||
|
|
||||||
|
return signal
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
x = np.linspace(0 * np.pi, 20* np.pi, 1000)
|
||||||
|
y = np.sin(x)
|
||||||
|
signal=y
|
||||||
|
signal_all=[]
|
||||||
|
'''for i in range(200):
|
||||||
|
levels=np.random.uniform(0.5, 0.9)
|
||||||
|
#print(levels)
|
||||||
|
signals=voltage_sag(signal, level=levels)
|
||||||
|
#plt.plot(signals)
|
||||||
|
#plt.show()
|
||||||
|
signal_all.append(np.copy(signals))
|
||||||
|
signal_all=np.array(signal_all, dtype=float).reshape(-1,1000)
|
||||||
|
with open('sag.csv', 'w') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(signal_all)'''
|
||||||
|
|
||||||
|
|
||||||
|
'''signal_all=[]
|
||||||
|
for i in range(200):
|
||||||
|
levels=np.random.uniform(0.0, 0.1)
|
||||||
|
#print(levels)
|
||||||
|
signals=voltage_distortion(signal, level=levels)
|
||||||
|
#plt.plot(signals)
|
||||||
|
#plt.show()
|
||||||
|
signal_all.append(np.copy(signals))
|
||||||
|
signal_all=np.array(signal_all, dtype=float).reshape(-1,1000)
|
||||||
|
with open('distortion.csv', 'w') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(signal_all)'''
|
||||||
|
|
||||||
|
|
||||||
|
'''signal_all=[]
|
||||||
|
for i in range(200):
|
||||||
|
levels=np.random.uniform(0.5, 0.8)
|
||||||
|
#print(levels)
|
||||||
|
signals=voltage_impulse(signal, level=levels)
|
||||||
|
#plt.plot(signals)
|
||||||
|
#plt.show()
|
||||||
|
signal_all.append(np.copy(signals))
|
||||||
|
signal_all=np.array(signal_all, dtype=float).reshape(-1,1000)
|
||||||
|
with open('impulse.csv', 'w') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(signal_all)'''
|
||||||
|
|
||||||
|
signal_all = []
|
||||||
|
for i in range(200):
|
||||||
|
levels = np.random.uniform(0.0, 0.01)
|
||||||
|
# print(levels)
|
||||||
|
signals = voltage_distortion(signal, level=levels)
|
||||||
|
# plt.plot(signals)
|
||||||
|
# plt.show()
|
||||||
|
signal_all.append(np.copy(signals))
|
||||||
|
signal_all = np.array(signal_all, dtype=float).reshape(-1, 1000)
|
||||||
|
with open('normal.csv', 'w') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(signal_all)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,244 @@
|
||||||
|
import tensorflow as tf
|
||||||
|
import keras
|
||||||
|
from keras.optimizers import SGD
|
||||||
|
from Neural_Net_Module import rnn_model
|
||||||
|
import csv
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from utils import *
|
||||||
|
|
||||||
|
lr = 0.01
|
||||||
|
batch_size = 200
|
||||||
|
nb_epoch = 10
|
||||||
|
controllable_dim = 16
|
||||||
|
seq_length = 10
|
||||||
|
TEMP_MAX = 24
|
||||||
|
TEMP_MIN = 19
|
||||||
|
eps=0.03
|
||||||
|
gamma=90
|
||||||
|
|
||||||
|
|
||||||
|
def scaled_gradient(x, predictions, target):
|
||||||
|
loss = tf.square(predictions - target)
|
||||||
|
# Take gradient with respect to x_{T}, since it contains all the x value needs to be updated
|
||||||
|
grad, = tf.gradients(loss, x)
|
||||||
|
signed_grad = tf.sign(grad)
|
||||||
|
# Define the gradient of log barrier function on constraints
|
||||||
|
#grad_comfort_high = 1 / ((tref_high - tset))
|
||||||
|
#grad_comfort_low = 1 / ((tset - tref_low))
|
||||||
|
#grad_contrained = grad[:, :, 0:16] + 0.000000001 * (grad_comfort_high + grad_comfort_low)
|
||||||
|
return grad, signed_grad
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if keras.backend.image_dim_ordering() != 'tf':
|
||||||
|
keras.backend.set_image_dim_ordering('tf')
|
||||||
|
|
||||||
|
sess = tf.Session()
|
||||||
|
keras.backend.set_session(sess)
|
||||||
|
|
||||||
|
with open('building_data.csv', 'r') as csvfile:
|
||||||
|
reader = csv.reader(csvfile)
|
||||||
|
rows = [row for row in reader]
|
||||||
|
rows = rows[1:43264]
|
||||||
|
print("Dataset shape", shape(rows))
|
||||||
|
rows = np.array(rows[1:], dtype=float)
|
||||||
|
|
||||||
|
feature_dim = rows.shape[1]
|
||||||
|
print("Feature dimension", feature_dim)
|
||||||
|
|
||||||
|
# Normalize the feature and response
|
||||||
|
max_value = np.max(rows, axis=0)
|
||||||
|
print("Max power values: ", max_value)
|
||||||
|
min_value = np.min(rows, axis=0)
|
||||||
|
rows2 = (rows - min_value) / (max_value - min_value)
|
||||||
|
|
||||||
|
# Reorganize to the RNN-like sequence
|
||||||
|
X_train, Y_train = reorganize(rows2[:, 0:feature_dim - 1], rows2[:, feature_dim - 1], seq_length=seq_length)
|
||||||
|
print("Training data shape", shape(X_train))
|
||||||
|
print("X_train None:", np.argwhere(np.isnan(X_train)))
|
||||||
|
X_train = np.array(X_train, dtype=float)
|
||||||
|
Y_train = np.array(Y_train, dtype=float)
|
||||||
|
|
||||||
|
# Test data: change here for real testing data
|
||||||
|
Y_test = np.copy(Y_train[3500:])
|
||||||
|
X_test = np.copy(X_train[3500:])
|
||||||
|
X_train = X_train[:35000]
|
||||||
|
Y_train = Y_train[:35000]
|
||||||
|
print('Number of testing samples', Y_test.shape[0])
|
||||||
|
print('Number of training samples', Y_train.shape[0])
|
||||||
|
|
||||||
|
# Define tensor
|
||||||
|
x = tf.placeholder(tf.float32, shape=(None, seq_length, feature_dim - 1))
|
||||||
|
y = tf.placeholder(tf.float32, shape=(None, 1))
|
||||||
|
tset = tf.placeholder(tf.float32, shape=(None, seq_length, controllable_dim))
|
||||||
|
target = tf.placeholder(tf.float32, shape=(None, 1))
|
||||||
|
|
||||||
|
# Define the tempture setpoint upper and lower bound
|
||||||
|
temp_low = TEMP_MIN * np.ones((1, controllable_dim)) # temp setpoint lowest as 20
|
||||||
|
temp_low = (temp_low - min_value[0:controllable_dim]) / (max_value[0:controllable_dim] - min_value[0:controllable_dim])
|
||||||
|
temp_high = TEMP_MAX * np.ones((1, controllable_dim)) # temp setpoint highest as 25
|
||||||
|
temp_high = (temp_high - min_value[0:controllable_dim]) / (max_value[0:controllable_dim] - min_value[0:controllable_dim])
|
||||||
|
|
||||||
|
# Define the RNN model, establish the graph and SGD solver
|
||||||
|
model = rnn_model(seq_length=seq_length, input_dim=feature_dim - 1)
|
||||||
|
predictions = model(x)
|
||||||
|
sgd = SGD(lr=0.0001, decay=1e-6, momentum=0.9, nesterov=True)
|
||||||
|
model.compile(loss='mean_squared_error', optimizer=sgd)
|
||||||
|
|
||||||
|
# Fit the RNN model with training data and save the model weight
|
||||||
|
model.fit(X_train, Y_train, batch_size=batch_size, epochs=nb_epoch, shuffle=True) # validation_split=0.1
|
||||||
|
# model.save_weights('rnn_clean.h5')
|
||||||
|
model.load_weights('rnn_clean.h5')
|
||||||
|
y_value = model.predict(X_test[0:5000], batch_size=32)
|
||||||
|
|
||||||
|
# Record the prediction result
|
||||||
|
with open('predicted_rnn2.csv', 'w') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(y_value)
|
||||||
|
|
||||||
|
with open('truth_rnn2.csv', 'w') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(Y_test[0:5000])
|
||||||
|
|
||||||
|
# Plot the prediction result. This is the same as Building_Load_Forecasting.py
|
||||||
|
t = np.arange(0, 2016)
|
||||||
|
plt.plot(t, Y_test[216:216 + 2016], 'r--', label="True")
|
||||||
|
plt.plot(t, y_value[216:216 + 2016], 'b', label="predicted")
|
||||||
|
plt.legend(loc='northeast')
|
||||||
|
ax = plt.gca() # grab the current axis
|
||||||
|
ax.set_xticks(144 * np.arange(0, 14)) # choose which x locations to have ticks
|
||||||
|
ax.set_xticklabels(["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
|
||||||
|
"Sun"]) # set the labels to display at those ticks
|
||||||
|
plt.title("Building electricity consumption")
|
||||||
|
plt.show()
|
||||||
|
print("Clean training completed!")
|
||||||
|
print("Training percentage error:", np.mean(np.divide(abs(y_value - Y_train[0:5000]), Y_train[0:5000])))
|
||||||
|
#model.save_weights('rnn_clean.h5')
|
||||||
|
|
||||||
|
# Optimization step starts here!
|
||||||
|
|
||||||
|
|
||||||
|
X_new = []
|
||||||
|
grad_new = []
|
||||||
|
mpc_scope = seq_length
|
||||||
|
X_train2 = np.copy(X_test)
|
||||||
|
with sess.as_default():
|
||||||
|
counter = 0
|
||||||
|
# Initialize the SGD optimizer
|
||||||
|
grad, sign_grad = scaled_gradient(x, predictions, target)
|
||||||
|
for q in range(1000 - seq_length):
|
||||||
|
if counter % 100 == 0 and counter > 0:
|
||||||
|
print("Optimization Time step" + str(counter))
|
||||||
|
|
||||||
|
# Define the control output target
|
||||||
|
#Y_target = (0 * Y_test[counter:counter + mpc_scope]).reshape(-1, 1)
|
||||||
|
Y_target = Y_test[counter:counter + mpc_scope].reshape(-1, 1)
|
||||||
|
|
||||||
|
# upper and lower bound for controllable features
|
||||||
|
X_upper_bound = np.tile(temp_high, (mpc_scope, seq_length, 1))
|
||||||
|
X_lower_bound = np.tile(temp_low, (mpc_scope, seq_length, 1))
|
||||||
|
|
||||||
|
# Define input: x_t, x_{t+1},...,x_{t+pred_scope}
|
||||||
|
X_input = X_train2[counter:counter + mpc_scope]
|
||||||
|
#X_input = check_control_constraint(X_input, controllable_dim, X_upper_bound, X_lower_bound)
|
||||||
|
X_controllable = X_input[:, :, 0:controllable_dim]
|
||||||
|
# the uncontrollable part needs to be replaced by prediction later!!!
|
||||||
|
X_uncontrollable = X_input[:, :, controllable_dim:feature_dim - 1]
|
||||||
|
|
||||||
|
X_new_group = X_input
|
||||||
|
#print("X_new_group shape", shape(X_new_group))
|
||||||
|
gradient_value, signed_grad = sess.run([grad, sign_grad], feed_dict={x: X_new_group,
|
||||||
|
target: Y_target,
|
||||||
|
tset: X_controllable,
|
||||||
|
keras.backend.learning_phase(): 0})
|
||||||
|
#print("sign_grad", signed_grad)
|
||||||
|
#print(np.shape(signed_grad))
|
||||||
|
saliency_mat=np.abs(gradient_value)
|
||||||
|
saliency_mat=(saliency_mat>np.percentile(np.abs(gradient_value),[gamma])).astype(int)
|
||||||
|
random_num=np.random.randint(0,2)
|
||||||
|
if random_num==0:
|
||||||
|
X_new_group = X_new_group + np.multiply(eps * signed_grad, saliency_mat)
|
||||||
|
#X_new_group = X_new_group + eps * signed_grad
|
||||||
|
else:
|
||||||
|
X_new_group = X_new_group - np.multiply(eps * signed_grad, saliency_mat)
|
||||||
|
#X_new_group = X_new_group - eps * signed_grad
|
||||||
|
|
||||||
|
# check the norm constraints on input
|
||||||
|
#X_new_group = check_control_constraint(X_new_group, controllable_dim, X_upper_bound, X_lower_bound)
|
||||||
|
y_new_group = model.predict(X_new_group)
|
||||||
|
|
||||||
|
if X_new == []:
|
||||||
|
X_new = X_new_group[0].reshape([1, seq_length, feature_dim - 1])
|
||||||
|
grad_new = gradient_value[0]
|
||||||
|
else:
|
||||||
|
X_new = np.concatenate((X_new, X_new_group[0].reshape([1, seq_length, feature_dim - 1])), axis=0)
|
||||||
|
grad_new = np.concatenate((grad_new, gradient_value[0]), axis=0)
|
||||||
|
|
||||||
|
# Update the x value in the training data
|
||||||
|
X_train2[counter] = X_new_group[0].reshape([1, seq_length, feature_dim - 1])
|
||||||
|
for i in range(1, seq_length):
|
||||||
|
X_train2[counter + i, 0:seq_length - i, :] = X_train2[counter, i:seq_length, :]
|
||||||
|
|
||||||
|
# Next time step
|
||||||
|
counter += 1
|
||||||
|
|
||||||
|
|
||||||
|
X_new = np.array(X_new, dtype=float)
|
||||||
|
print("Adversarial X shape", shape(X_new))
|
||||||
|
dime=55
|
||||||
|
y_new = model.predict(X_new, batch_size=64)* (max_value[dime] - min_value[dime]) + min_value[dime]
|
||||||
|
y_val=model.predict(X_test[:1000], batch_size=32)* (max_value[dime] - min_value[dime]) + min_value[dime]
|
||||||
|
y_orig=Y_test[:1000]* (max_value[dime] - min_value[dime]) + min_value[dime]
|
||||||
|
plt.plot(y_new,'r')
|
||||||
|
plt.plot(y_val, 'g')
|
||||||
|
plt.plot(y_orig,'b')
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
print("Adversary Forecast Error:", np.mean(np.clip(np.abs(y_new - y_orig[:990])/y_orig[:990], 0,3)))
|
||||||
|
with open('test_true.csv', 'w') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(y_orig.reshape(-1,1))
|
||||||
|
|
||||||
|
with open('test_pred.csv', 'w') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(y_val.reshape(-1,1))
|
||||||
|
|
||||||
|
with open('test_adversary.csv', 'w') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(y_new.reshape(-1,1))
|
||||||
|
|
||||||
|
|
||||||
|
#Observe the difference on input features and visualize
|
||||||
|
deviation_all=0
|
||||||
|
'''for dime in range(30):
|
||||||
|
X_temp = rows[0:len(X_new), dime]
|
||||||
|
X_temp_new = X_new[0:len(X_new), 0, dime] * (max_value[dime] - min_value[dime]) + min_value[dime]
|
||||||
|
deviation=np.mean(np.abs(X_temp_new-X_temp)/(X_temp+0.0001))
|
||||||
|
print(deviation)
|
||||||
|
deviation_all+=deviation
|
||||||
|
plt.plot(X_temp, 'r--', label="previous")
|
||||||
|
plt.plot(X_temp_new, 'b', label="adversarial")
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
print("The overall input features deviation: ", deviation_all/30.0)'''
|
||||||
|
|
||||||
|
dime=26
|
||||||
|
X_temp = rows[0:len(X_new), dime].reshape(-1,1)
|
||||||
|
X_temp_new = (X_new[0:len(X_new), 0, dime] * (max_value[dime] - min_value[dime]) + min_value[dime]).reshape(-1,1)
|
||||||
|
plt.plot(X_temp, 'r--', label="previous")
|
||||||
|
plt.plot(X_temp_new, 'b', label="adversarial")
|
||||||
|
plt.show()
|
||||||
|
with open('fea10_orig.csv', 'w') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(X_temp)
|
||||||
|
|
||||||
|
with open('fea10_adv.csv', 'w') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(X_temp_new)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
#build the NN models: RNN module
|
||||||
|
import tensorflow
|
||||||
|
from tensorflow.python.ops import control_flow_ops
|
||||||
|
from keras.models import Sequential
|
||||||
|
from keras.layers import Dense, Dropout, Activation, Flatten
|
||||||
|
from keras.layers import Convolution2D, MaxPooling2D
|
||||||
|
from keras.layers import LSTM, Embedding,SimpleRNN
|
||||||
|
from keras.utils import np_utils
|
||||||
|
from tensorflow.python.platform import flags
|
||||||
|
from numpy import shape
|
||||||
|
import numpy as np
|
||||||
|
from skimage import io, color, exposure, transform
|
||||||
|
import os
|
||||||
|
import glob
|
||||||
|
import h5py
|
||||||
|
import pandas as pd
|
||||||
|
import numpy
|
||||||
|
|
||||||
|
|
||||||
|
FLAGS = flags.FLAGS
|
||||||
|
#tensorflow.python.control_flow_ops =control_flow_ops
|
||||||
|
|
||||||
|
|
||||||
|
def rnn_model(seq_length, input_dim):
|
||||||
|
model = Sequential()
|
||||||
|
model.add((SimpleRNN(64, input_shape=(seq_length, input_dim))))
|
||||||
|
model.add(Dropout(0.2))
|
||||||
|
model.add(Dense(64))
|
||||||
|
model.add(Activation('relu'))
|
||||||
|
model.add(Dense(32))
|
||||||
|
model.add(Activation('relu'))
|
||||||
|
model.add(Dense(16))
|
||||||
|
model.add(Activation('relu'))
|
||||||
|
model.add(Dense(1,init='normal'))
|
||||||
|
return model
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Power_adversary
|
||||||
|
The code repo for Is Machine Learning in Power Systems Vulnerable?
|
||||||
|
|
||||||
|
Paper accepted to SmartGridComm2018, Workshop on AI in Energy Systems.
|
||||||
|
|
||||||
|
Authors: Yize Chen, Yushi Tan and Deepjyoti Deka
|
||||||
|
|
||||||
|
University of Washington and Los Alamos National Laboratory.
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
We look into the vulnerabilities of ML algorithms in power systems, and craft specific attacks on power systems with different applications.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
To exploit the algorithmic vulnerabilities, we consider the classification and forecasting case in power systems. Directly run the Python files and test the model accuracy before and after the attack.
|
||||||
|
|
||||||
|
Contact: yizechen@uw.edu
|
|
@ -0,0 +1,38 @@
|
||||||
|
# Defense strategies from literature
|
||||||
|
|
||||||
|
## Manipulating ML: poisoning attacks and countermeasure for regression learning
|
||||||
|
|
||||||
|
### System model
|
||||||
|
|
||||||
|
The function is chosen to minimize a quadratic loss function:
|
||||||
|
$
|
||||||
|
\mathcal{L}(\mathcal{D}_{tr}, \mathsf{\theta}) = \frac{1}{n}\sum_{i = 1}^{n} (f(\mathsf{x}_i, \mathsf{\theta}) - y_i)^2 + \lambda \Omega(\mathsf{w})
|
||||||
|
$
|
||||||
|
|
||||||
|
### Adversarial modeling
|
||||||
|
|
||||||
|
The goal is to corrupt the learning model generated in the training phase so that the predictions on new data will be modified in the testing phase. Two setup are considered, *white-box* and *black-box* attacks. In *black-box* attacks, the attackers has no knowledge of the training set $\mathcal{D}_{tr}$ but can collect a substitute data set $\mathcal{D}_{tr}^{\prime}$. The feature set and the learning algorithm are know, while the training parameters are not.
|
||||||
|
|
||||||
|
The *white-box* attack eventually could be modeled as
|
||||||
|
$$
|
||||||
|
\arg \max_{\mathcal{D}_p} \;\, \mathcal{W}(\mathcal{D}^{\prime}, \mathsf{\theta}_p^{\ast}) \\
|
||||||
|
\;\,\;\,\;\,\;\, s.t. \;\, \mathsf{\theta}_p^{\ast} \in \arg \min_{\mathsf{\theta}} \mathcal{L(\mathcal{D}_{tr} \cup \mathcal{D}_{p}, \mathsf{\theta})}
|
||||||
|
$$
|
||||||
|
In the *black-box* setting, the poisoned regression parameters $\mathsf{\theta}_{p}^{\ast}$ are estimated using the substitute data.
|
||||||
|
|
||||||
|
### Attack Methods
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Comments
|
||||||
|
|
||||||
|
1. The attack model is kind of different if I understand correctly. The aim is to come up with an additional data set so that the “optimized” parameter would fail on any intact data set.
|
||||||
|
2. And the set up is like the breakdown point, while the major difference is the evaluation. Breakdown point evaluates the parameter, but this setup evaluates the performance on “test” set.
|
||||||
|
3. This setup intrinsically attacks the fitting strategy, rather than a specific model.
|
||||||
|
4. And it uses the bi-level stackelberg game.
|
||||||
|
5. The defense strategy is still, more or less, the conventional trimmed loss.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## The space of transferable adversarial examples
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,28 @@
|
||||||
|
from numpy import shape
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def reorganize(X_train, Y_train, seq_length):
|
||||||
|
# Organize the input and output to feed into RNN model
|
||||||
|
x_data = []
|
||||||
|
for i in range(len(X_train) - seq_length):
|
||||||
|
x_new = X_train[i:i + seq_length]
|
||||||
|
x_data.append(x_new)
|
||||||
|
|
||||||
|
# Y_train
|
||||||
|
y_data = Y_train[seq_length:]
|
||||||
|
y_data = y_data.reshape((-1, 1))
|
||||||
|
|
||||||
|
return x_data, y_data
|
||||||
|
|
||||||
|
|
||||||
|
def check_control_constraint(X, dim, uppper_bound, lower_bound):
|
||||||
|
for i in range(0, shape(X)[0]):
|
||||||
|
for j in range(0, shape(X)[0]):
|
||||||
|
for k in range(0, dim):
|
||||||
|
if X[i, j, k] >= uppper_bound[i, j, k]:
|
||||||
|
X[i, j, k] = uppper_bound[i, j, k] - 0.01
|
||||||
|
if X[i, j, k] <= lower_bound[i, j, k]:
|
||||||
|
X[i, j, k] = lower_bound[i, j, k] + 0.01
|
||||||
|
return X
|
Loading…
Reference in New Issue