{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 1. Phân tích dữ liệu ","metadata":{}},{"cell_type":"code","source":"from sklearn.preprocessing import MultiLabelBinarizer\nfrom sklearn.model_selection import StratifiedKFold\nfrom tqdm.notebook import tqdm\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nimport albumentations\nimport pandas as pd\nimport numpy as np\nimport shutil\nimport os","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#load data\ndf = pd.read_csv('../input/plant-pathology-2021-fgvc8/train.csv', index_col='image')\n#nhãn bằng chữ ban đầu của từng mẫu\nlabels = df.labels.values.copy()\ndf","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nlabel_unique = df.labels.unique()\nprint(label_unique)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.value_counts()\n\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#format train data\ntrain_Y = df['labels'].values.copy() \n# nhìn vào dữ liệu ta thấy rằng 1 mẫu dữ liệu có thể có nhiều nhãn, vậy đây là bài toán đa nhãn\ndf['labels'] = [x.split(' ') for x in df['labels']] \nclasses = ['complex', 'frog_eye_leaf_spot', 'powdery_mildew', 'rust', 'scab', 'healthy']\nscores = MultiLabelBinarizer(classes=classes).fit_transform(df['labels'].values)\ndf = pd.DataFrame(columns=classes, data=scores, index=df.index)\n# df.to_csv('train.csv')\ndf.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Ta nhận thấy rằng tuy đây là bài toán đa nhãn nhưng nhìn vào thực tế những mẫu đã được gán nhãn heathy rồi thì sẽ không gán được những nhãn khác, vậy ta sẽ xây dựng model cho 5 nhãn:complex, frog_eye_leaf_spot,  powdery_mildew,  rust,  scab. Mẫu dữ liệu không được gán nhãn nào trong 5 nhãn trên sẽ đc gán là healthy\n","metadata":{}},{"cell_type":"code","source":"x = [df[x].sum() for x in classes]\nprint(x)\ny = classes\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.style.use('bmh')\nplt.xticks(fontsize =12)\nplt.yticks(fontsize =12)\nplt.xlabel('Category',fontsize =13)\nplt.ylabel('Quantity of Image',fontsize = 13)\nplt.xticks(rotation=50)\ncolor_list = ['#f8a709', '#FF6565', '#2CC9FB', '#37DE5B', '#FF74E9', '#2C99FE']\nplt.bar(y,x, color = color_list,width=0.6)\n\nplt.show()\nprint(\"Số mẫu dữ liệu: \", len(df))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Nhìn vào biểu đồ trên, ta thấy rằng có một số lớp khá ít dữ liệu, nên khi chia dữ liệu dễ bị miss nên ta dùng 5-fold cross validation ","metadata":{}},{"cell_type":"markdown","source":"# 2. Chia fold ","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import KFold\nkfold = KFold(n_splits=5, shuffle=True, random_state = 42)\nfold_ids = np.zeros(len(df))\nfor i, (train_ids, val_ids) in enumerate(kfold.split(df.index, labels)):\n    fold_ids[val_ids] = i\n\nvalue_counts = lambda x: pd.Series.value_counts(x, normalize=True)\ndf_five_folds = pd.DataFrame({\n    'origin_data': df.apply(value_counts).loc[1],\n    'fold_0': df[fold_ids == 0].apply(value_counts).loc[1],\n    'fold_1': df[fold_ids == 1].apply(value_counts).loc[1],\n    'fold_2': df[fold_ids == 2].apply(value_counts).loc[1],\n    'fold_3': df[fold_ids == 3].apply(value_counts).loc[1],\n    'fold_4': df[fold_ids == 4].apply(value_counts).loc[1]})\n\nbar = df_five_folds.plot.bar(figsize=[10, 10], colormap='Spectral', rot=50)\n\nfolds = pd.DataFrame({\n    'image': df.index,\n    'fold': fold_ids})\n\nfolds.to_csv('folds.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Khi sử dụng KFold ta thấy phân bố nhãn trong các fold so với phân bố nhãn trong dữ liệu train ban đầu bị lệch nhau. Với StratifiedKFold ta sẽ thu được tỉ lệ này cân bằng hơn khá nhiều. Với phương pháp này thì nó sẽ chỉ shuffle dữ liệu một lần đầu tiên trước khi bắt đầu chia fold và nó sẽ cố gắng chia sao cho tỷ lệ các class trong các fold là tương đồng nhau.","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import StratifiedKFold\nkfold = StratifiedKFold(n_splits=5, shuffle=True, random_state = 42)\nfold_ids = np.zeros(len(df))\nfor i, (train_ids, val_ids) in enumerate(kfold.split(df.index, labels)):\n    fold_ids[val_ids] = i\n\nvalue_counts = lambda x: pd.Series.value_counts(x, normalize=True)\ndf_five_folds = pd.DataFrame({\n    'origin_data': df.apply(value_counts).loc[1],\n    'fold_0': df[fold_ids == 0].apply(value_counts).loc[1],\n    'fold_1': df[fold_ids == 1].apply(value_counts).loc[1],\n    'fold_2': df[fold_ids == 2].apply(value_counts).loc[1],\n    'fold_3': df[fold_ids == 3].apply(value_counts).loc[1],\n    'fold_4': df[fold_ids == 4].apply(value_counts).loc[1]})\n\nbar = df_five_folds.plot.bar(figsize=[10, 10], colormap='Spectral', rot=50)\n\nfolds = pd.DataFrame({\n    'image': df.index,\n    'fold': fold_ids})\n\nfolds.to_csv('folds.csv', index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Khởi tạo một số tham số**","metadata":{}},{"cell_type":"code","source":"root = '../input/plant-pathology-2021-fgvc8/train_images'\nclasses = [\n        'complex', \n        'frog_eye_leaf_spot', \n        'powdery_mildew', \n        'rust', \n        'scab',\n        'healthy']\nstrategy = tf.distribute.get_strategy()\nbatch_size = 16\n#kích thước mỗi ảnh   \nimg_size = 512\n#số fold đã chia\nfolds = 5 \n#số file .tfrec trong mỗi fold\nsubfolds = 16 \n    ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. Tạo file tfrecords\n","metadata":{}},{"cell_type":"markdown","source":"> **Định nghĩa một số hàm**","metadata":{}},{"cell_type":"code","source":"#tuần tự hóa hình ảnh\ndef _serialize_image(path, transform=None):\n    image = tf.io.read_file(path)\n    image = tf.image.decode_jpeg(image, channels=3)\n    image = tf.image.resize(image, [img_size, img_size])\n    image = tf.cast(image, tf.uint8)\n    \n    if transform is not None:\n        image = transform(image=image.numpy())['image']\n        \n    return tf.image.encode_jpeg(image).numpy()\n\n#tuần tự hóa các mẫu dữ liệu\ndef _serialize_sample(image, image_name, label):\n    feature = {\n        'image': tf.train.Feature(bytes_list=tf.train.BytesList(value=[image])),\n        'image_name': tf.train.Feature(bytes_list=tf.train.BytesList(value=[image_name])),\n        'complex': tf.train.Feature(int64_list=tf.train.Int64List(value=[label[0]])),\n        'frog_eye_leaf_spot': tf.train.Feature(int64_list=tf.train.Int64List(value=[label[1]])),\n        'powdery_mildew': tf.train.Feature(int64_list=tf.train.Int64List(value=[label[2]])),\n        'rust': tf.train.Feature(int64_list=tf.train.Int64List(value=[label[3]])),\n        'scab': tf.train.Feature(int64_list=tf.train.Int64List(value=[label[4]])),\n        'healthy': tf.train.Feature(int64_list=tf.train.Int64List(value=[label[5]]))}\n    sample = tf.train.Example(features=tf.train.Features(feature=feature))\n    return sample.SerializeToString()\n\n#tuần tự hóa các fold\ndef serialize_fold(fold, name, transform=None, bar=None):\n    samples = []\n    \n    for image_name, labels in fold.iterrows():\n        path = os.path.join(root, image_name)\n        image = _serialize_image(path, transform=transform)\n        samples.append(_serialize_sample(image, image_name.encode(), labels))\n    \n    with tf.io.TFRecordWriter(name + '.tfrec') as writer:\n        [writer.write(x) for x in samples]\n        \n    if bar is not None:\n        bar.update(1)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"total = folds * subfolds\n\nwith tqdm(total=total) as bar:\n\n    for i in range(folds):\n\n        df_fold = df[fold_ids == i]\n        \n        folder = f'fold_{i}'\n        \n        try:\n            os.mkdir(folder)\n        except FileExistsError:\n            shutil.rmtree(folder)\n            os.mkdir(folder)\n        \n        for k, subfold in enumerate(np.array_split(df_fold, subfolds)):\n            name=os.path.join(folder, '%.2i-%.3i' % (k, len(subfold)))\n            serialize_fold(subfold, name=name, bar=bar)\n       ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"run test","metadata":{}}]}