conv2d Dimensions & Train Model

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Dominik72
User
Beiträge: 3
Registriert: Samstag 7. November 2020, 10:57

Hi,

ich versuche meine erste Image Classification auf Jupyter Notebooks hinzukriegen. Verwendet habe mnist.npz. Bist zum Trainieren des Models lief alles (dank vielen Youtube Videos und Foren Beiträgen) sehr gut. Bei der Architektur habe ich wie überall verwiesen, model = Sequential() definiert. Bei der ganzen Architektur kommt kein Fehler. Jedoch beim Trainieren, hist = model.fit(x_train, y_train_one_hot,
batch_size = 256,
epochs = 10,
validation_split = 0.2)

kommt der Fehler, dass meine Dimension falsch ist (ValueError: Error when checking input: expected conv2d_9_input to have 4 dimensions, but got array with shape (60000, 28, 28). Bei anderen Tutorials werden die Dimensionen immer klar definiert. Ich verstehe jedoch nicht wie viele Dimensionen meine Bilder haben, da auch bei einem der ersten Schritte, shape Trainings und Tests, keine Dimension ausgewiesen wurde wie zum Beispiel bei anderen Tutorials. Kann mir jemand sagen, wo ich meinen Denkfehler habe?Bild[/img]
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Hallo Dominik,
um dir da helfen zu können, wo an welcher Stelle der Fehler liegt, bräuchte ich den kompletten Code.
Du kannst den im Vollständigen Editor nach Klick auf den Button </> zwischen [ code]hier Code einfügen[ /code] einfügen.
Das sähe dann so aus:

Code: Alles auswählen

import tensorflow as tf
# etc
Bitte keine Bilder hochladen.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Dominik72
User
Beiträge: 3
Registriert: Samstag 7. November 2020, 10:57

Code: Alles auswählen

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Sequential

from tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D, Dropout
from tensorflow.keras import layers
from tensorflow.keras.utils import to_categorical
import tensorflow_datasets as tfds
import seaborn as sns

import os # noch rausfinden, was dieses Package bringt
import PIL

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.style.use("fivethirtyeight")

import sklearn
from sklearn.metrics import classification_report  
from sklearn.metrics import confusion_matrix
import sklearn.metrics as metrics  

tf.keras.datasets.mnist.load_data(path="mnist.npz")
Data1 = tf.keras.datasets.mnist.load_data()
Data1

builder = tfds.builder("Data1")
info = builder.info

(x_train, y_train), (x_test, y_test) = Data1

print(type(x_train))
print(type(y_train))
print(type(x_test))
print(type(y_test))

print("x_train shape:", x_train.shape)
print("y_train shape:", y_train.shape)
print("x_test shape:", x_test.shape)
print("y_test shape:", y_test.shape)

y_train

df_y_train = pd.DataFrame(y_train)
df_y_train.head()

df_y_train[0].value_counts(sort=False)

df_y_train[0].value_counts(normalize=True)

y_test

df_y_test = pd.DataFrame(y_test)
df_y_test.head()

df_y_test[0].value_counts(sort=False)

df_y_test[0].value_counts(normalize=True)

index = 1
classification = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
print("the image class is:", classification[y_train[index][1]])

index = 1
x_train[index]

img = plt.imshow(x_train[index]) 

print("the image label is:", y_train[index])

print(y_train)
f, ax = plt.subplots(figsize=(16, 16))
sns.heatmap(index, annot=True, fmt='.1f', square=True, cmap="YlGnBu")
plt.show()

y_train_one_hot = to_categorical(y_train)
y_test_one_hot = to_categorical(y_test)

print(y_train_one_hot)

print("the one hot label is:", y_train_one_hot[index])

x_train = x_train / 255               
x_test = x_test / 255

model = Sequential()
model.add(Conv2D(28, (5,5), activation = "relu", input_shape = (28, 28, 2)))
model.add(MaxPooling2D(pool_size = (2, 2)))
model.add(Conv2D(28, (5,5), activation = "relu"))
model.add(MaxPooling2D(pool_size = (2, 2)))
model.add(Flatten())
model.add(Dense(1000, activation = "relu"))
model.add(Dropout(0.5))
model.add(Dense(500, activation = "relu"))
model.add(Dropout(0.5))
model.add(Dense(250, activation = "relu"))
model.add(Dense(10, activation = "softmax"))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])
              
hist = model.fit(x_train, y_train_one_hot, 
                 batch_size = 256,
                 epochs = 10,
                 verbose=1,
                 validation_split = 0.2, shuffle=True)
                 
from sklearn.naive_bayes import GaussianNB
gnb=GaussianNB()

model = gnb.fit(x_train, y_train_one_hot)

history = model.fit(x_train, y_train_one_hot, batch_size=32, epochs=10, 
                verbose=1,
                validation_split=0.2, shuffle=True)


Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Hallo Dominik,

du musst x_train und x_test in einen 4D Tensor umwandeln

Code: Alles auswählen

print(x_train.shape)
x_train = np.expand_dims(x_train, -1)
x_test = np.expand_dims(x_test, -1)
print(x_train.shape)
und die richtige Shape als input in die conv2d angeben

Code: Alles auswählen

model = Sequential()
model.add(Conv2D(28, (5,5), activation = "relu", input_shape = (28, 28, 1)))
dann läuft es.

Einige Tipps:
Du kannst die Lossfunktion sparse_categorical_crossentropy verwenden, dann brauchst du die Labels nicht in einen One-Hot-Vektor umwandeln.

Code: Alles auswählen

model.compile(loss=keras.losses.sparse_categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])
              
history = model.fit(x_train, y_train,  # hier kann der normale Labelvektor rein
                 batch_size = 32, epochs = 50, verbose=1,
                 validation_split = 0.2, shuffle=True)
Die batch_size ist bei dir mit 256 bei diesem Beispiel recht hoch gegriffen, da nimmt man üblicherweise so 32 oder max. 64

Habe mal bis 30 Epochen trainiert, da kam dein Modell bis auf 90% Validationaccuracy, da geht noch einiges, also Epochen hochsetzen.

Viel Spaß weiterhin.
Thomas
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Dominik72
User
Beiträge: 3
Registriert: Samstag 7. November 2020, 10:57

Hallo Thomas

danke vielmals für deine Hilfe.

Eine Frage habe ich zu meiner Predictions. Normalerweise wird ein "New_Image" hochgeladen, z.B. ein Photo von einer Katze um dann zuerst ein "Resize" zu machen für die Predictions. Ich benütze mnist.npz, kann ich dann ein beliebiges Photo von einer Zahl hochladen oder muss ich auf etwas bestimmtes achten?
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Das freut mich. Da dein Modell auf MNIST trainiert wurde, muss ja die input_shape 28x28x1 betragen. Wenn du ein Photo einer Zahl mit den Dimensionen 640x480 (VGA) auf 28x28 verkleinerst ,kommt da imho nichts brauchbares raus. Ich habe mir damals in Python mit Pygame ein Programm geschrieben, mit dem ich in ein 28x28 Raster malen konnte und habe das dann in das Modell eingespeist.

Das ganze hatte ich hier gesehen und das von Javascript nach Python umgesetzt.
https://www.youtube.com/watch?v=pqY_Tn2 ... h&index=21
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Antworten