I'm using the example from the tflearn github repository below, I've saved it and I'd like to reload the model with a different optimizer. Please help. Thanks.
init2=False
from __future__ import division, print_function, absolute_import
import tflearn
from tflearn.layers.core import input_data, dropout, fully_connected
from tflearn.layers.conv import conv_2d, max_pool_2d
from tflearn.layers.normalization import local_response_normalization
from tflearn.layers.estimator import regression
X1=sanit_tr
Y1=sanit_trlabels
testX=sanit_te
testY=sanit_telabels
# valid_dataset2=sanit_va
# valid_labels2=sanit_valabels
network = input_data(shape=[None, 28, 28, 1], name='input')
network = conv_2d(network, 32, 3, activation='relu', regularizer="L2")
network = max_pool_2d(network, 2)
network = local_response_normalization(network)
network = conv_2d(network, 64, 3, activation='relu', regularizer="L2")
network = max_pool_2d(network, 2)
network = local_response_normalization(network)
network = fully_connected(network, 128, activation='tanh')
network = dropout(network, 0.8)
network = fully_connected(network, 256, activation='tanh')
network = dropout(network, 0.8)
network = fully_connected(network, 10, activation='softmax')
network = regression(network, optimizer='Adagrad', learning_rate=0.1,
loss='categorical_crossentropy', name='target')
model = tflearn.DNN(network, tensorboard_verbose=0)
if not init2:
model.load('tflearn_model')
model.fit({'input': X1}, {'target': Y1}, n_epoch=2,
validation_set=({'input': testX}, {'target': testY}),
snapshot_step=100, show_metric=True, run_id='convnet_mnist')
model.save('tflearn_model')
This is where I'd like to load with new optimizer:
model.load('tflearn_model')
model.fit({'input': X1}, {'target': Y1}, n_epoch=2,
validation_set=({'input': testX}, {'target': testY}),
snapshot_step=100, show_metric=True, run_id='convnet_mnist')
model.save('tflearn_model')
I guss you just want to retrain the model. You just need to change the layer fully connected layer and redefine tflearn.DNN() before load model. And the whole code is:
init2=False
from __future__ import division, print_function, absolute_import
import tflearn
from tflearn.layers.core import input_data, dropout, fully_connected
from tflearn.layers.conv import conv_2d, max_pool_2d
from tflearn.layers.normalization import local_response_normalization
from tflearn.layers.estimator import regression
X1=sanit_tr
Y1=sanit_trlabels
testX=sanit_te
testY=sanit_telabels
# valid_dataset2=sanit_va
# valid_labels2=sanit_valabels
network = input_data(shape=[None, 28, 28, 1], name='input')
network = conv_2d(network, 32, 3, activation='relu', regularizer="L2")
network = max_pool_2d(network, 2)
network = local_response_normalization(network)
network = conv_2d(network, 64, 3, activation='relu', regularizer="L2")
network = max_pool_2d(network, 2)
network = local_response_normalization(network)
network = fully_connected(network, 128, activation='tanh')
network = dropout(network, 0.8)
network = fully_connected(network, 256, activation='tanh')
network = dropout(network, 0.8)
end_network = fully_connected(network, 10, activation='softmax')
network = regression(end_network, optimizer='Adagrad', learning_rate=0.1,
loss='categorical_crossentropy', name='target')
model = tflearn.DNN(network, tensorboard_verbose=0)
if not init2:
model.load('tflearn_model')
model.fit({'input': X1}, {'target': Y1}, n_epoch=2,
validation_set=({'input': testX}, {'target': testY}),
snapshot_step=100, show_metric=True, run_id='convnet_mnist')
model.save('tflearn_model')
network = regression(end_network, optimizer='RMSprop', learning_rate=0.1,
loss='categorical_crossentropy', name='target')
model = tflearn.DNN(network, tensorboard_verbose=0)
model.load('tflearn_model')
model.fit({'input': X1}, {'target': Y1}, n_epoch=2,
validation_set=({'input': testX}, {'target': testY}),
snapshot_step=100, show_metric=True, run_id='convnet_mnist')
model.save('tflearn_model')
Related
I am running a VAE in Keras. the model compiles, and its summary is :
however, when I try to train the model I get the following error:
ValueError: Dimensions must be equal, but are 32 and 16 for '{{node vae_mlp/tf_op_layer_AddV2_14/AddV2_14}} = AddV2[T=DT_FLOAT, _cloned=true](vae_mlp/tf_op_layer_Mul_10/Mul_10, vae_mlp/tf_op_layer_Mul_11/Mul_11)' with input shapes: [16,32,32], [16].
The 16 is the batch size. I know because if I change to any number greater than 1, I get the same error that mentions the batch size (and it works for a batch size of 1). I suspect that the problem is that stimuli have 3 channels and that for some reason, it treats it as if it is greyscaled. But I am not sure.
I am attaching the full code as well:
"""### VAE Cifar 10"""
from keras import layers
from keras.layers import Conv2D, MaxPool2D, Flatten, Dense
from keras.layers import Dropout
from keras import regularizers
from keras.datasets import cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
x_train = x_train.astype('float32') / 255
x_test = x_test.astype('float32') / 255
input_shape=(x_train.shape[1], x_train.shape[2], x_train.shape[3])
original_dim=x_train.shape[1]*x_train.shape[2]
latent_dim = 12
import keras
#encoder architecture
encoder_input = keras.Input(shape=input_shape)
cx=layers.Conv2D(filters=64,
kernel_size=(3, 3),
activation='relu',
padding='same')(encoder_input)
cx=layers.Conv2D(filters=64,
kernel_size=(3, 3),
activation='relu',
input_shape=(32, 32, 3),padding='same')(cx)
cx=layers.MaxPool2D(2,2)(cx)
cx=layers.Dropout(0.2)(cx)
cx=layers.Conv2D(filters=64,
kernel_size=(3, 3),
activation='relu',padding='same')(cx)
cx=layers.Conv2D(filters=64,
kernel_size=(3, 3),
activation='relu',padding='same')(cx)
cx=layers.MaxPool2D(2,2)(cx)
cx=layers.Dropout(0.2)(cx)
cx=layers.Conv2D(filters=128,
kernel_size=(3, 3),
activation='relu',padding='same')(cx)
cx=layers.Conv2D(filters=128,
kernel_size=(3, 3),
activation='relu',padding='same')(cx)
cx=layers.MaxPool2D(2,2)(cx)
cx=layers.Dropout(0.2)(cx)
x=layers.Flatten()(cx)
z_mean=layers.Dense(latent_dim, activation='relu', name = 'z_mean')(x) #I removed the softmax layer
z_log_sigma=layers.Dense(latent_dim, activation='relu',name = 'z_sd' )(x)
from keras import backend as K #what is that...
def sampling(args):
z_mean, z_log_sigma = args
epsilon = K.random_normal(shape=(K.shape(z_mean)[0], latent_dim),
mean=0., stddev=0.1)
return z_mean + K.exp(z_log_sigma) * epsilon
z = layers.Lambda(sampling)([z_mean, z_log_sigma])
# Create encoder
encoder = keras.Model(encoder_input, [z_mean, z_log_sigma, z], name='encoder')
encoder.summary()
# Get Conv2D shape for Conv2DTranspose operation in decoder
conv_shape = K.int_shape(cx)
# Create decoder
#look at : https://www.machinecurve.com/index.php/2019/12/30/how-to-create-a-variational-autoencoder-with-keras/
from keras.layers import Conv2DTranspose, Reshape
latent_inputs = keras.Input(shape=(latent_dim, ), name='z_sampling') #shape=(latent_dim,) or shape=late_dim?
d0 = layers.Dense(conv_shape[1] * conv_shape[2] * conv_shape[3], activation='relu')(latent_inputs)
d05 = Reshape((conv_shape[1], conv_shape[2], conv_shape[3]))(d0)
d1=layers.Conv2DTranspose(filters=128,
kernel_size=(3, 3),
strides=2,
activation='relu',padding='same')(d05)#(latent_inputs)
d2=layers.Conv2DTranspose(filters=128,
kernel_size=(3, 3),
strides=2,
activation='relu',padding='same')(d1)
d3=layers.Conv2DTranspose(filters=64,
kernel_size=(3, 3),
strides=2,
activation='relu',padding='same')(d2)
d4=layers.Conv2DTranspose(filters=64,
kernel_size=(3, 3),
activation='relu',padding='same')(d3)
d5=layers.Conv2DTranspose(filters=64,
kernel_size=(3, 3),
activation='relu',
padding='same')(d4)
d6=layers.Conv2DTranspose(filters=64,
kernel_size=(3, 3),
activation='relu',
input_shape=input_shape,padding='same')(d5)
outputs = layers.Conv2D(filters=3, kernel_size=3, activation='sigmoid', padding='same', name='decoder_output')(d6) #Dense(128, activation='relu')
from keras import Model
decoder = Model(latent_inputs, outputs, name='decoder')
decoder.summary()
# instantiate VAE model
outputs = decoder(encoder(encoder_input)[2])
vae = keras.Model(encoder_input, outputs, name='vae_mlp')
vae.summary()
#loss
reconstruction_loss = keras.losses.binary_crossentropy(encoder_input, outputs)
reconstruction_loss *= original_dim
kl_loss = 1 + z_log_sigma - K.square(z_mean) - K.exp(z_log_sigma)
kl_loss = K.sum(kl_loss, axis=-1)
kl_loss *= -0.5
vae_loss = K.mean(reconstruction_loss + kl_loss)
vae.add_loss(vae_loss)
vae.compile(optimizer='adam')
#batch size = 1 doens't break after one epoch
print('you use x_train_t')
vae.fit(x_train, x_train,
epochs=20,
batch_size=16,
validation_data=(x_test, x_test))
There are two things that required to solve the issue:
First, the way to attach the loss function to the model should be by:
vae.compile(optimizer='adam', loss=val_loss_func)
Second, before training one should run:
import tensorflow as tf
tf.config.run_functions_eagerly(True)
I am not sure what this does..
I am getting this error when I try to run my code:
File "C:\Users\olaku\anaconda3\lib\site-packages\keras\legacy\interfaces.py", line 91, in wrapper
return func(*args, **kwargs)
TypeError: __init__() missing 1 required positional argument: 'units'".
My code:
# Importing the relevant libraries.
import numpy as np
import pandas as pd
#importing the dataset
dataset = pd.read_csv ('Churn_Modelling.csv')
X = dataset.iloc[:, 3:13].values
y = dataset.iloc[:, 13].values
# Encoding categorical data
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
labelencoder_X_1 = LabelEncoder()
X[:, 1] = labelencoder_X_1.fit_transform(X[:, 1])
labelencoder_X_2 = LabelEncoder()
X[:, 2] = labelencoder_X_2.fit_transform(X[:, 2])
onehotencoder = OneHotEncoder(categories='auto', drop=None, sparse=True)
X = onehotencoder.fit_transform(X).toarray()
X = X[:, 1:]
# Splitting the dataset into training and testing set
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 123)
#Feature Scalling
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
# Part 2: Make the Artifical Neural Network (ANN)
#Import the Keras library and packages
import keras
from keras.models import Sequential
from keras.layers import Dense
#Initialising the ANN
classifier = Sequential ()
classifier.add(Dense(units = 6, kernel_initializer = 'uniform', activation = 'relu', input_dim = 11))
#Adding the second hidden layer
classifier.add(Dense(units = 6, kernel_initializer = 'uniform', activation = 'relu'))
#Adding the output layer
classifier.add(Dense(output = 1, kernel_initializer = 'uniform', activation = 'sigmoid'))
try this changes:
classifier.add(Dense(6, kernel_initializer = 'uniform', activation = 'relu', input_dim = 11))
#Adding the second hidden layer
classifier.add(Dense(6, kernel_initializer = 'uniform', activation = 'relu'))
#Adding the output layer
classifier.add(Dense(1, kernel_initializer = 'uniform', activation = 'sigmoid'))
let me know!
I want to predict the kind of 2 diseases but I get results as binary (like 1.0 and 0.0). How can I get accuracy of these (like 0.7213)?
Training code:
from keras.models import Sequential
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dense
# Intialising the CNN
classifier = Sequential()
# Step 1 - Convolution
classifier.add(Conv2D(32, (3, 3), input_shape = (64, 64, 3), activation = 'relu'))
# Step 2 - Pooling
classifier.add(MaxPooling2D(pool_size = (2, 2)))
# Adding a second convolutional layer
classifier.add(Conv2D(32, (3, 3), activation = 'relu'))
classifier.add(MaxPooling2D(pool_size = (2, 2)))
# Step 3 - Flattening
classifier.add(Flatten())
# Step 4 - Full connection
classifier.add(Dense(units = 128, activation = 'relu'))
classifier.add(Dense(units = 1, activation = 'sigmoid'))
# Compiling the CNN
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
# Part 2 - Fitting the CNN to the images
import h5py
from keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(rescale = 1./255,
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip = True)
test_datagen = ImageDataGenerator(rescale = 1./255)
training_set = train_datagen.flow_from_directory('training_set',
target_size = (64, 64),
batch_size = 32,
class_mode = 'binary')
test_set = test_datagen.flow_from_directory('test_set',
target_size = (64, 64),
batch_size = 32,
class_mode = 'binary')
classifier.fit_generator(training_set,
steps_per_epoch = 100,
epochs = 1,
validation_data = test_set,
validation_steps = 100)
Single prediction code:
import numpy as np
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img,image
test_image = image.load_img('path_to_image', target_size = (64, 64))
test_image = image.img_to_array(test_image)
test_image = np.expand_dims(test_image, axis = 0)
result = classifier.predict(test_image)
print(result[0][0]) # Prints 1.0 or 0.0
# I want accuracy rate for this prediction like 0.7213
The file structures is like:
test_set
benigne
benigne_images
melignant
melignant_images
training set
Training set structure is also the same as test set.
Update: As you clarified in the comments, you are looking for the probabilities of each class given one single test sample. Therefore you can use predict method. However, note that you must first preprocess the image the same way you have done in the training phase:
test_image /= 255.0
result = classifier.predict(test_image)
The result would be the probability of the given image belonging to class one (i.e. positive class).
If you have a generator for test data, then you can use evaluate_generator() to get the loss as well as the accuracy (or any other metric you have set) of the model on the test data.
For example, right after fitting the model, i.e. using fit_generator, you can use evaluate_generator on your test data generator, i.e. test_set:
loss, acc = evaluate_generator(test_set)
I am currently creating a CNN model that classifies whether the font is Arial, Verdana, Times New Roman and Georgia. All in all there are 16 classes since I considered also detecting whether the font is regular, bold, italics or bold italics. So 4 fonts * 4 styles = 16 classes.
The data that I have used in my training are the following:
Training data set : 800 image patches of 256 * 256 dimension (50 for each class)
Validation data set : 320 image patches of 256 * 256 dimension (20 for each class)
Testing data set : 160 image patches of 256 * 256 dimension (10 for each class)
Below is the sample screenshot of my data:
Below is my initial code:
import numpy as np
import keras
from keras import backend as K
from keras.models import Sequential
from keras.layers import Activation
from keras.layers.core import Dense, Flatten
from keras.optimizers import Adam
from keras.metrics import categorical_crossentropy
from keras.preprocessing.image import ImageDataGenerator
from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import *
from matplotlib import pyplot as plt
import itertools
import matplotlib.pyplot as plt
import pickle
image_width = 256
image_height = 256
train_path = 'font_model_data/train'
valid_path = 'font_model_data/valid'
test_path = 'font_model_data/test'
train_batches = ImageDataGenerator().flow_from_directory(train_path, target_size=(image_width, image_height), classes=['1','2','3','4', '5', '6', '7', '8', '9', '10', '11', '12','13', '14', '15', '16'], batch_size = 16)
valid_batches = ImageDataGenerator().flow_from_directory(valid_path, target_size=(image_width, image_height), classes=['1','2','3','4', '5', '6', '7', '8', '9', '10', '11', '12','13', '14', '15', '16'], batch_size = 16)
test_batches = ImageDataGenerator().flow_from_directory(test_path, target_size=(image_width, image_height), classes=['1','2','3','4', '5', '6', '7', '8', '9', '10', '11', '12','13', '14', '15', '16'], batch_size = 160)
imgs, labels = next(train_batches)
#CNN model
model = Sequential([
Conv2D(32, (3,3), activation='relu', input_shape=(image_width, image_height, 3)),
Flatten(),
Dense(16, activation='softmax'),
])
print(model.summary())
model.compile(Adam(lr=.0001),loss='categorical_crossentropy', metrics=['accuracy'])
model.fit_generator(train_batches, steps_per_epoch = 50, validation_data= valid_batches, validation_steps = 20, epochs = 1, verbose = 2)
model_pickle = open('cnn_font_model.pickle', 'wb')
pickle.dump(model, model_pickle)
model_pickle.close()
print('Training Done.')
test_imgs, test_labels = next(test_batches)
predictions = model.predict_generator(test_batches, steps = 160, verbose = 2)
print(predictions)
Can anyone suggest how will I know the right network architecture and parameters to get the optimal accuracy? How should I start tweaking my network?
Before going to choose Network you need to segmentize the image tile into subtitles with characters and feed to the following architecture...
# Initialising the CNN
classifier = Sequential()
# Step 1 - Convolution
classifier.add(Conv2D(32, (3, 3), input_shape = (64, 64, 3), activation = 'relu'))
# Step 2 - Pooling
classifier.add(MaxPooling2D(pool_size = (2, 2)))
# Adding a second convolutional layer
classifier.add(Conv2D(32, (3, 3), activation = 'relu'))
classifier.add(MaxPooling2D(pool_size = (2, 2)))
# Step 3 - Flattening
classifier.add(Flatten())
# Step 4 - Full connection
classifier.add(Dense(units = 128, activation = 'relu'))
classifier.add(Dense(units = 1, activation = 'sigmoid'))
# Compiling the CNN
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
classifier.fit_generator(training_set,
steps_per_epoch = XXX,
epochs = XX,
validation_data = test_set,
validation_steps = XXX)
from keras.models import load_model
classifier.save('your_classifier.h5')
I am beginner in machine learning. I am making a CNN model using keras to detect pest from leaf image. During training the data, memory exceed and I was unable to train. I have used kaggle/Google Collab but in both I have memory probelm.
I was suggested to use Data Generator, but while trying to do, I was unable to do. Is there any other way to efficiently train or any example whether data generator is used(Have seen many examples but have problem while adding.
import numpy as np
import pickle
import cv2
from os import listdir
from sklearn.preprocessing import LabelBinarizer
from keras.models import Sequential
from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.core import Activation, Flatten, Dropout, Dense
from keras import backend as K
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import Adam
from keras.preprocessing import image
from keras.preprocessing.image import img_to_array
from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
EPOCHS = 25
INIT_LR = 1e-3
BS = 32
default_image_size = tuple((256, 256))
image_size = 0
directory_root = 'PlantVillage/'
width=256
height=256
depth=3
#Function to convert images to array
def convert_image_to_array(image_dir):
try:
image = cv2.imread(image_dir)
if image is not None:
image = cv2.resize(image,default_image_size)
return img_to_array(image)
else:
return np.array([])
except Exception as e:
print(f"Error : {e}")
return None
image_list, label_list = [], []
try:
print("[INFO] Loading images ...")
root_dir = listdir(directory_root)
#Looping inside root_directory
for directory in root_dir :
# remove .DS_Store from list
if directory == ".DS_Store" :
root_dir.remove(directory)
for plant_folder in root_dir :
plant_disease_folder_list = listdir(f"{directory_root}/{plant_folder}")
print(f"[INFO] Processing {plant_folder} ...")
#looping in images
for disease_folder in plant_disease_folder_list :
# remove .DS_Store from list
if disease_folder == ".DS_Store" :
plant_disease_folder_list.remove(plant_folder)
#If all data taken not able to train
for images in plant_disease_folder_list:
image_directory = f"{directory_root}/{plant_folder}/{images}"
if image_directory.endswith(".jpg") == True or image_directory.endswith(".JPG") == True:
image_list.append(convert_image_to_array(image_directory))
label_list.append(plant_folder)
print("[INFO] Image loading completed")
except Exception as e:
print(f"Error : {e}")
#Get Size of Processed Image
image_size = len(image_list)
#Converting multi-class labels to binary labels(belong or doesnot belong in the class)
label_binarizer = LabelBinarizer()
image_labels = label_binarizer.fit_transform(label_list)
#Saving label binarizer instance using pickle
pickle.dump(label_binarizer,open('label_transform.pkl','wb'))
n_classes = len(label_binarizer.classes_)
print(label_binarizer.classes_)
#Normalizing image from [0,255] to [0,1]
np_image_list = np.array(image_list, dtype = np.float)/255.0
#Splitting data into training and test set 80:20
print('Splitting data to train,test')
x_train, x_test, y_train, y_test = train_test_split(np_image_list, image_labels, test_size=0.2, random_state = 42)
#Creating image generator object which performs random rotations, shifs,flips,crops,sheers
aug = ImageDataGenerator(
rotation_range = 25, width_shift_range=0.1,
height_shift_range=0.1, shear_range=0.2,
zoom_range=0.2, horizontal_flip = True,
fill_mode="nearest")
model = Sequential()
inputShape = (height, width, depth)
chanDim = -1
if K.image_data_format() == "channels_first":
inputShape = (depth, height, width)
chanDim = 1
model.add(Conv2D(32, (3, 3), padding="same",input_shape=inputShape))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(3, 3)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(64, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(128, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(128, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(32))
model.add(Activation("relu"))
model.add(BatchNormalization())
model.add(Dropout(0.5))
model.add(Dense(n_classes))
model.add(Activation("softmax"))
#model.summary()
#Compiling the CNN
opt = Adam(lr= INIT_LR, decay= INIT_LR/EPOCHS)
#distribution
model.compile(loss="binary_crossentropy", optimizer = opt, metrics=["accuracy"])
#training the Model
print("Training Model.....")
history = model.fit_generator(
aug.flow(x_train, y_train, batch_size= BS),
validation_data = (x_test, y_test),
steps_per_epoch = len(x_train) // BS,
epochs = EPOCHS, verbose = 1
)
You find code in this link too.
The problem here is that you have loaded the complete data in the workspace, which fills lots of memory and create lots of extra load on the processes.
One thing you can used is data-generator with flow_from_directory, which allows you to define the augmentation and pre-processing pipeline along with data on the fly. The advantage here is that workspace doesn't have extra load of data. You can find an example here.
Feel free to ask question.
You can convert images into binary format which is understandable by tensorflow called "tfrecord" format.
Please refer to the below links
https://www.tensorflow.org/guide/datasets http://www.machinelearninguru.com/deep_learning/tensorflow/basics/tfrecord/tfrecord.html