I am trying to create a binary image classification model using the malaria dataset from NIH (National Library of Medicine) which contains approximately 27,000 images of each class (infected/uninfected).
There seems to be overfitting and I have tried to play around with different batch sizes, steps per epoch/validation steps, using different hidden layers and adding callbacks etc. The graph always shows a straight line that is either dramatically increasing or decreasing, rather than increasing steadily with some decreases as it learns (which from my understanding, is how it should be). Below is an example, most turn out somewhat similar to this.
I'm new to deep learning, I have read a lot about overfitting and trying to find a solution. But I think there must be something I'm doing wrong and/or misunderstanding. If someone is able to spot something that doesn't look right and is able to point me in the right direction, it would be greatly appreciated!
from keras.layers import MaxPooling2D, Conv2D, Flatten, Dense, Dropout
from keras_preprocessing.image import ImageDataGenerator
from sklearn.model_selection import train_test_split
from keras.models import Sequential
import matplotlib.pyplot as plt
import constants as c
import numpy as np
import keras
# Clear session and instantiate model
keras.backend.clear_session()
model = Sequential()
# Load images & labels
cells = np.load(c.cells_path)
labels = np.load(c.labels_path)
# Shuffle the entire dataset
n = np.arange(cells.shape[0])
np.random.shuffle(n)
# Update numpy files with shuffled data
cells = cells[n]
labels = labels[n]
# Split the dataset into train/validation/test
train_x, test_x, train_y, test_y = train_test_split(cells, labels, test_size=1 - c.train_ratio, shuffle=False)
val_x, test_x, val_y, test_y = train_test_split(test_x, test_y, test_size=c.test_ratio / (c.test_ratio + c.val_ratio),
shuffle=False)
# The amount of images in each set
print('Training data shape: ', train_x.shape)
print('Validation data shape: ', val_x.shape)
print('Testing data shape: ', test_x.shape)
# Neural network
model.add(Conv2D(32, (3, 3), input_shape=c.input_shape, activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(units=64, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(units=1, activation='sigmoid'))
# Compile the model
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
# Data augmentation
train_datagen = ImageDataGenerator(rescale=1. / 255,
rotation_range=20,
width_shift_range=0.05,
height_shift_range=0.05,
shear_range=0.05,
zoom_range=0.05,
horizontal_flip=True,
fill_mode='nearest')
validation_datagen = ImageDataGenerator(rescale=1. / 255)
testing_datagen = ImageDataGenerator(rescale=1. / 255)
training_dataset = train_datagen.flow(train_x, train_y, batch_size=32)
validation_dataset = validation_datagen.flow(val_x, val_y, batch_size=32)
testing_dataset = validation_datagen.flow(val_x, val_y, batch_size=32)
# Add callbacks to prevent overfitting
es = EarlyStopping(monitor='accuracy',
min_delta=0,
patience=2,
verbose=0,
mode='max')
rlrop = ReduceLROnPlateau(monitor='val_loss',
factor=0.2,
patience=0.5,
min_lr=0.001)
checkpoint = ModelCheckpoint("Model.h5")
# Perform backpropagation and update weights in model
history = model.fit_generator(training_dataset,
epochs=50,
validation_data=validation_dataset,
callbacks=[es, checkpoint, rlrop])
# Save model & weights
model.save_weights("Model_weights.h5")
model.save("Model.h5")
# Plot accuracy graph
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'val'], loc='upper left')
plt.show()
Doesn't seem to be a case of overfitting. Without looking much at it, would do the following:
leave the filters at 32 in the fist layer and gradually double on every following convolutional layer.
Since the variations in the images aren't that significant lower the Dropout rate.
Oddly enough, this is something I built when I was first trying Tensorflow 2.0, you can check it here.
Related
My first go at training a model on a dataset, this is the data from a pandas dataset
In [16]: exists.head()
Out[16]:
id url \
1 0a58358a2afd3e4e http://lh6.ggpht.com/-igpT6wu0mIA/ROV8HnUuABI/...
2 6b2bb500b6a38aa0 http://lh6.ggpht.com/-vKr5G5MEusk/SR6r6SJi6mI/...
3 b399f09dee9c3c67 https://lh3.googleusercontent.com/-LOW2cjAqubA...
4 19ace29d77a5be66 https://lh5.googleusercontent.com/-tnmSXwQcWL8...
5 2c9c54b62f0a6a37 https://lh5.googleusercontent.com/-mEaSECO7D-4...
landmark_id exists filename
1 6651 True training_images/0a58358a2afd3e4e.jpg
2 11284 True training_images/6b2bb500b6a38aa0.jpg
3 8429 True training_images/b399f09dee9c3c67.jpg
4 6231 True training_images/19ace29d77a5be66.jpg
5 10400 True training_images/2c9c54b62f0a6a37.jpg
it shows the training image in filename and the classification name in landmark_id
This is the way I've written the model to train it
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.callbacks import EarlyStopping
from keras.callbacks import ModelCheckpoint
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(3, 150, 150)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten()) # this converts our 3D feature maps to 1D feature vectors
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(5))
model.add(Dense(activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
monitor = EarlyStopping(monitor='val_loss', min_delta=1e-3, patience=5, verbose=0, mode='auto')
checkpointer = ModelCheckpoint(filepath="best_weights.hdf5", verbose=0, save_best_only=True) # save best model
model.compile(loss='binary_crossentropy',
optimizer='adam',
callbacks=[monitor,checkpointer],
verbose=0,
epochs=1000,
metrics=['accuracy'])
batch_size = 16
# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1./255)
# this is a generator that will read pictures found in
# subfolers of 'data/train', and indefinitely generate
# batches of augmented image data
train_generator = train_datagen.flow_from_directory(
'training_images', # this is the target directory
target_size=(150, 150), # all images will be resized to 150x150
batch_size=batch_size,
class_mode='binary') # since we use binary_crossentropy loss, we need binary labels
# this is a similar generator, for validation data
validation_generator = test_datagen.flow_from_directory(
'test_images',
target_size=(150, 150),
batch_size=batch_size,
class_mode='binary')
model.fit_generator(
train_generator,
steps_per_epoch=2000 // batch_size,
epochs=50,
validation_data=validation_generator,
validation_steps=800 // batch_size)
model.load_weights('best_weights.hdf5') # load weights from best model
model.save('last_model.h5')
I don't know how I'm supposed to put the labels to the image while training. So when it trains and loops through the images in the training_images folder.
Samuel,
Your FitGenerator is getting the training input labels from the flow_from_directory method. This method uses the folder structure to determine the training categories. Since your class is binary, and you have a single sigmoid output, I'm assuming that you are doing a Hot Dog - Not Hot Dog type of classification where you just want a single probability value.
The other hint for me that you care about the single probability that something is a category or not is that your loss function is binary_crossentropy.
Check your training data folder. Look at how the data is organized. This should be set up such that the data is organized correctly.
You seem to be hinting that you want to create multiple labels (e.g., car, boat, train). If this is the case, you will want to create those folders under train and validate and put the images in the respective folder. You will need to change several things about your model if you do this though. Your loss, output layer size, and output layer activations will change accordingly.
I am currently working on handwritten digit recognition of regional languages. Currently, I am focusing on Oriya. I test the MNIST dataset through the CNN model and I am trying to apply the model on my Oriya dataset. Model is performing poorly. It is giving the wrong predictions. I have a dataset of 4971 samples.
How to improve the accuracy?
Here's my code:
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.convolutional import Convolution2D, MaxPooling2D
from keras.optimizers import SGD,RMSprop,adam
from keras.utils import np_utils
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import os
import theano
from PIL import Image
from numpy import *
# SKLEARN
from sklearn.utils import shuffle
from sklearn.cross_validation import train_test_split
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)
# input image dimensions
img_rows, img_cols = 28, 28
# number of channels
img_channels = 1
path2 = '/home/saumya/Desktop/Oriya/p' #path of folder of images
imlist = os.listdir(path2)
im1 = array(Image.open('/home/saumya/Desktop/Oriya/p' + '/'+ imlist[0])) # open one image to get size
m,n = im1.shape[0:2] # get the size of the images
imnbr = len(imlist) # get the number of images
# create matrix to store all flattened images
immatrix = array([array(Image.open('/home/saumya/Desktop/Oriya/p' + '/'+ im2)).flatten()
for im2 in imlist],'f')
label=np.ones((num_samples,),dtype = int)
label[1:503]=0
label[503:1000]=1
label[1000:1497]=2
label[1497:1995]=3
label[1995:2493]=4
label[2493:2983]=5
label[2983:3483]=6
label[3483:3981]=7
label[3981:4479]=8
label[4479:4972]=9
print(label[1000])
data,Label = shuffle(immatrix,label, random_state=2)
train_data = [data,Label]
img=immatrix[2496].reshape(img_rows,img_cols)
plt.imshow(img)
plt.show()
(X, y) = (train_data[0],train_data[1])
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=4)
X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols)
X_test = X_test.reshape(X_test.shape[0], 1, img_rows, img_cols)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
print('X_train shape:', X_train.shape)
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')
X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype('float32')
X_test = X_test.reshape(X_test.shape[0], 1, 28, 28).astype('float32')
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_test.shape[1]
def baseline_model():
# create model
model = Sequential()
model.add(Conv2D(32, (3,3), input_shape=(1, 28, 28), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
#model.add(Conv2D(64, (5, 5), input_shape=(1, 10, 10), activation='relu'))
#model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(num_classes, activation='softmax', name = 'first_dense_layer'))
# Compile model
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
# build the model
model = baseline_model()
# Fit the model
hist=model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=30, batch_size=100, verbose=2)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("CNN Error: %.2f%%" % (100-scores[1]*100))
score = model.evaluate(X_test, y_test, verbose=0)
print('Test Loss:', score[0])
print('Test accuracy:', score[1])
test_image = X_test[0:1]
print (test_image.shape)
print(model.predict(test_image))
print(model.predict_classes(test_image))
print(y_test[0:1])
# define the larger model
def larger_model():
# create model
model = Sequential()
model.add(Conv2D(30, (5, 5), input_shape=(1, 28, 28), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(15, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(50, activation='relu', name='first_dense_layer'))
model.add(Dense(num_classes, activation='softmax'))
# Compile model
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
# build the model
model = larger_model()
# Fit the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=200)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Large CNN Error: %.2f%%" % (100-scores[1]*100))
I am trying to resize my model using opencv, it is generating the following error:
/root/mc-x64-2.7/conda-bld/opencv-3_1482254119970/work/opencv-3.1.0/modules/imgproc/src/imgwarp.cpp:3229: error: (-215) ssize.area() > 0 in function resize
How to improve the accuracy?
A bit hard to give a detailed answer from what you posted, and without seeing some data sample, but still will attempt a stab at this. What I can see that may help improve you accuracy is:
Get more data. In Deep Learning one usually works with big amount of data, and models almost always improve when adding more data. If you can't obtain new data you may try to generate more samples with the ones you got, by adding noise or similar modifications.
I see you currently have 30 and 10 epochs on the training of your model. I suggest you increase the number of epochs, so your model has more time to converge. This also most of the times improves performance up to a point.
I also see that your batch size is 100 and 200 on your models. You can try reducing the batch size of your training process, so your training performs gradient update more times on each epoch (remember that you can even use batch_size=1 to upgrade your model for each sample, instead of batches).
Alternatively, you can try iteratively increasing the complexity and layers of your architecture and compare your performances. It is best to start with a simple model, train and test, and then add layers and nodes until you are satisfied with the results. I also see you have tried a hybrid convolutional and non-convolutional approach; you can well try starting with just one of the approaches before increasing the complexity of your architecture.
New to Keras, trying to reimplement this following binary image classification example from: https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html
It works for binary classification for me.
Rebuilding it for a 3-class classification I am getting the following dimensions mismatch error:
60 epochs=50,
61 validation_data=validation_generator,
---> 62 validation_steps=250 // batch_size)
ValueError: Error when checking target: expected activation_50 to have shape (None, 1) but got array with shape (16, 3)
This is my current implementation:
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K
K.set_image_dim_ordering('th')
batch_size = 16
# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1./255)
# this is a generator that will read pictures found in
# subfolers of 'data/train', and indefinitely generate
# batches of augmented image data
train_generator = train_datagen.flow_from_directory(
'F://train_data//', # this is the target directory
target_size=(150, 150), # all images will be resized to 150x150
batch_size=batch_size,
class_mode='categorical') # since we use binary_crossentropy loss, we need binary labels
# this is a similar generator, for validation data
validation_generator = test_datagen.flow_from_directory(
'F://validation_data//',
target_size=(150, 150),
batch_size=batch_size,
class_mode='categorical')
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(3, 150, 150)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), data_format="channels_first"))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), data_format="channels_first"))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), data_format="channels_first"))
model.add(Flatten()) # this converts our 3D feature maps to 1D feature vectors
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('softmax')) # instead of sigmoid
model.compile(loss='mean_squared_error',
optimizer='adam',
metrics=['accuracy'])
# another loss: sparse_categorical_crossentropy
model.fit_generator(
train_generator,
steps_per_epoch=1800 // batch_size,
epochs=50,
validation_data=validation_generator,
validation_steps=250 // batch_size)
So far I have changed the activation function of the output layer from sigmoid to softmax. Changed class_mode from binary to categorical. Can't seem to find the problem.
Also, I am aware of similar questions on StackOverflow:
Multi-Output Multi-Class Keras Model
Train multi-class image classifier in Keras
Multi-class classification using keras
But none of the solutions helped me.
You need to change the final Dense layer to model.add(Dense(3)). Softmax activation expects the units in the Dense layer to match the number of classes.
Also, if you are going to use loss='sparse_categorical_crossentropy', remember to change class_mode into 'sparse'. Your current setting, class_mode='categorical', should be used with loss='categorical_crossentropy'.
My model is training and is not predicting the same output everytime but it is not converging, I mean in the 30th epoch the validation accuracy = 65% and, in the 31st, the validation accuracy = 38%, for example. Also, the loss is around 27 to 29 and is not decreasing at all (while fitting the model).
Just for introduction:
Problem: Recognizing if a signature is genuine or forgery.
Dataset: GPDS database offline signature which consists of 4000 users => 24 genuine / 30 forgery per user.
Input of the net: The sum of two signature images of the same user. Genuine + Forgery = False (class 0) or Genuine + Genuine = True (class 1) .
Now, Im training with around 130k images (just a small part of the approximately 4 million possible sum images) which 100k are Genuine+Forgery and 30k are Genuine+Genuine from around 150 users in total. Anyway, Im using class weights in training (model.fit_generator).
There is one concern about the problem:
The size of the images varies but normally it is around 1200x400 pixels. It is huge for the memory and the training lasts a looong time so I used the attribute target_size of the function flow_from_directory which resizes the image to 100x100 pixels. Also, Im training for the maximum of 100 epochs.
Im using an instance in Amazon with 1 GPU, 8 CPUs, 15Gb RAM,
The code is below:
import keras
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras import backend as K
from keras.preprocessing.image import ImageDataGenerator
K.set_image_dim_ordering('th')
train_datagen = ImageDataGenerator(rescale=1./255, shear_range=0.2,
zoom_range=0.2, horizontal_flip=True)
train_generator = train_datagen.flow_from_directory('C:\Users\lucas\Desktop\DL\TrainGenuineForgery', target_size=(100, 100), color_mode="grayscale", batch_size=10, class_mode='binary')
validation_datagen = ImageDataGenerator(rescale=1./255)
validation_generator = validation_datagen.flow_from_directory('C:\Users\lucas\Desktop\DL\Validation', target_size=(100, 100), color_mode="grayscale", batch_size=10, class_mode='binary')
model = Sequential()
model.add(Conv2D(96, (11, 11), input_shape=(1, 100, 100), activation='relu', data_format='channels_first'))
model.add(MaxPooling2D(pool_size=(3, 3)))
model.add(Conv2D(256, (5, 5), activation='relu'))
model.add(MaxPooling2D(pool_size=(3, 3)))
model.add(Conv2D(384, (3, 3), activation='relu'))
model.add(Conv2D(256, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(3, 3)))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(4096, activation='relu'))
model.add(Dense(2, activation='softmax'))
optAdadelta = keras.optimizers.Adadelta(lr=1.0, rho=0.95, epsilon=1e-08, decay=0.0)
model.compile(loss='sparse_categorical_crossentropy', optimizer=optAdadelta, metrics=['accuracy'])
history = model.fit_generator(train_generator, steps_per_epoch=13000, epochs=100, validation_data=validation_generator, validation_steps=100, class_weight = {0:29,1:71})
I would like to know if the image resizing can be a serious problem, maybe training not enough, maybe the approach of the solution is not good, maybe not enough dataset samples, maybe not adequate optimizer.
Thanks for your attention!
Lucas
I have created a simple cat and dog image classification (convolution neural network). Having training data of 7,000 each class and validation data of 5,500 each class.
My problem is my system is not completing all epoch. I would really appreciate if someone could explain the proportion or criteria of selecting nb_epoch, samples_per_epoch and nb_val_samples values to get maximum out of given amount of training and validation data.
Following is my code:
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Convolution2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.callbacks import EarlyStopping
import numpy as np
from keras.preprocessing import image
from keras.utils.np_utils import probas_to_classes
model=Sequential()
model.add(Convolution2D(32, 5,5, input_shape=(28,28,3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Convolution2D(32,3,3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Flatten())
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(2))
model.add(Activation('softmax'))
train_datagen=ImageDataGenerator(rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen=ImageDataGenerator(rescale=1./255)
train_generator=train_datagen.flow_from_directory(
r'F:\data\train',
target_size=(28,28),
classes=['dog','cat'],
batch_size=10,
class_mode='categorical',
shuffle=True)
validation_generator=test_datagen.flow_from_directory(
r'F:\data\validation',
target_size=(28, 28),
classes=['dog','cat'],
batch_size=10,
class_mode='categorical',
shuffle=True)
model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
early_stopping=EarlyStopping(monitor='val_loss', patience=2)
model.fit_generator(train_generator,verbose=2, samples_per_epoch=650, nb_epoch=100, validation_data=validation_generator, callbacks=[early_stopping],nb_val_samples=550)
json_string=model.to_json()
open(r'F:\data\mnistcnn_arc.json','w').write(json_string)
model.save_weights(r'F:\data\mnistcnn_weights.h5')
score=model.evaluate_generator(validation_generator, 1000)
print('Test score:', score[0])
print('Test accuracy:', score[1])
img_path = 'F:/abc.jpg'
img = image.load_img(img_path, target_size=(28, 28))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
y_proba = model.predict(x)
y_classes = probas_to_classes(y_proba)
print(train_generator.class_indices)
print(y_classes)
samples_per_epoch is usually setted as:
samples_per_epoch=train_generator.nb_samples
This way you are ensuring that every epoch you are seeing a number of samples equal to the size of your training set. This means that you are seeing all of your training samples at every epoch.
nb_epoch is pretty much up to you. It determines how many times you iterate over a number defined by samples_per_epoch.
To give you an example, in your code right now your model is 'seeing' (nb_epoch * samples_per_epoch) images, wich in this case are 65000 images.
nb_val_samples determines over how many validation samples your model is evaluated after finishing every epoch. It is up to you aswell. The usual thing is to set:
nb_val_samples=validation_generator.nb_samples
In order to evaluate your model on the full validation set.
batch_size determines how many images are feeded at the same time to your gpu (or cpu). Rule of dumb is to set the largest batch_size that your gpu's memmory allows. Ideal batch_size is active area of research nowdays, but usually a bigger batch_size will work better.