iT邦幫忙

0

CNN 模型中怎麼呼叫函式

  • 分享至 

  • xImage
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')

最近閱讀一篇論文
https://openaccess.thecvf.com/content_ECCV_2018/papers/Sanghyun_Woo_Convolutional_Block_Attention_ECCV_2018_paper.pdf

閱讀完後試著實作在網路上找到網友放在 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.

透過關鍵字上網找解決方法兩天了都沒能解決,請問有人能替我解答嗎?感激不盡

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

1
I code so I am
iT邦高手 1 級 ‧ 2023-07-11 07:34:42
最佳解答

Sequential model及Function API不可混用,應二擇一,建構模型,可參考https://keras.io/guides/functional_api/ 。
例如,

x1 = GlobalAveragePooling2D()(x)

表示 GlobalAveragePooling2D 接在 x 神經層之後,例如 cbam 寫法。

vuj8104 iT邦新手 4 級 ‧ 2023-07-11 10:57:13 檢舉

問題解決了,謝謝您!

👍👍👍

我要發表回答

立即登入回答