{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"import tensorflow.compat.v1 as tf\nimport tensorflow.compat.v1.gfile as gfile\n# from tensorflow.python.platform import gfile\nimport csv,os,json,cv2,math,shutil,time\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport sys\n\ntf.disable_v2_behavior()\n\nroot_dir = os.path.join('..', 'input')\nmodel_dir = os.path.join(root_dir,'pretrainedmodel')\ndata_dir = os.path.join(root_dir,'landmark-recognition-2020')\nlabel_dict_dir = os.path.join(root_dir,'label-dict')\n\nsys.path.append(model_dir)\nsys.path.append(root_dir)\nimport tf_slim as slim\nimg_format = {'png', 'bmp', 'jpg'}\nfrom inception_resnet_v1 import inference as inception_resnet_v1 \n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_root_dir = os.path.join(data_dir,'test')\ntrain_root_dir = os.path.join(data_dir,'train')\n\ncsv_path = os.path.join(data_dir,'train.csv')\npb_path = os.path.join(model_dir,'pb_model.pb')\nnode_dict = {'input': 'input:0',\n             'phase_train':'phase_train:0',\n             'embeddings': 'embeddings:0',\n             'keep_prob': 'keep_prob:0'\n             }\nimg_format = {'png', 'bmp', 'jpg'}\npredict_num = 20\ndata_range = None\n\n\n#----get train paths\n#train_uid_path,label_dict = get_path_labels(train_root_dir,csv_path)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#----from the label dict to get the label2uid dict\nlabel2uid_dict = dict()\njson_files = [file.path for file in os.scandir(label_dict_dir) if file.name.split(\".\")[-1] == 'json']\nwith open(json_files[0],'r') as f:\n    label_dict = json.load(f)\n    \nfor uid, label in label_dict.items():\n    label2uid_dict[label] = uid","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"# print(tf.__version__)\n\nfor obj in os.scandir(label_dict_dir):\n#     if obj.is_dir():\n    print(obj.path)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#----get test paths\ntest_paths = list()\n\nfor dir_name, sub_dirnames, filenames in os.walk(test_root_dir):\n    if len(filenames) > 0:\n        for file in filenames:\n            if file.split(\".\")[-1] in img_format:\n                full_path = os.path.join(dir_name,file)\n                test_paths.append(full_path)\nlen_path = len(test_paths)\nprint(\"test image quantity:\",len_path)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class Prediction():\n    def __init__(self):\n        pass\n        # ----var\n        #paths = list()\n        \n#         print(\"--------Prediction init --------\")\n\n#         #----get paths from json file\n# #         if isinstance(path_source, str):\n# #             if path_source[-4:] == 'json':\n# #                 with open(path_source, 'r')as f:\n# #                     content = json.load(f)\n# #                     paths = content['paths']\n\n#         len_path = len(paths)\n\n\n#         if len_path == 0:\n#             raise  ValueError\n\n#         else:\n#             print(\"image quantity:\",len_path)\n#             #----local var to global\n#             self.paths = paths\n#             self.len_path = len_path\n#             #self.path_source = path_source\n\n    def model_init(self):\n        #----var\n        model_shape = [None,112,112,3]\n        feature_num = 256\n        class_num = 81313\n        lr = 5e-4\n        \n        print(\"--------Prediction model init --------\")\n\n        # ----tf placeholder\n        tf_input = tf.placeholder(dtype=tf.float32, shape=model_shape, name=\"input\")\n        tf_label_batch = tf.placeholder(dtype=tf.int32, shape=[None], name=\"label_batch\")\n        tf_phase_train = tf.placeholder(tf.bool, name='phase_train')\n        tf_keep_prob = tf.placeholder(tf.float32, name='keep_prob')\n\n        #----inference\n        prelogits, _ = inception_resnet_v1(tf_input, tf_keep_prob, phase_train=tf_phase_train,\n                                           bottleneck_layer_size=feature_num,\n                                           weight_decay=0.0)\n        embeddings = tf.nn.l2_normalize(prelogits, 1, 1e-10, name='embeddings')\n\n        #----loss\n        logits = tf.layers.dense(inputs=prelogits, units=class_num, activation=None, name=\"logits\")\n        predict = tf.nn.softmax(logits, name='predict')\n        loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(\n            labels=tf_label_batch, logits=logits), name='loss')\n\n        #----opt\n        #optimizer = tf.train.AdamOptimizer(learning_rate=lr).minimize(loss)\n\n        # ----local vars to global\n        self.model_shape = model_shape\n        self.feature_num = feature_num\n        self.lr = lr\n        self.tf_input = tf_input\n        self.tf_label_batch = tf_label_batch\n        self.tf_phase_train = tf_phase_train\n        self.tf_keep_prob = tf_keep_prob\n        self.embeddings = embeddings\n        self.prelogit = prelogits\n        self.predict = predict\n\n    def get_prediction(self,paths,save_dir,label2uid_dict,predict_num=1):\n        #----var\n        batch_size = 192\n        predictions = list()\n        saver = tf.train.Saver(max_to_keep=2)\n        argsort = list()\n        \n        #----paths\n        len_path = len(paths)\n        if len_path == 0:\n            raise  ValueError\n        else:\n            print(\"image quantity:\",len_path)\n\n        #----GPU setting\n        config = tf.ConfigProto(log_device_placement=True,\n                                allow_soft_placement=True,  # 允許當找不到設備時自動轉換成有支援的設備\n                                )\n        config.gpu_options.allow_growth = True\n\n        with tf.Session(config=config) as sess:\n            # ----restore the model\n            files = [file.name for file in os.scandir(save_dir) if file.name.split(\".\")[-1] == \"meta\"]\n\n            if len(files) == 0:  # 沒有任何之前的權重\n                sess.run(tf.global_variables_initializer())\n                print('no previous model param can be used')\n            else:\n                # self.saver.restore(sess, tf.train.latest_checkpoint(self.save_dir))\n                num_list = list()\n                for file in files:\n                    num_list.append(int(file.split(\".\")[0].split(\"-\")[-1]))\n                argmax = np.argmax(num_list)\n                model_path = os.path.join(model_dir,files[argmax].split(\".\")[0])\n                #check_name = files[-1].split(\"/\")[-1].split(\".\")[0]\n                #model_path = os.path.join(save_dir, check_name)\n                saver.restore(sess, model_path)\n                msg = 'use previous model param:{}'.format(model_path)\n                print(msg)\n\n            feed_dict = {self.tf_phase_train: False, self.tf_keep_prob: 1.0}\n\n            ites = math.ceil(len_path / batch_size)\n            for idx in range(ites):\n                num_start = idx * batch_size\n                num_end = np.minimum(num_start + batch_size, len_path)\n\n                # ----batch data\n                batch_dim = [num_end - num_start]\n                batch_dim.extend(self.model_shape[1:])\n                batch_data = np.zeros(batch_dim, dtype=np.float32)\n                for idx_path, path in enumerate(paths[num_start:num_end]):\n                    img = cv2.imread(path)\n                    if img is None:\n                        print(\"read failed:\", path)\n                    else:\n                        img = cv2.resize(img, (self.model_shape[2], self.model_shape[1]))\n                        img = img[:, :, ::-1]\n                        batch_data[idx_path] = img\n\n                # ----img data norm\n                batch_data /= 255\n                print(\"batch_data shape:\", batch_data.shape)\n\n                feed_dict[self.tf_input] = batch_data\n\n                temp_predict = sess.run(self.predict, feed_dict=feed_dict)#[batch_size,81313]\n                #print(\"num_start:{}, num_end:{}, temp_predict shape:{}\".format(num_start, num_end, temp_predict.shape))\n                temp_argsort = np.argsort(temp_predict,axis=-1)\n                temp_argsort = temp_argsort[:, -predict_num:]\n                argsort.extend(temp_argsort)\n                #----get the biggest predict_num probabilities\n                for arg_1, pred in zip(temp_argsort,temp_predict):\n                    predictions.append(pred[arg_1])\n\n            #----\n            argsort = np.array(argsort)\n            # argsort = np.argsort(predictions, axis=-1)\n            # argsort = argsort[:, -predict_num:]\n            print(\"argsort shape\", argsort.shape)\n\n            #----data distribution\n#             prob_list = list()\n#             for seq, prob in zip(argsort,predictions):\n#                 prob_list.append(prob[seq])\n\n#             argsort.astype(int)\n#             prob_list = np.array(prob_list,dtype=float)\n\n            #----output csv\n            csv_path = 'submission.csv'\n            with open(csv_path, 'w') as submission_csv:\n                csv_writer = csv.DictWriter(submission_csv, fieldnames=['id', 'landmarks'])\n                csv_writer.writeheader()\n                for test_path, label,prediction in zip(paths, argsort,predictions):\n                    uid = test_path.split(\"/\")[-1].split(\".\")[0]\n                    \n                    score = prediction[-1]\n                    csv_writer.writerow({'id': uid, 'landmarks': f'{label2uid_dict[label[-1]]} {score}'})\n\n            print(\"csv_path is saved in \",csv_path)\n\n\n\n#             content = {'paths':self.paths, 'argsort':argsort.tolist(),'prob':prob_list.tolist()}\n\n# #             json_path = os.path.join(os.path.dirname(self.path_source),'argsort_prob.json')\n#             json_path = 'argsort_prob.json'\n#             with open(json_path, 'w') as f:\n#                 json.dump(content,f)\n#                 print(\"json_path is saved in \",json_path)\n\n#             return json_path","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#----prediction\n'''\n●I use my pretrained model weights to do predictions\n●I created a classification model with inception resnet v1. The loss func. is the normal cross entropy\n●In my original opinions, I wanna use embeddings to do matchings but it needs more than 13 GB RAM.So I gave up.\n●Because of data imbalance, specific number images of each class are selected to train. For example, 3 images of each class are randomly selected every epoch to do optimizers without data imbalance.\n●Augmentation method is also adopted. But I do it when reading the batch data.\n●The most difficult point is not to recognize the landmark but the faces shown in testing images.\n\n'''\npredict_num = 1\npre = Prediction()\npre.model_init()\npre.get_prediction(test_paths,model_dir,label2uid_dict,predict_num=predict_num)\n","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}