In [ ]:
#!pip install tensorflow
In [ ]:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import tensorflow as tf
from tensorflow.keras import layers, models
In [ ]:
from keras.datasets import mnist
(x_train_image,y_train_label),(x_test_image,y_test_label)=mnist.load_data()
print('train data= ',x_train_image.shape)
print('test data=', x_test_image.shape)
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11490434/11490434 ━━━━━━━━━━━━━━━━━━━━ 1s 0us/step
train data=  (60000, 28, 28)
test data= (10000, 28, 28)
In [ ]:
import matplotlib.pyplot as plt

# 建立函數要來畫多圖的
def plot_images_labels_prediction(images,labels,prediction,idx,num=10):
  # 設定顯示圖形的大小
  fig= plt.gcf()
  fig.set_size_inches(12,14)
  # 最多25張
  if num>25:num=25
  # 一張一張畫
  for i in range(0,num):
    # 建立子圖形5*5(五行五列)
    ax=plt.subplot(5,5,i+1)
    # 畫出子圖形
    ax.imshow(images[idx],cmap='binary')
    # 標題和label
    title="label=" +str(labels[idx])
    # 如果有傳入預測結果也顯示
    if len(prediction)>0:
      title+=",predict="+str(prediction[idx])
    # 設定子圖形的標題大小
    ax.set_title(title,fontsize=10)
    # 設定不顯示刻度
    ax.set_xticks([]);ax.set_yticks([])
    idx+=1
  plt.show()
plot_images_labels_prediction(x_train_image,y_train_label,[],0,10)
No description has been provided for this image
In [ ]:
#x_Train=x_train_image.reshape(60000,784).astype('float32')
#x_Test=x_test_image.reshape(10000,784).astype('float32')


# 由於是圖片最大的是255,所以全部除以255,使其變成0-1的數值
x_Train_normalize=x_train_image/255
x_Test_normalize=x_test_image/255
In [ ]:
# Build the CNN model
model = models.Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.Flatten(),
    layers.Dense(32, activation='relu'),
    layers.Dense(10, activation='softmax')
])

# Compile the model
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

# Train the model
history = model.fit(x_Train_normalize, y_train_label, epochs=10, validation_split=0.1)
/usr/local/lib/python3.10/dist-packages/keras/src/layers/convolutional/base_conv.py:107: UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When using Sequential models, prefer using an `Input(shape)` object as the first layer in the model instead.
  super().__init__(activity_regularizer=activity_regularizer, **kwargs)
Epoch 1/10
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 28s 16ms/step - accuracy: 0.8523 - loss: 0.4666 - val_accuracy: 0.9808 - val_loss: 0.0674
Epoch 2/10
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 26s 15ms/step - accuracy: 0.9779 - loss: 0.0698 - val_accuracy: 0.9838 - val_loss: 0.0520
Epoch 3/10
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 41s 15ms/step - accuracy: 0.9851 - loss: 0.0477 - val_accuracy: 0.9860 - val_loss: 0.0485
Epoch 4/10
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 26s 16ms/step - accuracy: 0.9880 - loss: 0.0372 - val_accuracy: 0.9878 - val_loss: 0.0447
Epoch 5/10
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 26s 15ms/step - accuracy: 0.9914 - loss: 0.0275 - val_accuracy: 0.9863 - val_loss: 0.0527
Epoch 6/10
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 41s 15ms/step - accuracy: 0.9934 - loss: 0.0219 - val_accuracy: 0.9888 - val_loss: 0.0484
Epoch 7/10
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 41s 15ms/step - accuracy: 0.9945 - loss: 0.0169 - val_accuracy: 0.9878 - val_loss: 0.0496
Epoch 8/10
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 26s 16ms/step - accuracy: 0.9965 - loss: 0.0123 - val_accuracy: 0.9892 - val_loss: 0.0492
Epoch 9/10
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 38s 23ms/step - accuracy: 0.9969 - loss: 0.0091 - val_accuracy: 0.9882 - val_loss: 0.0522
Epoch 10/10
1688/1688 ━━━━━━━━━━━━━━━━━━━━ 27s 16ms/step - accuracy: 0.9971 - loss: 0.0080 - val_accuracy: 0.9855 - val_loss: 0.0730
In [ ]:
# Evaluate the model
test_loss, test_acc = model.evaluate(x_Test_normalize, y_test_label)
print(f"Test accuracy: {test_acc:.4f}")
313/313 ━━━━━━━━━━━━━━━━━━━━ 2s 5ms/step - accuracy: 0.9834 - loss: 0.0550
Test accuracy: 0.9859
In [ ]:
fig, ax = plt.subplots(1, 2, figsize=(8, 3))  # Create a 1x2 grid of subplots

# Plot accuracy
ax[0].plot(np.arange(1,11),history.history['accuracy'], label='Training Accuracy', marker='o')
ax[0].plot(np.arange(1,11),history.history['val_accuracy'], label='Validation Accuracy', marker='x')
ax[0].set_title('Accuracy')
ax[0].set_xlabel('Epoch')
ax[0].set_ylabel('Accuracy')
ax[0].legend(loc='lower right')
ax[0].set_ylim([0.9, 1.0])
ax[0].grid(True)

# Plot loss
ax[1].plot(np.arange(1,11),history.history['loss'], label='Training Loss', marker='o')
ax[1].plot(np.arange(1,11),history.history['val_loss'], label='Validation Loss', marker='x')
ax[1].set_title('Loss')
ax[1].set_xlabel('Epoch')
ax[1].set_ylabel('Loss')
ax[1].legend(loc='upper right')
ax[1].set_ylim([0,0.2])
ax[1].grid(True)

plt.tight_layout()  # Adjust subplot spacing
plt.show()
No description has been provided for this image
In [ ]:
from sklearn import datasets, svm, metrics
# Predict the value of the digit on the test subset
predicted = np.argmax(model.predict(x_Test_normalize), axis=1)
# Display the confusion matrix
disp = metrics.ConfusionMatrixDisplay.from_predictions(y_test_label, predicted,cmap='CMRmap_r')
accu = metrics.accuracy_score(y_test_label, predicted)
disp.figure_.suptitle("Confusion Matrix of CNN")
#print(f"Confusion matrix:\n{disp.confusion_matrix}")
print('Overall Acuracy:{:.4}'.format(accu))
313/313 ━━━━━━━━━━━━━━━━━━━━ 2s 5ms/step
Overall Acuracy:0.9859
No description has been provided for this image
In [1]:
'''
for layer in model.layers:
    print(f"Layer: {layer.name}")
    weights = layer.get_weights()  # Returns [weights, biases] or just [weights] depending on the layer
    if weights:  # Check if the layer has parameters
        for param in weights:
            print(param.shape)
            print(param)
'''
Out[1]:
'\nfor layer in model.layers:\n    print(f"Layer: {layer.name}")\n    weights = layer.get_weights()  # Returns [weights, biases] or just [weights] depending on the layer\n    if weights:  # Check if the layer has parameters\n        for param in weights:\n            print(param.shape)\n            print(param)\n'
In [ ]:
import matplotlib.pyplot as plt
import numpy as np

# Get the weights of the first Conv2D layer
filters, biases = model.layers[0].get_weights()
print(filters.shape)
# Normalize filter values for visualization
#filters = (filters - filters.min()) / (filters.max() - filters.min())

# Plot the filters
num_filters = filters.shape[-1]
fig, axes = plt.subplots(1, num_filters, figsize=(20, 8))
print(filters[:,:,0,0])
for i in range(num_filters):
    ax = axes[i]
    print(filters[:,:,0,i])
    img = ax.imshow(filters[:, :, 0, i], cmap='gray')
    ax.axis('off')
    img.set_clim(-1, 1)  # Equivalent to caxis in MATLAB
plt.show()
(3, 3, 1, 16)
[[ 0.21415356 -0.30885267 -0.6519661 ]
 [ 0.5058699   0.23093837 -0.22200817]
 [ 0.19406222  0.12560114  0.19133475]]
[[ 0.21415356 -0.30885267 -0.6519661 ]
 [ 0.5058699   0.23093837 -0.22200817]
 [ 0.19406222  0.12560114  0.19133475]]
[[ 0.13758168  0.2611158   0.13047461]
 [-0.10168032  0.20637156  0.26559454]
 [-0.54037744 -0.26272145 -0.0892069 ]]
[[-0.45447803  0.110102    0.2370891 ]
 [ 0.01917345  0.47166994  0.04347578]
 [ 0.1570626  -0.07592573 -0.35444763]]
[[-0.6938688  -0.05676343  0.5356932 ]
 [-0.33486983  0.20785178  0.28816774]
 [-0.20069587  0.09422254  0.07748269]]
[[ 0.11412303  0.26057878  0.18961528]
 [-0.10704428  0.03975838  0.13112152]
 [-0.4502424  -0.19582744 -0.438199  ]]
[[ 0.31722534  0.22499524  0.16056031]
 [ 0.05747228  0.25339037  0.17074552]
 [ 0.03227609  0.13687608 -0.1061388 ]]
[[ 0.07825576  0.40836647  0.4523092 ]
 [-0.2057633  -0.08299793  0.26804474]
 [-0.7127716  -0.2987081  -0.1287441 ]]
[[ 0.07901289  0.07470872  0.31638077]
 [ 0.25074646  0.2950283   0.03148688]
 [-0.28968665 -0.46267453 -0.4003041 ]]
[[-0.21390766 -0.24693145  0.17037503]
 [-0.09921002  0.29982483  0.29925054]
 [-0.12932292  0.1117539  -0.14127398]]
[[-0.09663841  0.0290889   0.08615615]
 [ 0.18088852  0.34550953 -0.2610065 ]
 [ 0.11386446 -0.11024614 -0.2258369 ]]
[[-0.2561223   0.18832779 -0.0936925 ]
 [-0.23700483  0.3406391  -0.07570899]
 [-0.01622296  0.04902215 -0.03053573]]
[[-0.31174532  0.28981948  0.12505637]
 [ 0.23953749  0.42738876 -0.22290403]
 [ 0.1021284  -0.08801013 -0.510321  ]]
[[ 0.25381076  0.13187167  0.05188906]
 [-0.13400862  0.20843098  0.05804522]
 [-0.25477076  0.22373801  0.16677879]]
[[ 0.3697697   0.32917467  0.28125772]
 [-0.3935351  -0.66763455 -0.60329956]
 [-0.16455817  0.15415668  0.18668981]]
[[ 0.04671665  0.43674755  0.20692779]
 [ 0.22960134  0.14111868 -0.3492528 ]
 [-0.01214183 -0.18648607 -0.33370447]]
[[-0.37765288 -0.30157796  0.47008973]
 [ 0.2407328  -0.44805565  0.13863577]
 [ 0.29043388 -0.00142932 -0.3981033 ]]
No description has been provided for this image
In [ ]:
# Visualize tht second layer
# Get the weights of the second Conv2D layer
filters, biases = model.layers[2].get_weights()

# Normalize filter values for visualization
#filters = (filters - filters.min()) / (filters.max() - filters.min())
print(filters.shape)
# Plot the filters
num_filters = filters.shape[-1]
print(num_filters)
fig, axes = plt.subplots(2, int(num_filters/2), figsize=(20, 3))

for i in range(num_filters):
    #ax = axes[i]
    ax = axes[i // int(np.ceil(num_filters / 2))][i % int(np.ceil(num_filters / 2))]
    #print(filters[:,:,0,i])
    img = ax.imshow(filters[:, :, 0, i], cmap='gray')
    ax.axis('off')
    img.set_clim(-1, 1)  # Equivalent to caxis in MATLAB
plt.show()

fig, axes = plt.subplots(2, int(num_filters/2), figsize=(20, 3))
for i in range(num_filters):
    #ax = axes[i]
    ax = axes[i // int(np.ceil(num_filters / 2))][i % int(np.ceil(num_filters / 2))]
    #print(filters[:,:,0,i])
    img = ax.imshow(filters[:, :, 1, i], cmap='gray')
    ax.axis('off')
    img.set_clim(-1, 1)  # Equivalent to caxis in MATLAB
plt.show()
(3, 3, 16, 32)
32
No description has been provided for this image
No description has been provided for this image
In [ ]:
import seaborn as sns

# Get weights of the first Dense layer
dense_weights, dense_biases = model.layers[-2].get_weights()

# Visualize as a heatmap
plt.figure(figsize=(8, 24))
sns.heatmap(dense_weights, cmap='coolwarm', cbar=True)
plt.title("Dense Layer Weights")
plt.xlabel("Neurons")
plt.ylabel("Input Features")
plt.show()
No description has been provided for this image
In [ ]:
# Get weights of the first Dense layer
dense_weights, dense_biases = model.layers[-1].get_weights()

# Visualize as a heatmap
plt.figure(figsize=(4, 6))
sns.heatmap(dense_weights, cmap='coolwarm', cbar=True)
plt.title("Dense Layer Weights")
plt.xlabel("Neurons")
plt.ylabel("Input Features")
plt.show()
No description has been provided for this image
In [ ]:
from tensorflow.keras.utils import plot_model

plot_model(model, to_file='CNN_MNIST_Model.png', show_shapes=True, show_layer_names=True)
Out[ ]:
No description has been provided for this image
In [ ]:
img = x_test_image[0,:,:]
Input = img.reshape(-1, 28, 28, 1)

output = model.predict(Input)
print(output.shape)
plt.imshow(img)
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 120ms/step
(1, 10)
Out[ ]:
<matplotlib.image.AxesImage at 0x7f1a520af550>
No description has been provided for this image
In [ ]:
from tensorflow.keras.models import Model

# Create a model that outputs the activations of the first Conv2D layer
layer_outputs = model.layers[0].output  # Get the output of the first Conv2D layer
print(model.inputs)

activation_model = Model(inputs=model.inputs, outputs=layer_outputs)
[<KerasTensor shape=(None, 28, 28, 1), dtype=float32, sparse=False, name=keras_tensor>]
In [ ]:
# Use a sample image from your dataset (ensure it has the correct shape)
sample_image = np.expand_dims(x_test_image[0], axis=0)  # Reshape to (1, 28, 28, 1)

# Pass the image through the model to get the activations
feature_maps = activation_model.predict(sample_image)

# Print the shape of the resulting feature maps
print("Feature maps shape:", feature_maps.shape)  # Shape: (1, 26, 26, num_filters)

# Visualize the first feature map

fig, axes = plt.subplots(2,8, figsize=(20, 8))
num_filters =16
for i in range(num_filters):
    ax = axes[i // int(np.ceil(num_filters / 2))][i % int(np.ceil(num_filters / 2))]
    img = ax.imshow(feature_maps[0, :, :, i], cmap='coolwarm')
    ax.axis('off')
    img.set_clim(-1, 1)
plt.show()
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 59ms/step
Feature maps shape: (1, 26, 26, 16)
No description has been provided for this image
In [ ]:
# Create a model that outputs the activations of the first Conv2D layer
layer_outputs = model.layers[2].output  # Get the output of the first Conv2D layer
print(model.inputs)

activation_model = Model(inputs=model.inputs, outputs=layer_outputs)
[<KerasTensor shape=(None, 28, 28, 1), dtype=float32, sparse=False, name=keras_tensor>]
In [ ]:
# Use a sample image from your dataset (ensure it has the correct shape)
sample_image = np.expand_dims(x_test_image[0], axis=0)  # Reshape to (1, 28, 28, 1)

# Pass the image through the model to get the activations
feature_maps = activation_model.predict(sample_image)

# Print the shape of the resulting feature maps
print("Feature maps shape:", feature_maps.shape)  # Shape: (1, 26, 26, num_filters)

# Visualize the first feature map
num_filters =32

fig, axes = plt.subplots(2,int(num_filters/2), figsize=(20, 3))

for i in range(num_filters):
    ax = axes[i // int(np.ceil(num_filters / 2))][i % int(np.ceil(num_filters / 2))]
    img = ax.imshow(feature_maps[0, :, :, i], cmap='coolwarm')
    ax.axis('off')
    img.set_clim(-1, 1)
plt.show()
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 377ms/step
Feature maps shape: (1, 11, 11, 32)
No description has been provided for this image