{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":4829,"databundleVersionId":44847,"sourceType":"competition"}],"dockerImageVersionId":30587,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# **DSI206 Final Project**","metadata":{}},{"cell_type":"markdown","source":"**Yelp Restaurant Photo Classification**","metadata":{}},{"cell_type":"markdown","source":"# Resnet50 SCORES:   ","metadata":{}},{"cell_type":"markdown","source":"\n**Introduction**\n* จุดมุ่งหมาย: เพื่อศึกษาและลงมือทำการทำ Multi Label Image Classification โดยสร้างโมเดลที่สามารถทำนายlabelsจากรูปภาพได้\n* เราได้เลือกใช้ Multiclass Logistic Regression ในการทำนาย เนื่องจาก Multiclass Logistic Regression เหมาะสำหรับงาน image classification ที่ต้องการทำนายหลายๆ ป้ายกำกับ (multiple labels) หรือหลายคลาสต่อภาพ.","metadata":{}},{"cell_type":"markdown","source":"# 1.Data loading\n* นำเข้าข้อมูลและแพคเกจ","metadata":{}},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd\nimport os\nimport numpy as np\nfrom tensorflow.keras.preprocessing import image\nfrom tensorflow.keras.applications import ResNet50\nfrom tensorflow.keras.applications.resnet50 import preprocess_input\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Input, Conv2D, Flatten\nfrom sklearn.preprocessing import MultiLabelBinarizer\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.multioutput import MultiOutputClassifier\nfrom sklearn.metrics import accuracy_score, classification_report\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.multioutput import MultiOutputClassifier\nfrom sklearn.linear_model import LogisticRegression\nfrom IPython.display import display, Image\nimport random \n","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:04:15.556301Z","iopub.execute_input":"2023-11-27T16:04:15.556807Z","iopub.status.idle":"2023-11-27T16:04:15.564196Z","shell.execute_reply.started":"2023-11-27T16:04:15.556767Z","shell.execute_reply":"2023-11-27T16:04:15.563079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-11-27T16:04:15.565991Z","iopub.execute_input":"2023-11-27T16:04:15.566265Z","iopub.status.idle":"2023-11-27T16:04:15.583925Z","shell.execute_reply.started":"2023-11-27T16:04:15.566243Z","shell.execute_reply":"2023-11-27T16:04:15.582962Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n# extract files\n!apt install pigz\n!pigz -dc /kaggle/input/yelp-restaurant-photo-classification/sample_submission.csv.tgz | tar xf -\n!pigz -dc /kaggle/input/yelp-restaurant-photo-classification/test_photo_to_biz.csv.tgz | tar xf -\n!pigz -dc /kaggle/input/yelp-restaurant-photo-classification/test_photos.tgz | tar xf -\n!pigz -dc /kaggle/input/yelp-restaurant-photo-classification/train.csv.tgz | tar xf -\n!pigz -dc /kaggle/input/yelp-restaurant-photo-classification/train_photo_to_biz_ids.csv.tgz | tar xf -\n!pigz -dc /kaggle/input/yelp-restaurant-photo-classification/train_photos.tgz | tar xf -","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:04:15.585063Z","iopub.execute_input":"2023-11-27T16:04:15.585353Z","iopub.status.idle":"2023-11-27T16:09:58.100163Z","shell.execute_reply.started":"2023-11-27T16:04:15.585328Z","shell.execute_reply":"2023-11-27T16:09:58.098821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load training data that maps business ID to labels\ntrain = pd.read_csv('train.csv')\ndisplay(train.head())\nprint('Shape of train data:', train.shape)\nprint('Number of unique businesses:', train.shape[0])","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:09:58.102779Z","iopub.execute_input":"2023-11-27T16:09:58.103117Z","iopub.status.idle":"2023-11-27T16:09:58.127873Z","shell.execute_reply.started":"2023-11-27T16:09:58.103088Z","shell.execute_reply":"2023-11-27T16:09:58.126984Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load training data that maps photos to business ID\ntrain_photo_to_id = pd.read_csv('train_photo_to_biz_ids.csv')\ndisplay(train_photo_to_id.head())\nprint('Shape of train_photo_to_id:', train_photo_to_id.shape)\nprint('Number of images in training set:', train_photo_to_id.shape[0])","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:09:58.128972Z","iopub.execute_input":"2023-11-27T16:09:58.129236Z","iopub.status.idle":"2023-11-27T16:09:58.230392Z","shell.execute_reply.started":"2023-11-27T16:09:58.129213Z","shell.execute_reply":"2023-11-27T16:09:58.229429Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_biz=pd.read_csv('./train_photo_to_biz_ids.csv')\ntest_biz=pd.read_csv('./test_photo_to_biz.csv')\ntrain=pd.read_csv('./train.csv')\nsub=pd.read_csv('./sample_submission.csv')","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:09:58.231766Z","iopub.execute_input":"2023-11-27T16:09:58.232102Z","iopub.status.idle":"2023-11-27T16:09:58.681523Z","shell.execute_reply.started":"2023-11-27T16:09:58.232074Z","shell.execute_reply":"2023-11-27T16:09:58.680685Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_biz=train_biz.groupby(\"business_id\").last()\nprint(train_biz.head())","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:09:58.682755Z","iopub.execute_input":"2023-11-27T16:09:58.683055Z","iopub.status.idle":"2023-11-27T16:09:58.697914Z","shell.execute_reply.started":"2023-11-27T16:09:58.683029Z","shell.execute_reply":"2023-11-27T16:09:58.696936Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train=train.merge(train_biz,on=\"business_id\")","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:09:58.701840Z","iopub.execute_input":"2023-11-27T16:09:58.702146Z","iopub.status.idle":"2023-11-27T16:09:58.709987Z","shell.execute_reply.started":"2023-11-27T16:09:58.702121Z","shell.execute_reply":"2023-11-27T16:09:58.708985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['labs']=train['labels'].apply(lambda x:str(x).split(' '))","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:09:58.711118Z","iopub.execute_input":"2023-11-27T16:09:58.711477Z","iopub.status.idle":"2023-11-27T16:09:58.728353Z","shell.execute_reply.started":"2023-11-27T16:09:58.711451Z","shell.execute_reply":"2023-11-27T16:09:58.727439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test=test_biz.groupby(\"business_id\").last()\ntest","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:09:58.729537Z","iopub.execute_input":"2023-11-27T16:09:58.730189Z","iopub.status.idle":"2023-11-27T16:09:58.857678Z","shell.execute_reply.started":"2023-11-27T16:09:58.730158Z","shell.execute_reply":"2023-11-27T16:09:58.856621Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load ResNet50 as the base model\nbase_model = ResNet50(weights='imagenet', include_top=False, input_shape=(600, 600, 3))\nn_filters = 32\nkernel_size = 3\npool_size = 2\ninputs = Input(shape=(600, 600, 3))\n\n# ResNet50 feature extraction\nbase_features = base_model(inputs, training=False)\n\n# Additional convolutional layers for dimensionality reduction\nx = Conv2D(n_filters, kernel_size, activation='relu')(base_features)\nx = Conv2D(n_filters, kernel_size, activation='relu')(x)\nx = Flatten()(x)\n\n# Create the feature extraction model\nmodel_fet = Model(inputs, x)\n\ndef load_and_preprocess_image(file_path):\n    img = image.load_img(file_path, target_size=(600, 600))\n    img_array = image.img_to_array(img)\n    img_array = np.expand_dims(img_array, axis=0)\n    img_array = preprocess_input(img_array)\n    return img_array\n\ndef extract_features(file_paths):\n    features = []\n   \n    for i, path in enumerate(file_paths):\n        path = \"/kaggle/working/train_photos/\" + str(path) + \".jpg\"\n        img_array = load_and_preprocess_image(path)\n        feature = model_fet.predict(img_array)\n        feature = np.squeeze(feature)\n        features.append(feature)\n        print(i)\n    return np.array(features)","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2023-11-27T16:09:58.858909Z","iopub.execute_input":"2023-11-27T16:09:58.859219Z","iopub.status.idle":"2023-11-27T16:10:03.454562Z","shell.execute_reply.started":"2023-11-27T16:09:58.859193Z","shell.execute_reply":"2023-11-27T16:10:03.453607Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Display summary for the feature extraction model\nprint(\"\\nFeature Extraction Model Summary:\")\nmodel_fet.summary()","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:10:03.455842Z","iopub.execute_input":"2023-11-27T16:10:03.456179Z","iopub.status.idle":"2023-11-27T16:10:03.504632Z","shell.execute_reply.started":"2023-11-27T16:10:03.456149Z","shell.execute_reply":"2023-11-27T16:10:03.503599Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"features = extract_features(train['photo_id'].tolist())","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2023-11-27T16:10:03.505960Z","iopub.execute_input":"2023-11-27T16:10:03.506286Z","iopub.status.idle":"2023-11-27T16:13:05.680995Z","shell.execute_reply.started":"2023-11-27T16:10:03.506260Z","shell.execute_reply":"2023-11-27T16:13:05.679951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mlb = MultiLabelBinarizer()\none_hot_labels = mlb.fit_transform(train['labs'])\none_hot_labels=one_hot_labels[:,:-1]","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:13:05.683279Z","iopub.execute_input":"2023-11-27T16:13:05.683558Z","iopub.status.idle":"2023-11-27T16:13:05.694518Z","shell.execute_reply.started":"2023-11-27T16:13:05.683535Z","shell.execute_reply":"2023-11-27T16:13:05.693518Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train, X_test, y_train, y_test = train_test_split(features, one_hot_labels, test_size=0.2, random_state=42)\nbase_classifier = LogisticRegression(C=0.001,solver=\"newton-cholesky\")\nclassifier = MultiOutputClassifier(base_classifier)\nclassifier.fit(X_train, y_train)\npredictions = classifier.predict(X_test)\nprint(\"\\nClassification Report for ResNet50-based Model:\\n\", classification_report(y_test, predictions))","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:13:05.695665Z","iopub.execute_input":"2023-11-27T16:13:05.695958Z","iopub.status.idle":"2023-11-27T16:15:45.620461Z","shell.execute_reply.started":"2023-11-27T16:13:05.695934Z","shell.execute_reply":"2023-11-27T16:15:45.619172Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def pipline_predict(photo_id):\n    path=\"/kaggle/working/test_photos/\"+ str(photo_id)+\".jpg\"\n    img = image.load_img(path, target_size=(600, 600))\n    img_array = image.img_to_array(img)\n    img_array = np.expand_dims(img_array, axis=0)\n    img_array = preprocess_input(img_array)\n    feature = model_fet.predict(img_array)\n    feature = np.squeeze(feature)\n    y_pred=classifier.predict([feature])\n    y_pred=np.where(y_pred > 0.5)[1]\n    return ' '.join(map(str, y_pred))","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:15:45.622357Z","iopub.execute_input":"2023-11-27T16:15:45.623074Z","iopub.status.idle":"2023-11-27T16:15:45.634164Z","shell.execute_reply.started":"2023-11-27T16:15:45.623029Z","shell.execute_reply":"2023-11-27T16:15:45.632889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def pipline_predict_proba(photo_id):\n    path=\"/kaggle/working/test_photos/\"+ str(photo_id)+\".jpg\"\n    img = image.load_img(path, target_size=(600, 600))\n    img_array = image.img_to_array(img)\n    img_array = np.expand_dims(img_array, axis=0)\n    img_array = preprocess_input(img_array)\n    feature = model_fet.predict(img_array)\n    feature = np.squeeze(feature)\n    y_pred=classifier.predict_proba([feature])\n    return y_pred","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:15:45.635916Z","iopub.execute_input":"2023-11-27T16:15:45.636496Z","iopub.status.idle":"2023-11-27T16:15:45.652248Z","shell.execute_reply.started":"2023-11-27T16:15:45.636447Z","shell.execute_reply":"2023-11-27T16:15:45.650709Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pipline_predict(405544)","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:15:45.654046Z","iopub.execute_input":"2023-11-27T16:15:45.654593Z","iopub.status.idle":"2023-11-27T16:15:45.791262Z","shell.execute_reply.started":"2023-11-27T16:15:45.654550Z","shell.execute_reply":"2023-11-27T16:15:45.790327Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test[\"labels\"]=np.vectorize(pipline_predict)(test[\"photo_id\"])","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2023-11-27T16:15:45.792601Z","iopub.execute_input":"2023-11-27T16:15:45.793306Z","iopub.status.idle":"2023-11-27T16:31:10.521299Z","shell.execute_reply.started":"2023-11-27T16:15:45.793268Z","shell.execute_reply":"2023-11-27T16:31:10.520444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:31:10.524833Z","iopub.execute_input":"2023-11-27T16:31:10.525114Z","iopub.status.idle":"2023-11-27T16:31:10.536959Z","shell.execute_reply.started":"2023-11-27T16:31:10.525090Z","shell.execute_reply":"2023-11-27T16:31:10.535837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# สุ่มเลือก 3 รูปภาพ\nrandom_photo_ids = random.sample(test['photo_id'].tolist(), 3)\n\n# วนลูปแสดงผลลัพธ์สำหรับทุกรูปภาพที่สุ่มมา\nfor photo_id in random_photo_ids:\n    prediction = pipline_predict(photo_id)\n    prediction_proba = pipline_predict_proba(photo_id)\n    \n    # โหลดรูปภาพ\n    img_path = \"/kaggle/working/test_photos/\" + str(photo_id) + \".jpg\"\n    img = Image(filename=img_path, width=300, height=300)\n    \n    # แสดงรูปภาพ\n    display(img)\n\n    print(\"Photo ID:\", photo_id)\n    print(\"Prediction:\", prediction)\n    print(\"Predicted Probabilities:\")\n    print(prediction_proba)","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:31:10.538176Z","iopub.execute_input":"2023-11-27T16:31:10.538430Z","iopub.status.idle":"2023-11-27T16:31:11.074189Z","shell.execute_reply.started":"2023-11-27T16:31:10.538408Z","shell.execute_reply":"2023-11-27T16:31:11.073218Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test=test.reset_index()\ntest\n","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:31:11.075689Z","iopub.execute_input":"2023-11-27T16:31:11.076072Z","iopub.status.idle":"2023-11-27T16:31:11.091807Z","shell.execute_reply.started":"2023-11-27T16:31:11.076035Z","shell.execute_reply":"2023-11-27T16:31:11.090533Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test[[\"business_id\",\"labels\"]].to_csv('submission.csv',index=False)","metadata":{"execution":{"iopub.status.busy":"2023-11-27T16:31:11.093010Z","iopub.execute_input":"2023-11-27T16:31:11.093314Z","iopub.status.idle":"2023-11-27T16:31:11.132395Z","shell.execute_reply.started":"2023-11-27T16:31:11.093289Z","shell.execute_reply":"2023-11-27T16:31:11.131435Z"},"trusted":true},"execution_count":null,"outputs":[]}]}