├── README.md ├── stats.py ├── test.py ├── get_features.py ├── mnist_digit.py ├── mnist_fashion.py ├── mnist_digit_fc.py ├── cifar10.py ├── daily_usage.py ├── nnmodels.py └── functions.py /README.md: -------------------------------------------------------------------------------- 1 | # commodity_image_classificiation 2 | 基于深度学习的日用品图像分类与识别的研究与应用_本科论文代码 3 | -------------------------------------------------------------------------------- /stats.py: -------------------------------------------------------------------------------- 1 | from functions import Functions 2 | import pandas as pd 3 | import matplotlib.pyplot as plt 4 | fct = Functions() 5 | 6 | dirs = '../data/daily-usage' 7 | x, y, n, y_dict = fct.read_images(dirs, target_size=(64,64)) 8 | # m = [(y_dict[i], val) for i, val in n.items()] 9 | # pd = pd.DataFrame(m) 10 | # pd.to_excel('stats.xlsx') 11 | 12 | row, col = 8, 10 13 | per = 2 14 | cnt = {} 15 | now = 1 16 | plt.figure() 17 | for i, image in enumerate(x): 18 | if y[i] not in cnt: 19 | cnt[y[i]] = 0 20 | cnt[y[i]] += 1 21 | if cnt[y[i]] <= per: 22 | plt.subplot(row, col, now) 23 | plt.imshow(image) 24 | plt.axis('off') 25 | now = now + 1 26 | else: 27 | continue 28 | 29 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | from functions import Functions as Funcs 2 | from keras.models import load_model 3 | import warnings 4 | 5 | warnings.filterwarnings('ignore') 6 | # read images and preprocess 7 | test_path = '../test_pictures' 8 | model_path = '../models/daily_50_9337.h5' 9 | json_path = '../data/daily/index.json' 10 | plot_path = '../prediction.jpg' 11 | target_size = (224, 224) 12 | limits = 42 13 | x = Funcs.read_images_from_directory(test_path, target_size=target_size, limits=limits, shuffle=True) 14 | x = Funcs.preprocess_input(x) 15 | 16 | # load model 17 | model = load_model(model_path) 18 | pred = model.predict(x) 19 | pred = Funcs.decode_prediction(pred, json_path) 20 | x = Funcs.undo_input(x) 21 | Funcs.plot_prediction(x, pred, fname=plot_path) 22 | -------------------------------------------------------------------------------- /get_features.py: -------------------------------------------------------------------------------- 1 | from functions import Functions as Funcs 2 | from src.nnmodels import Models 3 | from keras.models import load_model 4 | import matplotlib.pyplot as plt 5 | 6 | 7 | # read images and preprocess 8 | test_path = '../test_pictures' 9 | model_path = '../models/daily_50_9337.h5' 10 | json_path = '../data/daily/index.json' 11 | plot_path = '../prediction.jpg' 12 | target_size = (224, 224) 13 | limits = 42 14 | cap_i = 0 15 | x = Funcs.read_images_from_directory(test_path, target_size=target_size, limits=limits, shuffle=False) 16 | x = Funcs.preprocess_input(x) 17 | plt.figure() 18 | plt.imshow(x[cap_i]) 19 | plt.axis('off') 20 | x0 = x[cap_i].reshape((1,)+x[cap_i].shape) 21 | 22 | model = Models.conv_vgg16() 23 | y0 = model.predict(x0) 24 | rows, cols = 20, 25 25 | plt.figure(figsize=(cols, rows)) 26 | for i in range(rows*cols): 27 | plt.subplot(rows, cols, i+1) 28 | plt.imshow(y0[0, :, :, i], cmap=plt.cm.gray_r) 29 | # plt.title(str(i+1)) 30 | plt.axis('off') -------------------------------------------------------------------------------- /mnist_digit.py: -------------------------------------------------------------------------------- 1 | from src.nnmodels import Models 2 | from src.functions import Functions as Funcs 3 | from keras.callbacks import ModelCheckpoint, LearningRateScheduler 4 | from keras.models import load_model 5 | import os 6 | import datetime 7 | 8 | 9 | # initialize base variable 10 | epochs = 120 11 | model_design = Models.mnist_digit 12 | data_name = 'mnist_digit' 13 | dirs = '../data/{}'.format(data_name) 14 | json_path = '{}/train/index.json'.format(dirs) 15 | model_save_path = '../models/{}_{}.h5'.format(data_name, epochs) 16 | model_load_path = '../models/{}_{}_{}.h5'.format(data_name, epochs, 9947) 17 | model_history_path = '../train_info/{}_{}_modelHis.dat'.format(data_name, epochs) 18 | history_path = '../train_info/{}_{}_his.jpg'.format(data_name, epochs) 19 | pred_path = '../train_info/{}_{}_pred.jpg'.format(data_name, epochs) 20 | target_size = (28, 28) 21 | classes = 10 22 | num_pred = 30 23 | batch_size = 32 24 | gray = True 25 | load_existent_model = False 26 | 27 | # load train and test data 28 | print('loading data ...') 29 | (x_train, y_train), (x_test, y_test) = Funcs.load_data(dirs, target_size, gray=gray, classes=classes) 30 | print('loading data done') 31 | 32 | # define callbacks for models to render model performance better 33 | checkpoint = ModelCheckpoint(model_save_path, monitor='val_acc', save_best_only=True, verbose=1) 34 | lrschedual = LearningRateScheduler(lambda epoch: Funcs.lr_schedual(epoch, epochs=epochs), verbose=0) 35 | 36 | # whether load existent model 37 | if load_existent_model and os.path.exists(model_load_path): 38 | model = load_model(model_load_path) 39 | else: 40 | model = model_design(x_train.shape[1:], classes) 41 | 42 | # train the model 43 | start_time = datetime.datetime.now() 44 | model.fit(x_train, y_train, epochs=epochs, batch_size=batch_size, 45 | validation_data=(x_test, y_test), callbacks=[checkpoint, lrschedual], verbose=2) 46 | end_time = datetime.datetime.now() 47 | best_model = load_model(model_save_path) 48 | loss_acc = best_model.evaluate(x_test, y_test) 49 | print('loss: {:.3f}, acc: {:.3f}'.format(loss_acc[0], loss_acc[1])) 50 | print('training time: {}s'.format((end_time-start_time).seconds)) 51 | 52 | # plot the history of training 53 | Funcs.save_history(model.history, model_history_path) 54 | Funcs.plot_history(model.history, history_path, num_xticks=6) 55 | 56 | # use highest accuracy model for prediction 57 | pred = best_model.predict(x_test) 58 | pred_idx = Funcs.get_pred_index(pred, num_pred=num_pred, y=y_test) 59 | x = Funcs.undo_input(x_test[pred_idx]) 60 | pred = Funcs.decode_prediction(pred[pred_idx], json_path) 61 | y = Funcs.decode_prediction(y_test[pred_idx], json_path) 62 | Funcs.plot_prediction(x, pred, fname=pred_path, y=y) 63 | 64 | # amend model filename to easily recognize 65 | new_model_save_path = model_save_path[:-3] + '_' + str(int(loss_acc[1]*10000)) + model_save_path[-3:] 66 | os.rename(model_save_path, new_model_save_path) 67 | print('saved model to {}'.format(new_model_save_path)) 68 | -------------------------------------------------------------------------------- /mnist_fashion.py: -------------------------------------------------------------------------------- 1 | from src.nnmodels import Models 2 | from src.functions import Functions as Funcs 3 | from keras.callbacks import ModelCheckpoint, LearningRateScheduler 4 | from keras.models import load_model 5 | import os 6 | import datetime 7 | 8 | 9 | # initialize base variable 10 | epochs = 120 11 | model_design = Models.mnist_fashion 12 | data_name = 'mnist_fashion' 13 | dirs = '../data/{}'.format(data_name) 14 | json_path = '{}/train/index.json'.format(dirs) 15 | model_save_path = '../models/{}_{}.h5'.format(data_name, epochs) 16 | model_load_path = '../models/{}_{}_{}.h5'.format(data_name, epochs, 10) 17 | model_history_path = '../train_info/{}_{}_modelHis.dat'.format(data_name, epochs) 18 | history_path = '../train_info/{}_{}_his.jpg'.format(data_name, epochs) 19 | pred_path = '../train_info/{}_{}_pred.jpg'.format(data_name, epochs) 20 | target_size = (28, 28) 21 | classes = 10 22 | num_pred = 30 23 | batch_size = 32 24 | gray = True 25 | load_existent_model = False 26 | 27 | # load train and test data 28 | print('loading data ...') 29 | (x_train, y_train), (x_test, y_test) = Funcs.load_data(dirs, target_size, gray=gray, classes=classes) 30 | print('loading data done') 31 | 32 | # define callbacks for models to render model performance better 33 | checkpoint = ModelCheckpoint(model_save_path, monitor='val_acc', save_best_only=True, verbose=0) 34 | lrschedual = LearningRateScheduler(lambda epoch: Funcs.lr_schedual(epoch, epochs=epochs), verbose=0) 35 | 36 | # whether load existent model 37 | if load_existent_model and os.path.exists(model_load_path): 38 | model = load_model(model_load_path) 39 | else: 40 | model = model_design(x_train.shape[1:], classes) 41 | 42 | # train the model 43 | start_time = datetime.datetime.now() 44 | model.fit(x_train, y_train, epochs=epochs, batch_size=batch_size, 45 | validation_data=(x_test, y_test), callbacks=[checkpoint, lrschedual], verbose=1) 46 | end_time = datetime.datetime.now() 47 | best_model = load_model(model_save_path) 48 | loss_acc = best_model.evaluate(x_test, y_test) 49 | print('loss: {:.3f}, acc: {:.3f}'.format(loss_acc[0], loss_acc[1])) 50 | print('training time: {}s'.format((end_time-start_time).seconds)) 51 | 52 | # plot the history of training 53 | Funcs.save_history(model.history, model_history_path) 54 | Funcs.plot_history(model.history, history_path, num_xticks=6) 55 | 56 | # use highest accuracy model for prediction 57 | pred = best_model.predict(x_test) 58 | pred_idx = Funcs.get_pred_index(pred, num_pred=num_pred, y=y_test) 59 | x = Funcs.undo_input(x_test[pred_idx]) 60 | pred = Funcs.decode_prediction(pred[pred_idx], json_path) 61 | y = Funcs.decode_prediction(y_test[pred_idx], json_path) 62 | Funcs.plot_prediction(x, pred, fname=pred_path, y=y) 63 | 64 | # amend model filename to easily recognize 65 | new_model_save_path = model_save_path[:-3] + '_' + str(int(loss_acc[1]*10000)) + model_save_path[-3:] 66 | os.rename(model_save_path, new_model_save_path) 67 | print('saved model to {}'.format(new_model_save_path)) 68 | -------------------------------------------------------------------------------- /mnist_digit_fc.py: -------------------------------------------------------------------------------- 1 | from src.nnmodels import Models 2 | from src.functions import Functions as Funcs 3 | from keras.callbacks import ModelCheckpoint, LearningRateScheduler 4 | from keras.models import load_model 5 | import os 6 | import datetime 7 | 8 | 9 | # initialize base variable 10 | epochs = 120 11 | model_design = Models.mnist_digit_fc 12 | data_name = 'mnist_digit_fc' 13 | dirs = '../data/{}'.format('mnist_digit') 14 | json_path = '{}/train/index.json'.format(dirs) 15 | model_save_path = '../models/{}_{}.h5'.format(data_name, epochs) 16 | model_load_path = '../models/{}_{}_{}.h5'.format(data_name, epochs, 9947) 17 | model_history_path = '../train_info/{}_{}_modelHis.dat'.format(data_name, epochs) 18 | history_path = '../train_info/{}_{}_his.jpg'.format(data_name, epochs) 19 | pred_path = '../train_info/{}_{}_pred.jpg'.format(data_name, epochs) 20 | target_size = (28, 28) 21 | classes = 10 22 | num_pred = 30 23 | batch_size = 32 24 | gray = True 25 | load_existent_model = False 26 | 27 | # load train and test data 28 | print('loading data ...') 29 | (x_train, y_train), (x_test, y_test) = Funcs.load_data(dirs, target_size, gray=gray, classes=classes) 30 | print('loading data done') 31 | 32 | # define callbacks for models to render model performance better 33 | checkpoint = ModelCheckpoint(model_save_path, monitor='val_acc', save_best_only=True, verbose=1) 34 | lrschedual = LearningRateScheduler(lambda epoch: Funcs.lr_schedual(epoch, epochs=epochs), verbose=0) 35 | 36 | # whether load existent model 37 | if load_existent_model and os.path.exists(model_load_path): 38 | model = load_model(model_load_path) 39 | else: 40 | model = model_design(x_train.shape[1:], classes) 41 | 42 | # train the model 43 | start_time = datetime.datetime.now() 44 | model.fit(x_train, y_train, epochs=epochs, batch_size=batch_size, 45 | validation_data=(x_test, y_test), callbacks=[checkpoint, lrschedual], verbose=2) 46 | end_time = datetime.datetime.now() 47 | best_model = load_model(model_save_path) 48 | loss_acc = best_model.evaluate(x_test, y_test) 49 | print('loss: {:.3f}, acc: {:.3f}'.format(loss_acc[0], loss_acc[1])) 50 | print('training time: {}s'.format((end_time-start_time).seconds)) 51 | 52 | # plot the history of training 53 | Funcs.save_history(model.history, model_history_path) 54 | Funcs.plot_history(model.history, history_path, num_xticks=6) 55 | 56 | # use highest accuracy model for prediction 57 | pred = best_model.predict(x_test) 58 | pred_idx = Funcs.get_pred_index(pred, num_pred=num_pred, y=y_test) 59 | x = Funcs.undo_input(x_test[pred_idx]) 60 | pred = Funcs.decode_prediction(pred[pred_idx], json_path) 61 | y = Funcs.decode_prediction(y_test[pred_idx], json_path) 62 | Funcs.plot_prediction(x, pred, fname=pred_path, y=y) 63 | 64 | # amend model filename to easily recognize 65 | new_model_save_path = model_save_path[:-3] + '_' + str(int(loss_acc[1]*10000)) + model_save_path[-3:] 66 | os.rename(model_save_path, new_model_save_path) 67 | print('saved model to {}'.format(new_model_save_path)) 68 | -------------------------------------------------------------------------------- /cifar10.py: -------------------------------------------------------------------------------- 1 | from src.nnmodels import Models 2 | from src.functions import Functions as Funcs 3 | from keras.callbacks import ModelCheckpoint, LearningRateScheduler 4 | from keras.models import load_model 5 | import os 6 | import datetime 7 | from keras.datasets.cifar10 import load_data 8 | 9 | # initialize base variable 10 | epochs = 300 11 | model_design = Models.cifar10 12 | data_name = 'cifar10' 13 | dirs = '../data/{}'.format(data_name) 14 | json_path = '{}/train/index.json'.format(dirs) 15 | model_save_path = '../models/{}_{}.h5'.format(data_name, epochs) 16 | model_load_path = '../models/{}_{}_{}.h5'.format(data_name, epochs, 10) 17 | model_history_path = '../train_info/{}_{}_modelHis.dat'.format(data_name, epochs) 18 | history_path = '../train_info/{}_{}_his.jpg'.format(data_name, epochs) 19 | pred_path = '../train_info/{}_{}_pred.jpg'.format(data_name, epochs) 20 | target_size = (32, 32) 21 | classes = 10 22 | num_pred = 30 23 | batch_size = 32 24 | gray = False 25 | load_existent_model = False 26 | 27 | # load train and test data 28 | print('loading data ...') 29 | # (x_train, y_train), (x_test, y_test) = Funcs.load_data(dirs, target_size, gray=gray, classes=classes) 30 | (x_train, y_train), (x_test, y_test) = load_data() 31 | (x_train, y_train) = Funcs.trans_data(x_train, y_train, classes) 32 | (x_test, y_test) = Funcs.trans_data(x_test, y_test, classes) 33 | print('loading data done') 34 | 35 | # define callbacks for models to render model performance better 36 | checkpoint = ModelCheckpoint(model_save_path, monitor='val_acc', save_best_only=True, verbose=0) 37 | lrschedual = LearningRateScheduler(lambda epoch: Funcs.lr_schedual(epoch, epochs=epochs), verbose=0) 38 | 39 | # whether load existent model 40 | if load_existent_model and os.path.exists(model_load_path): 41 | model = load_model(model_load_path) 42 | else: 43 | model = model_design(x_train.shape[1:], classes) 44 | 45 | # train the model 46 | start_time = datetime.datetime.now() 47 | model.fit(x_train, y_train, epochs=epochs, batch_size=batch_size, 48 | validation_data=(x_test, y_test), callbacks=[checkpoint, lrschedual], verbose=1) 49 | end_time = datetime.datetime.now() 50 | best_model = load_model(model_save_path) 51 | loss_acc = best_model.evaluate(x_test, y_test) 52 | print('loss: {:.3f}, acc: {:.3f}'.format(loss_acc[0], loss_acc[1])) 53 | print('training time: {}s'.format((end_time-start_time).seconds)) 54 | 55 | # plot the history of training 56 | Funcs.save_history(model.history, model_history_path) 57 | Funcs.plot_history(model.history, history_path) 58 | 59 | # use highest accuracy model for prediction 60 | pred = best_model.predict(x_test) 61 | pred_idx = Funcs.get_pred_index(pred, num_pred=num_pred, y=y_test) 62 | x = Funcs.undo_input(x_test[pred_idx]) 63 | pred = Funcs.decode_prediction(pred[pred_idx], json_path) 64 | y = Funcs.decode_prediction(y_test[pred_idx], json_path) 65 | Funcs.plot_prediction(x, pred, fname=pred_path, y=y) 66 | 67 | # amend model filename to easily recognize 68 | new_model_save_path = model_save_path[:-3] + '_' + str(int(loss_acc[1]*10000)) + model_save_path[-3:] 69 | os.rename(model_save_path, new_model_save_path) 70 | print('saved model to {}'.format(new_model_save_path)) 71 | -------------------------------------------------------------------------------- /daily_usage.py: -------------------------------------------------------------------------------- 1 | from src.nnmodels import Models 2 | from src.functions import Functions as Funcs 3 | from keras.callbacks import ModelCheckpoint, LearningRateScheduler 4 | from keras.models import load_model 5 | # from keras.optimizers import SGD 6 | import os 7 | import datetime 8 | 9 | 10 | epochs = 50 11 | epochs2 = 50 12 | model_design = Models.daily 13 | data_name = 'daily' 14 | dirs = '../data/{}'.format(data_name) 15 | json_path = '{}/index.json'.format(dirs) 16 | model_save_path = '../models/{}_{}.h5'.format(data_name, epochs) 17 | model_load_path = '../models/{}_{}_{}.h5'.format(data_name, epochs, 10) 18 | model_history_path = '../train_info/{}_{}_modelHis.dat'.format(data_name, epochs) 19 | history_path = '../train_info/{}_{}_his.jpg'.format(data_name, epochs) 20 | pred_path = '../train_info/{}_{}_pred.jpg'.format(data_name, epochs) 21 | target_size = (224, 224) 22 | num_pred = 30 23 | batch_size = 32 24 | gray = False 25 | load_existent_model = False 26 | 27 | # load train and test data 28 | print('loading data ...') 29 | (images, labels, counts) = Funcs.read_images_from_directories(dirs, target_size, get_counts=True, init_json=True, 30 | shuffle=True) 31 | classes = len(counts) 32 | (x_train, y_train), (x_test, y_test) = Funcs.split_train_test(images, labels, counts) 33 | (x_train, y_train) = Funcs.trans_data(x_train, y_train, classes) 34 | (x_test, y_test) = Funcs.trans_data(x_test, y_test, classes) 35 | print('loading data done') 36 | 37 | # define callbacks for models to render model performance better 38 | checkpoint = ModelCheckpoint(model_save_path, monitor='val_acc', save_best_only=True, verbose=0) 39 | lrschedual = LearningRateScheduler(lambda epoch: Funcs.lr_schedual(epoch, epochs=epochs), verbose=0) 40 | 41 | # whether load existent model 42 | if load_existent_model and os.path.exists(model_load_path): 43 | model = load_model(model_load_path) 44 | else: 45 | model = model_design(x_train.shape[1:], classes) 46 | 47 | # train the model 48 | start_time = datetime.datetime.now() 49 | model.fit(x_train, y_train, epochs=epochs, batch_size=batch_size, 50 | validation_data=(x_test, y_test), callbacks=[checkpoint, lrschedual], verbose=1) 51 | 52 | # fine tune last conv parameters 53 | # for layer in model.layers[:15]: 54 | # layer.trainable = False 55 | # for layer in model.layers[15:]: 56 | # layer.trainable = True 57 | # model.compile(optimizer=SGD(lr=0.0001, momentum=0.9), 58 | # loss='categorical_crossentropy', 59 | # metrics=['accuracy']) 60 | # model.fit(x_train, y_train, epochs=epochs2, batch_size=batch_size, 61 | # validation_data=(x_test, y_test), callbacks=[checkpoint], verbose=1) 62 | 63 | end_time = datetime.datetime.now() 64 | best_model = load_model(model_save_path) 65 | loss_acc = best_model.evaluate(x_test, y_test) 66 | print('loss: {:.3f}, acc: {:.3f}'.format(loss_acc[0], loss_acc[1])) 67 | print('training time: {}s'.format((end_time-start_time).seconds)) 68 | 69 | # plot the history of training 70 | Funcs.save_history(model.history, model_history_path) 71 | Funcs.plot_history(model.history, history_path, num_xticks=5) 72 | 73 | # use highest accuracy model for prediction 74 | pred = best_model.predict(x_test) 75 | pred_idx = Funcs.get_pred_index(pred, num_pred=num_pred, y=y_test) 76 | x = Funcs.undo_input(x_test[pred_idx]) 77 | pred = Funcs.decode_prediction(pred[pred_idx], json_path) 78 | y = Funcs.decode_prediction(y_test[pred_idx], json_path) 79 | Funcs.plot_prediction(x, pred, fname=pred_path, y=y) 80 | 81 | # amend model filename to easily recognize 82 | new_model_save_path = model_save_path[:-3] + '_' + str(int(loss_acc[1]*10000)) + model_save_path[-3:] 83 | os.rename(model_save_path, new_model_save_path) 84 | print('saved model to {}'.format(new_model_save_path)) 85 | -------------------------------------------------------------------------------- /nnmodels.py: -------------------------------------------------------------------------------- 1 | from keras.models import Model 2 | from keras.layers import Input, Flatten, Dropout 3 | from keras.layers import Dense, Conv2D, MaxPooling2D, GlobalAveragePooling2D 4 | from keras.applications.vgg16 import VGG16 5 | 6 | 7 | class Models(object): 8 | def __init__(self): 9 | pass 10 | 11 | @staticmethod 12 | def mnist_digit_fc(input_shape=(28, 28, 1), classes=10): 13 | img_input = Input(input_shape) 14 | 15 | x = Flatten(name='flatten')(img_input) 16 | x = Dense(64, activation='relu', name='dense1')(x) 17 | x = Dense(32, activation='relu', name='dense2')(x) 18 | x = Dense(classes, activation='softmax', name='prediction')(x) 19 | 20 | model = Model(img_input, x, name='mnist_digit_fc') 21 | model.compile(optimizer='adam', 22 | loss='categorical_crossentropy', 23 | metrics=['accuracy']) 24 | return model 25 | 26 | @staticmethod 27 | def mnist_digit(input_shape=(28, 28, 1), classes=10): 28 | img_input = Input(input_shape) 29 | 30 | x = Conv2D(16, (3, 3), activation='relu', padding='same', name='conv1')(img_input) 31 | x = MaxPooling2D((2, 2), name='pool1')(x) 32 | x = Conv2D(32, (3, 3), activation='relu', padding='same', name='conv2')(x) 33 | x = MaxPooling2D((2, 2), name='pool2')(x) 34 | x = Conv2D(64, (3, 3), activation='relu', padding='same', name='conv3')(x) 35 | 36 | x = Flatten()(x) 37 | x = Dense(128, activation='relu', name='fc1')(x) 38 | x = Dropout(0.2, name='drop1')(x) 39 | x = Dense(classes, activation='softmax', name='prediction')(x) 40 | 41 | model = Model(img_input, x, name='mnist_digit') 42 | model.compile(optimizer='adam', 43 | loss='categorical_crossentropy', 44 | metrics=['accuracy']) 45 | return model 46 | 47 | @staticmethod 48 | def mnist_fashion(input_shape=(28, 28, 1), classes=10): 49 | img_input = Input(input_shape) 50 | 51 | x = Conv2D(32, (3, 3), activation='relu', padding='same', name='conv1')(img_input) 52 | x = MaxPooling2D((2, 2), name='pool1')(x) 53 | x = Conv2D(48, (3, 3), activation='relu', padding='same', name='conv2')(x) 54 | x = MaxPooling2D((2, 2), name='pool2')(x) 55 | x = Conv2D(64, (2, 2), activation='relu', padding='same', name='conv3')(x) 56 | 57 | x = Flatten()(x) 58 | x = Dense(128, activation='relu', name='fc1')(x) 59 | x = Dropout(0.2, name='drop1')(x) 60 | x = Dense(classes, activation='softmax', name='prediction')(x) 61 | 62 | model = Model(img_input, x, name='mnist_digit') 63 | model.compile(optimizer='adam', 64 | loss='categorical_crossentropy', 65 | metrics=['accuracy']) 66 | return model 67 | 68 | @staticmethod 69 | def cifar10(input_shape=(32, 32, 3), classes=10): 70 | img_input = Input(input_shape) 71 | 72 | x = Conv2D(32, (3, 3), activation='relu', padding='same', name='conv1')(img_input) 73 | x = Conv2D(32, (3, 3), activation='relu', padding='same', name='conv2')(x) 74 | x = MaxPooling2D((2, 2), name='pool1')(x) 75 | x = Dropout(0.25, name='drop1')(x) 76 | 77 | x = Conv2D(64, (3, 3), activation='relu', padding='same', name='conv3')(x) 78 | x = Conv2D(64, (3, 3), activation='relu', padding='same', name='conv4')(x) 79 | x = MaxPooling2D((2, 2), name='pool2')(x) 80 | x = Dropout(0.25, name='drop2')(x) 81 | 82 | x = Conv2D(128, (3, 3), activation='relu', padding='same', name='conv5')(x) 83 | x = Conv2D(128, (3, 3), activation='relu', padding='same', name='conv6')(x) 84 | x = MaxPooling2D((2, 2), name='pool3')(x) 85 | x = Dropout(0.25, name='drop3')(x) 86 | 87 | x = Flatten()(x) 88 | x = Dense(256, activation='relu', name='fc1')(x) 89 | x = Dropout(0.25, name='drop4')(x) 90 | x = Dense(classes, activation='softmax', name='prediction')(x) 91 | 92 | model = Model(img_input, x, name='mnist_digit') 93 | model.compile(optimizer='adam', 94 | loss='categorical_crossentropy', 95 | metrics=['accuracy']) 96 | return model 97 | 98 | @staticmethod 99 | def daily(input_shape=(224, 224, 3), classes=40, model_path='../models/vgg16_weights_notop.h5'): 100 | base_model = VGG16(weights=model_path, include_top=False, input_shape=input_shape) 101 | 102 | x = base_model.output 103 | # x = Flatten()(x) 104 | x = GlobalAveragePooling2D()(x) 105 | x = Dense(256, activation='relu')(x) 106 | x = Dropout(0.1)(x) 107 | x = Dense(classes, activation='softmax')(x) 108 | model = Model(inputs=base_model.input, outputs=x) 109 | 110 | for layer in base_model.layers: 111 | layer.trainable = False 112 | 113 | model.compile(optimizer='adam', 114 | loss='categorical_crossentropy', 115 | metrics=['accuracy']) 116 | 117 | return model 118 | 119 | @staticmethod 120 | def conv_vgg16(input_shape=(224, 224, 3), classes=40, model_path='../models/vgg16_weights_notop.h5'): 121 | base_model = VGG16(weights=model_path, include_top=False, input_shape=input_shape) 122 | x = base_model.output 123 | model = Model(input=base_model.input, outputs=x) 124 | model.compile(optimizer='adam', 125 | loss='categorical_crossentropy', 126 | metrics=['accuracy']) 127 | return model 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /functions.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | from PIL import Image 4 | import json 5 | import pickle 6 | import seaborn 7 | import os 8 | seaborn.set_style(style='darkgrid') 9 | 10 | 11 | class Functions: 12 | def __init__(self): 13 | pass 14 | 15 | @staticmethod 16 | def read_images_from_directory(directory, target_size=(64, 64), gray=False, limits=np.Inf, shuffle=False): 17 | images, cnt = [], 0 18 | for i, image_name in enumerate(os.listdir(directory)): 19 | image_path = os.path.join(directory, image_name) 20 | image = np.array(Image.open(image_path).resize(target_size)) 21 | if (image.shape[-1] == 3 or gray) and (cnt < limits): 22 | images.append(image) 23 | cnt = cnt + 1 24 | if shuffle: 25 | np.random.shuffle(images) 26 | return np.array(images) 27 | 28 | @staticmethod 29 | def read_images_from_directories(directory, target_size=(64, 64), gray=False, max_classes=100, per_class=np.Inf, 30 | shuffle=False, get_counts=False, init_json=False, json_path=None): 31 | images, labels, counts, y_dict = [], [], [], {} 32 | temp_path = os.path.join(directory, 'index.json') 33 | if json_path is None: 34 | json_path = temp_path 35 | if not os.path.exists(json_path): 36 | init_json = True 37 | if init_json: 38 | y_dict = Functions.write_json(directory, json_path) 39 | else: 40 | y_dict = Functions.read_json(json_path) 41 | if not os.path.exists(temp_path): 42 | _ = Functions.write_json(json_path=temp_path, y_dict=y_dict) 43 | 44 | for i, label in y_dict.items(): 45 | dir_ = os.path.join(directory, label) 46 | temp = Functions.read_images_from_directory(dir_, target_size, gray, per_class, shuffle) 47 | images.append(temp) 48 | labels.append([i for _ in temp]) 49 | counts.append(temp.shape[0]) 50 | if int(i) >= max_classes: 51 | break 52 | 53 | images = np.concatenate(images, axis=0) 54 | labels = np.concatenate(labels, axis=0) 55 | counts = np.array(counts) 56 | if shuffle: 57 | index = np.arange(len(images)) 58 | np.random.shuffle(index) 59 | images = images[index] 60 | labels = labels[index] 61 | if get_counts: 62 | return images, labels, counts 63 | else: 64 | return images, labels 65 | 66 | @staticmethod 67 | def split_train_test(images, labels, counts, train_ratio=0.8): 68 | x, y, n = images, labels, counts 69 | x_train, y_train, x_test, y_test = [[] for _ in range(4)] 70 | now = {} 71 | for i, z in enumerate(x): 72 | if y[i] not in now: 73 | now[y[i]] = 0 74 | now[y[i]] += 1 75 | if now[y[i]] < n[y[i]] * train_ratio: 76 | x_train.append(z) 77 | y_train.append(y[i]) 78 | else: 79 | x_test.append(z) 80 | y_test.append(y[i]) 81 | x_train = np.array(x_train) 82 | y_train = np.array(y_train) 83 | x_test = np.array(x_test) 84 | y_test = np.array(y_test) 85 | return (x_train, y_train), (x_test, y_test) 86 | 87 | @staticmethod 88 | def write_json(directory=None, json_path=None, y_dict=None): 89 | if y_dict is None: 90 | i, y_dict = 0, {} 91 | for label in os.listdir(directory): 92 | if os.path.isdir(os.path.join(directory, label)): 93 | y_dict[i] = label 94 | i = i + 1 95 | with open(json_path, 'w') as f: 96 | json.dump(y_dict, f, ensure_ascii=False, indent=4) 97 | return y_dict 98 | 99 | @staticmethod 100 | def read_json(json_path): 101 | y_dict, temp = {}, {} 102 | with open(json_path, 'r') as f: 103 | temp = json.load(f) 104 | for i, label in temp.items(): 105 | y_dict[int(i)] = label 106 | return y_dict 107 | 108 | @staticmethod 109 | def show_images_from_directory(directory, target_size=(64, 64), gray=False, subdir=True, limits=100, fname=None): 110 | if subdir: 111 | classes = 0 112 | for label in os.listdir(directory): 113 | if os.path.isdir(os.path.join(directory, label)): 114 | classes += 1 115 | max_classes = min([limits, classes]) 116 | per_class = np.floor(limits / max_classes) 117 | x, y = Functions.read_images_from_directories(directory, target_size=target_size, gray=gray, 118 | max_classes=max_classes, per_class=per_class, 119 | shuffle=False, get_counts=False, init_json=False) 120 | else: 121 | x = Functions.read_images_from_directory(directory, target_size=target_size, gray=gray, 122 | limits=limits, shuffle=True) 123 | Functions.show_images_from_numpy(x, gray, fname) 124 | 125 | @staticmethod 126 | def show_images_from_numpy(x, gray=False, fname=None): 127 | total = len(x) 128 | rows = np.ceil(np.sqrt(total)) 129 | cols = np.ceil(total / rows) 130 | plt.figure(figsize=(4, 4)) 131 | for i, image in enumerate(x): 132 | plt.subplot(rows, cols, i + 1) 133 | if gray: 134 | plt.imshow(image, cmap=plt.cm.gray_r) 135 | else: 136 | plt.imshow(image) 137 | plt.axis('off') 138 | 139 | if fname is not None: 140 | plt.savefig(fname) 141 | 142 | @staticmethod 143 | def preprocess_input(x): 144 | x = x / 127.5 145 | x = x - 1 146 | return x 147 | 148 | @staticmethod 149 | def undo_input(x): 150 | x = x + 1 151 | x = x * 127.5 152 | x = x.astype(np.uint8) 153 | return x 154 | 155 | @staticmethod 156 | def to_categorical(y, num_class=None, dtype='float32'): 157 | y = np.array(y, dtype='int') 158 | input_shape = y.shape 159 | if input_shape and input_shape[-1] == 1 and len(input_shape) > 1: 160 | input_shape = tuple(y.shape[:-1]) 161 | y = y.ravel() 162 | n = y.shape[0] 163 | if not num_class: 164 | num_class = y.max() + 1 165 | categorical = np.zeros((n, num_class), dtype=dtype) 166 | categorical[np.arange(n), y] = 1 167 | output_shape = input_shape + (num_class,) 168 | categorical = categorical.reshape(output_shape) 169 | return categorical 170 | 171 | @staticmethod 172 | def decode_prediction(prediction, json_path, y_dict=None): 173 | if y_dict is None: 174 | y_dict = Functions.read_json(json_path) 175 | return [y_dict[pred.argmax()] for pred in prediction] 176 | 177 | @staticmethod 178 | def lr_schedual(epoch, epochs): 179 | if epoch < epochs / 4: 180 | return 0.001 181 | elif epoch < epochs * 3 / 4: 182 | return 0.0001 183 | else: 184 | return 0.00005 185 | 186 | @staticmethod 187 | def save_history(his, fname): 188 | with open(fname, 'wb') as f: 189 | pickle.dump(his, f) 190 | 191 | @staticmethod 192 | def load_history(fname): 193 | with open(fname, 'rb') as f: 194 | his = pickle.load(f) 195 | return his 196 | 197 | @staticmethod 198 | def plot_history(his, fname=None, num_xticks=6): 199 | xticks = np.linspace(his.epoch[0], his.epoch[-1]+1, num_xticks+1) 200 | 201 | plt.figure(figsize=(6, 3)) 202 | plt.rcParams['font.sans-serif'] = ['SimHei'] 203 | plt.rcParams['axes.unicode_minus'] = False 204 | plt.subplots_adjust(left=0.12, bottom=0.14, right=0.9, top=0.9, wspace=0.25, hspace=0.20) 205 | plt.subplot(1, 2, 1) 206 | plt.plot(his.epoch, his.history['acc']) 207 | plt.plot(his.epoch, his.history['val_acc']) 208 | plt.legend(['train', 'test']) 209 | plt.xlabel('epoch') 210 | plt.ylabel('accuracy') 211 | plt.xticks(xticks) 212 | 213 | plt.subplot(1, 2, 2) 214 | plt.plot(his.epoch, his.history['loss']) 215 | plt.plot(his.epoch, his.history['val_loss']) 216 | plt.legend(['train', 'test']) 217 | plt.xticks(xticks) 218 | plt.xlabel('epoch') 219 | plt.ylabel('loss') 220 | 221 | plt.show() 222 | 223 | if fname is not None: 224 | plt.savefig(fname) 225 | 226 | @staticmethod 227 | def get_pred_index(pred, num_pred=25, y=None, ratio=0.8): 228 | if y is None: 229 | pred_idx = np.random.choice(np.arange(len(pred)), num_pred) 230 | else: 231 | true_idx, false_idx, num_true = [], [], np.ceil(num_pred * ratio) 232 | for i in range(len(pred)): 233 | if pred[i].argmax() == y[i].argmax(): 234 | true_idx.append(i) 235 | else: 236 | false_idx.append(i) 237 | t1 = np.random.choice(true_idx, int(num_true)) 238 | t2 = np.random.choice(false_idx, int(num_pred - num_true)) 239 | pred_idx = np.concatenate([t1, t2]) 240 | return pred_idx 241 | 242 | @staticmethod 243 | def plot_prediction(x, pred, y=None, fname=None): 244 | total = len(x) 245 | rows = np.floor(np.sqrt(total)) 246 | cols = np.ceil(total / rows) 247 | plt.figure(figsize=(cols, rows)) 248 | plt.rcParams['font.sans-serif'] = ['SimHei'] 249 | plt.rcParams['axes.unicode_minus'] = False 250 | plt.subplots_adjust(left=0.1, bottom=0.1, right=0.9, top=0.9, wspace=0.75, hspace=0.75) 251 | if x.shape[-1] == 1 and len(x.shape) > 2: 252 | x = x.reshape(tuple(x.shape[:-1])) 253 | 254 | for i in range(total): 255 | plt.subplot(rows, cols, i + 1) 256 | if len(x.shape) < 4: 257 | plt.imshow(x[i], cmap=plt.cm.gray_r) 258 | else: 259 | plt.imshow(x[i]) 260 | if y is not None: 261 | if y[i] != pred[i]: 262 | plt.title('{}({})'.format(pred[i], y[i]), color='red', fontsize='medium') 263 | else: 264 | plt.title('{}({})'.format(pred[i], y[i]), fontsize='medium') 265 | else: 266 | plt.title('{}'.format(pred[i]), fontsize='medium') 267 | plt.axis('off') 268 | 269 | plt.show() 270 | 271 | if fname is not None: 272 | plt.savefig(fname) 273 | 274 | @staticmethod 275 | def trans_data(x, y, classes=10): 276 | x = Functions.preprocess_input(x) 277 | y = Functions.to_categorical(y, classes) 278 | if len(x.shape) < 4: 279 | x = np.expand_dims(x, axis=len(x.shape)) 280 | return x, y 281 | 282 | @staticmethod 283 | def load_data(directory, target_size, classes=None, gray=False, shuffle=False): 284 | dir_train = os.path.join(directory, 'train') 285 | dir_test = os.path.join(directory, 'test') 286 | x_train, y_train = Functions.read_images_from_directories(dir_train, target_size, gray=gray, shuffle=shuffle) 287 | x_test, y_test = Functions.read_images_from_directories(dir_test, target_size, gray=gray, shuffle=shuffle) 288 | (x_train, y_train) = Functions.trans_data(x_train, y_train, classes) 289 | (x_test, y_test) = Functions.trans_data(x_test, y_test, classes) 290 | return (x_train, y_train), (x_test, y_test) 291 | --------------------------------------------------------------------------------