import os
import csv
import matplotlib as mpl
import matplotlib.pyplot as plt
from IPython.display import display
import pandas as pd
import numpy as np
from PIL import Image
import tensorflow as tf
from tensorflow.keras import utils
from tensorflow import keras
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPool2D, MaxPooling2D, AveragePooling2D, BatchNormalization, Input, Lambda, Activation, Concatenate, Multiply, GlobalAveragePooling2D, GlobalMaxPooling2D, Reshape
image_list = []
label_list = []
root = "auc.distracted.driver.dataset_v2/v1_cam1_no_split/"
with open(root + "Train_data_list.csv", 'r') as file:
next(file)
csvreader = csv.reader(file)
for row in csvreader:
image_list.append(root + row[0])
label_list.append(row[1])
def get_image(row_id, root=root):
filename = "{}".format(row_id)
file_path = os.path.join(filename)
img = Image.open(file_path)
img = img.resize((300,160),Image.ANTIALIAS)
print(filename)
return np.array(img)
def create_feature_matrix(label_dataframe):
num_samples = len(label_dataframe)
feature_len = (160, 300, 3)
# 使用 memmap 儲存特徵數據
memmap_arr = np.memmap('data.memmap', dtype='float32', mode='w+', shape=(num_samples,) + feature_len)
for i in range(num_samples):
img_id = label_dataframe[i]
img_array = get_image(img_id)
img_normalized = img_array / 255.0
# 將影像特徵存入 memmap 陣列
memmap_arr[i] = np.array(img_normalized, dtype="float32")
return memmap_arr
def channel_attention_module(x, ratio=8):
batch, _, _, channel = x.shape
## Shared layers
l1 = Dense(channel//ratio, activation="relu", use_bias=False)
l2 = Dense(channel, use_bias=False)
## Global Average Pooling
x1 = GlobalAveragePooling2D()(x)
x1 = l1(x1)
x1 = l2(x1)
## Global Max Pooling
x2 = GlobalMaxPooling2D()(x)
x2 = l1(x2)
x2 = l2(x2)
## Add both the features and pass through sigmoid
feats = x1 + x2
feats = Activation("sigmoid")(feats)
feats = Multiply()([x, feats])
return feats
def spatial_attention_module(x):
## Average Pooling
x1 = tf.reduce_mean(x, axis=-1)
x1 = tf.expand_dims(x1, axis=-1)
## Max Pooling
x2 = tf.reduce_max(x, axis=-1)
x2 = tf.expand_dims(x2, axis=-1)
## Concatenat both the features
feats = Concatenate()([x1, x2])
## Conv layer
feats = Conv2D(1, kernel_size=7, padding="same", activation="sigmoid")(feats)
feats = Multiply()([x, feats])
return feats
def CBAM(x):
x = channel_attention_module(x)
x = spatial_attention_module(x)
return x
# run create_feature_matrix on our dataframe of images
X_train = create_feature_matrix(image_list)
# covert the labels intp onehot code
y_train = utils.to_categorical(label_list)
# constuct model
model = Sequential([
Conv2D(filters=16, kernel_size=3, strides=1, padding='valid', activation='relu', input_shape=(160, 300, 3)),
Conv2D(filters=16, kernel_size=3, strides=1, padding='valid', activation='relu'),
MaxPooling2D(pool_size=(2, 2), padding='valid'),
Lambda(lambda x: CBAM(x)),
Conv2D(filters=32, kernel_size=3, strides=1 , padding='valid', activation='relu'),
Conv2D(filters=32, kernel_size=3, strides=1 , padding='valid', activation='relu'),
MaxPooling2D(pool_size=(2, 2), padding='valid'),
Lambda(lambda x: CBAM(x)),
Conv2D(filters=32, kernel_size=3, strides=1 , padding='valid', activation='relu'),
Conv2D(filters=32, kernel_size=3, strides=1 , padding='valid', activation='relu'),
MaxPooling2D(pool_size=(2, 2), padding='valid'),
Lambda(lambda x: CBAM(x)),
Conv2D(filters=64, kernel_size=3, strides=1 , padding='valid', activation='relu'),
Conv2D(filters=64, kernel_size=3, strides=1 , padding='valid', activation='relu'),
MaxPooling2D(pool_size=(2, 2), padding='valid'),
Lambda(lambda x: CBAM(x)),
AveragePooling2D(pool_size=2, padding='same'),
Flatten(),
Dropout(rate=0.25),
Dense(10, activation='softmax')
])
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
train = model.fit(X_train, y_train, validation_split=0.2, epochs=300, batch_size=128, verbose=1)
model.save("model.h5", save_format='h5')
閱讀完後試著實作在網路上找到網友放在 GitHub 的程式碼
https://github.com/nikhilroxtomar/Attention-Mechanism-Implementation/blob/main/TensorFlow/cbam.py
想法是要在模型中呼叫函式,程式碼中的 Lambda(lambda x: CBAM(x)) 是要呼叫 CBAM 函式,傳入的參數是上層的輸出,但是都會出現以下的錯誤:
ValueError:
The following Variables were created within a Lambda layer (lambda)
but are not tracked by said layer:
<tf.Variable 'lambda/dense/kernel:0' shape=(16, 2) dtype=float32>
<tf.Variable 'lambda/dense_1/kernel:0' shape=(2, 16) dtype=float32>
<tf.Variable 'lambda/conv2d/kernel:0' shape=(7, 7, 2, 1) dtype=float32>
<tf.Variable 'lambda/conv2d/bias:0' shape=(1,) dtype=float32>
The layer cannot safely ensure proper Variable reuse across multiple
calls, and consquently this behavior is disallowed for safety. Lambda
layers are not well suited to stateful computation; instead, writing a
subclassed Layer is the recommend way to define layers with
Variables.
透過關鍵字上網找解決方法兩天了都沒能解決,請問有人能替我解答嗎?感激不盡