{"cells":[{"metadata":{},"cell_type":"markdown","source":"# 0. Introduction\n**Note** APTOS participants please ignore this kernel as it is a Thai verision of my *Preprocessing by Cropping & Ben's* kernel. I create this Thai version since it is more suitable to communicate with Thai community.\n\n"},{"metadata":{},"cell_type":"markdown","source":"\n# 1. อารัมภบท\n\nสวัสดีครับเพื่อนๆ ขอต้นรับเข้าสู่ **AI Workshop ลำดับ 6** ของทีมงาน ThAIKeras ครับ (ดู[รายชื่อ Workshops ก่อนหน้านี้ได้ที่นี่](https://thaikeras.com/category/workshop/))\n\nWorkshop นี้จะเป็นการประยุกต์งาน **Deep Computer Vision** เพื่อมาช่วยคัดกรองผู้ป่วยที่เป็นโรค **เบาหวานขึ้นตา** หรือทางการแพทย์เรียกว่า Diabetic Retinophaty ครับ\n\n![](https://i.ibb.co/PmTTwSs/AI-for-Eyes.png)\n\n[โรคเบาหวานขึ้นตานี้](www.banphaeoeyecenter.com/know2.htm)เป็นสาเหตุสำคัญมากสาเหตุหนึ่งของการตาบอด  เนื่องจากโรคนี้สามารถแบ่งความรุนแรงได้เป็น 5 ระดับ ในกรณีที่เราสามารถตรวจเจอตั้งแต่เนิ่นๆ การรักษาก็จะทำได้ง่ายขึ้นอย่างมากเลยครับ **[โดยเรามีจุดสังเกตสิ่งผิดปกติบนดวงตาอย่างน้อย 5 จุดดังรูปต่อไปนี้](https://www.eyeops.com/contents/our-services/eye-diseases/diabetic-retinopathy)**. credit ภาพจาก https://www.eyeops.com/\n![credit : https://www.eyeops.com/](https://sa1s3optim.patientpop.com/assets/images/provider/photos/1947516.jpeg)\n\nดังนั้นทาง Kaggle และ **โรงพยาบาลตา Aravind (Aravind Eye Hospital)** ซึ่งเป็นโรงพยาบาลตาที่ใหญ่ที่สุดในโลกที่อินเดียที่ได้ช่วยเหลือคนยากจนที่มีปัญหาทางสายตามาตลอดโดยไม่คิดค่าใช้จ่าย จึงได้คิดโครงการสร้างระบบ AI เพื่อช่วยวัดระดับเบาหวานขึ้นตาทั้ง 5 ระดับได้อย่างอัตโนมัติ ซึ่งจะเป็นการลดการพึ่งพาจักษุแพทย์และทำให้การรักษามีประสิทธิภาพมากขึ้นเป็นอย่างมากครับ\n\nเหมือนอย่างทุกครั้งครับ [โปรเจกต์นี้บน Kaggle จะเป็นโปรเจกต์ที่ AI / Data Scientists จากทั่วโลกจะมาร่วมมือกันทำ โดยไม่มีค่าใช้จ่าย (โดยอยู่ในรูปแบบของการแข่งขัน)](https://thaikeras.com/community/%E0%B9%80%E0%B8%81%E0%B8%B5%E0%B9%88%E0%B8%A2%E0%B8%A7%E0%B8%81%E0%B8%B1%E0%B8%9A-kaggle/kaggle-%E0%B8%84%E0%B8%B7%E0%B8%AD-lab-%E0%B8%97%E0%B8%B5%E0%B9%88%E0%B8%94%E0%B8%B5%E0%B8%97%E0%B8%B5%E0%B9%88%E0%B8%AA%E0%B8%B8%E0%B8%94%E0%B9%83%E0%B8%99%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B9%80/) ซึ่งทาง Kaggle จะจัดสรรทรัพยากรเครื่อง GPU Virtual Machine ให้ผู้เข้าร่วมทุกคนฟรี และทางทีมงาน ThAIKeras ก็จะถือโอกาสนี้ได้แชร์เรื่องราวดีดีนี้กับเพื่อนๆ ด้วยครับ โดยทางทีมงานจะแบ่ง Workshop นี้ออกเป็นหลายๆ ส่วนด้วยกัน Workshop แรกนี้ก็จะเป็นส่วน **การทำความเข้าใจข้อมูล (Data Exploration) และการ Preprocess ข้อมูล** เบื้องต้นนั่นเองครับ\n\nรายชื่อ workshop ภาคต่อเร็วๆ นี้ครับ\n* Augmentation รูปภาพอย่างมืออาชีพด้วย Albumentation [กดที่นี่เพื่อไปภาค 2](https://www.kaggle.com/ratthachat/workshop-augmentation-image-ai-for-eyes-2)\n* สร้างโมเดลเพื่อไว้เทรนข้อมูล และวัดความแม่นยำ\n* วิเคราะห์ความสมเหตุสมผลของโมเดลด้วยเทคนิก Heatmap Grad-CAM\n\n\nอนึ่งการแข่งขันหรือโปรเจกต์นี้เป็น LIVE project ซึ่งยังดำเนินอยู่ในปัจจุบันและจะจบในวันที่ 5 กันยายน 2562 เพื่อนๆ ถ้ามีเวลาติดตามก็จะเห็นความก้าวหน้าของโปรเจกต์นี้ไปจนจบครับว่าสุดท้าย ระบบ AI ที่ทุกคนร่วมกันสร้างและแข่งกันนั้นจะมีความแม่นยำอยู่ในระดับใด ซึ่งทีมงานขอทำนายว่าจะมีความแม่นยำเทียบเท่าจักษุแพทย์ชั้นนำเลยครับ\n\nถ้าพร้อมแล้วเราไปรับชมกันได้เลยครับ\n"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"import os, sys\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport cv2\nfrom sklearn.model_selection import train_test_split\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")\nIMG_SIZE = 512\nNUM_CLASSES = 5\nSEED = 77\nTRAIN_NUM = 1000 # use 1000 when you just want to explore new idea, use -1 for full train","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 1.1 ทำความเข้าใจปัญหาและข้อมูลที่มี\n\nทาง Kaggle ได้จัดเตรียมข้อมูลไว้ในใน directory `../input` ครับ"},{"metadata":{"trusted":true},"cell_type":"code","source":"!ls ../input","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"files หรือ director ที่เราสนใจคือ\n* `train_images` เป็น directory ที่เก็บภาพดวงตาผู้ป่วย (และผู้ไม่ป่วย) ไว้ราวๆ 3600 รูป ข้อมูลรูปทั้งหมดนี้คือ training set ที่เรามีครับ\n* `train.csv` เป็นไฟล์ excel ที่บอกข้อมูลว่าดวงตาแต่ละดวงนั้นมีความรุนแรงของเบาหวานขึ้นตาในระดับไหนตั้งแต่ระดับ 0 (ปกติ) ไปจนถึงระดับ 4 (รุนแรงมาก)\n* `test_images` เก็บไฟล์รูปภาพจำนวนราว 2000 รูปไว้สำหรับให้ผู้เข้าแข่งขันได้ทดสอบความแม่นยำของโมเดลที่สอนจาก training set ข้างต้น\n\nเราจะมาลองดูรูปดวงตากันครับว่ามีหน้าตาเป็นอย่างไรกันบ้าง ก่อนอื่นเราต้องอ่านข้อมูลชื่อไฟล์แต่ละดวงตาและระดับความรุนแรงมาจาก `train.csv` ก่อนครับ ซึ่งเราจะอ่านด้วยโมดูล `panda` ที่เรา import มาในชื่อ `pd` ครับ"},{"metadata":{"trusted":true},"cell_type":"code","source":"df_train = pd.read_csv('../input/train.csv')\ndf_test = pd.read_csv('../input/test.csv')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"ลองดู distribution ของระดับความรุนแรงบน training data กันครับ จะเห็นว่าข้อมูลส่วนใหญ่จะเป็นผู้ที่มีดวงตาปกติ (level 0) และ ดวงตาที่รุนแรงปานกลาง (level 2)"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_y = df_train['diagnosis']\ntrain_y.hist()\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"จากนั้นเราลองสุ่ม plot ดวงตาได้ตามโค้ดข้างล่างนี้ครับ โดยในโค้ดข้างล่างนี้เราวนลูป print ตัวอย่างดวงตาในแต่ระดับความรุนแรงตั้งแต่แถวแรก (level 0, ปกติ) ไปจนถึงแถวที่ 5 (ระดับ 4 รุนแรงมาก) โดยใช้ `cv2` library ในการอ่านและย่อรูป และใช้ `pyplot` ในการพล็อตรูปขึ้นมา"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"%%time\nfig = plt.figure(figsize=(25, 16))\n# display 10 images from each class\nfor class_id in sorted(train_y.unique()):\n    for i, (idx, row) in enumerate(df_train.loc[train_y == class_id].sample(5, random_state=SEED).iterrows()):\n        ax = fig.add_subplot(5, 5, class_id * 5 + i + 1, xticks=[], yticks=[])\n        path=f\"../input/train_images/{row['id_code']}.png\"\n        image = cv2.imread(path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        image = cv2.resize(image, (IMG_SIZE, IMG_SIZE))\n\n        plt.imshow(image)\n        ax.set_title('Label: %d-%d-%s' % (class_id, idx, row['id_code']) )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"จากรูปดังกล่าว เราก็พอจะสังเกตเห็นคร่าวๆ ว่าดวงตาที่มีอาการผิดปกติจะเริ่มมีจุดขาวๆ ขุ่นๆ หรือมีเลือดออกในดวงตา และดวงตาที่มีอาการรุนแรงมากก็จะมีแผล (เลือด) ขนาดใหญ่เลยทีเดียว เช่นรูปที่ 3 และ 4 ในแถวที่ 5\n\nทั้้งนี้การที่เราสังเกตข้อมูลคร่าวๆ ก่อนที่จะเริ่มทำโมเดล ก็จะทำให้เราเข้าใจข้อมูล training data มากขึ้นรวมทั้งออกแบบ Pre-processing, data augmentation รวมทั้ง model architecture ได้เหมาะสมมากยิ่งขึ้นด้วยครับ\n\nจาก 25 รูปข้างบนนั้น พบว่ามีสองเรื่องที่ีเราควรจะ pre-process รูปทั้งหมดก่อนคร่าวๆ ครับ\n\n- **ลดผลกระทบของ lighting-condition** : เนื่องจากรูปแต่ละรูปนั้นถูกถ่ายบนสภาพแสงที่มีความแตกต่างกัน เราจะเห็นว่าบางรูปก็มืดมากทำให้เรามองเห็นรายละเอียดบาดแผลได้ไม่ชัดเจน รวมทั้งความจัดจ้านของสีสันในบางรูปก็ทำให้เรามองเห็นบาดแผลยากด้วยครับ วิธีการ Pre-process ที่ง่ายที่สุดเราอาจลองเปลี่ยนจากภาพสีเป็นภาพขาวดำ (Gray Scale) ดูได้ วิธีที่มีประสิทธิภาพกว่าที่เราจะมาดูกันก็คือวิธี pre-process ของ [Ben Graham (นักวิจัยจาก Facebook AI Research)](https://github.com/btgraham/SparseConvNet/tree/kaggle_Diabetic_Retinopathy_competition) ซึ่งจะเปลี่ยนดวงตาที่ขุ่นมัวให้อยู่ในรูปของดวงจันทร์ (สีเลือด) อันสวยงามได้อย่างน่ามหัศจรรย์ครับ\n- **ตัดพื้นที่ไม่จำเป็น (uninformative area) ออก** : สังเกตว่าหลายๆ รูปนั้นจะมีกรอบสีดำขนาดใหญ่อยู่ (เช่นภาพที่ 2 และ 4 ในแถวแรก) และทำให้ดวงตามีขนาดเล็กลงเมื่อเทียบกับขนาดภาพ วิธีการ pre-process ที่เป็น common-sense คือตัดกรอบที่ไม่จำเป็นเหล่านี้ทิ้ง ซึ่งจะทำให้เราเห็นข้อมูลต่างๆ ในดวงตาได้ชัดเจนยิ่งขึ้นครับผม"},{"metadata":{},"cell_type":"markdown","source":"## 1.2 Simple Gray-Scale"},{"metadata":{},"cell_type":"markdown","source":"ในเบื้องต้นเราลองทำ gray-scale ดูกันครับ เราจะเห็นว่าบางรูปเราเริ่มเห็นรายละเอียดมากขึ้นเช่นรูปที่ 5 ในแถวที่ 5 ซึ่งเป็นความรุนแรงระดับ 4 เราเห็นบาดแผลบริเวณด้านบนของดวงตามากขึ้นแล้วครับ"},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nfig = plt.figure(figsize=(25, 16))\n# display 10 images from each class\nfor class_id in sorted(train_y.unique()):\n    for i, (idx, row) in enumerate(df_train.loc[train_y == class_id].sample(5, random_state=SEED).iterrows()):\n        ax = fig.add_subplot(5, 5, class_id * 5 + i + 1, xticks=[], yticks=[])\n        path=f\"../input/train_images/{row['id_code']}.png\"\n        image = cv2.imread(path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n        image = cv2.resize(image, (IMG_SIZE, IMG_SIZE))\n\n        plt.imshow(image,cmap='gray')\n        ax.set_title('Label: %d-%d-%s' % (class_id, idx, row['id_code']) )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"สังเกตรูปที่ 2 ในแถวที่ 5 นั้นมีความรุนแรงระดับ 4 แต่เราแทบจะไม่เห็นบาดแผลใดๆ เลย ซึ่งอาจเป็นเพราะรูปถูกย่อให้เล็กลง ถ้าเราดูภาพขนาดใหญ่ขึ้นก็จะเห็นบาดแผลชัดขึ้นครับ ดังนั้นจากการสำรวจข้อมูลเบื้องต้นนี้ เราได้ไอเดียในการออกแบบโมเดลว่าขนาดของรูปนี้ (ใหญ่หรือเล็ก) จะมีผลต่อความแม่นยำของโมเดลแน่นอน"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"dpi = 80 #inch\n\n# path=f\"../input/aptos2019-blindness-detection/train_images/5c7ab966a3ee.png\" # notice upper part\npath=f\"../input/train_images/cd54d022e37d.png\" # lower-right, this still looks not so severe, can be class3\nimage = cv2.imread(path)\nimage = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\nheight, width = image.shape\nprint(height, width)\n\nSCALE=2\nfigsize = (width / float(dpi))/SCALE, (height / float(dpi))/SCALE\n\nfig = plt.figure(figsize=figsize)\nplt.imshow(image, cmap='gray')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 2. ทดลองวิธี preprocessing ของ Ben Graham.\n\nในปี 2015 Ben Graham นักวิจัยปัญญาประดิษฐ์ของ Facebook ได้คิดค้นวิธีที่จะทำให้ภาพของดวงตานั้นใสกระจ่าง และตัดแสงและสีรบกวนต่างๆ ออกไป ทำให้เรามองเห็นรายละเอียดในดวงตาได้ง่ายขึ้น  วิธีของ Ben นั้นเราเพียงแค่เติมโค้ดลงไปสองบรรทัดจากโค้ดก่อนหน้า โดยไอเดียหลักคือการสร้าง mask ของโทนสีของดวงตาขึ้นมา (ตัวแปร `image2`) ซึ่งไม่มีรายละเอียดภายในดวงตา และเรานำ mask นี้ไปลบออกจากรูปต้นฉบับ ก็จะทำให้ภาพที่เหลือเป็นดวงตาที่ตัด mask สีสันรบกวนต่างๆ ออกไปนั่นเองครับ\n\nสำหรับผู้สนใจรายละเอียดสามารถดูจาก[รายงานวิจัยฉบับเต็มของเบนครับ](https://github.com/btgraham/SparseConvNet/tree/kaggle_Diabetic_Retinopathy_competition)\n\nตัวอย่าง mask ดวงตา\n"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"%%time\nfig = plt.figure(figsize=(25, 16))\nfor class_id in sorted(train_y.unique()):\n    for i, (idx, row) in enumerate(df_train.loc[df_train['diagnosis'] == class_id].sample(5, random_state=SEED).iterrows()):\n        ax = fig.add_subplot(5, 5, class_id * 5 + i + 1, xticks=[], yticks=[])\n        path=f\"../input/train_images/{row['id_code']}.png\"\n        image = cv2.imread(path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        image = cv2.resize(image, (IMG_SIZE, IMG_SIZE))\n        image2 = cv2.GaussianBlur( image , (0,0) , 27)\n#         image=cv2.addWeighted ( image,4, image2 ,-4 ,128) # the trick is to add this line\n\n        plt.imshow(image2, cmap='gray')\n        ax.set_title('Label: %d-%d-%s' % (class_id, idx, row['id_code']) )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"นำ mask ไปลบออกจากภาพต้นฉบับ จะได้ภาพรายละเอียดดวงตาที่สวยงามดุจเวทย์มนต์ขึ้นมา"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"%%time\nfig = plt.figure(figsize=(25, 16))\nfor class_id in sorted(train_y.unique()):\n    for i, (idx, row) in enumerate(df_train.loc[df_train['diagnosis'] == class_id].sample(5, random_state=SEED).iterrows()):\n        ax = fig.add_subplot(5, 5, class_id * 5 + i + 1, xticks=[], yticks=[])\n        path=f\"../input/train_images/{row['id_code']}.png\"\n        image = cv2.imread(path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        image = cv2.resize(image, (IMG_SIZE, IMG_SIZE))\n        image2 = cv2.GaussianBlur( image , (0,0) , 27)\n        image=cv2.addWeighted ( image,4, image2 ,-4 ,128) # the trick is to add this line\n\n        plt.imshow(image, cmap='gray')\n        ax.set_title('Label: %d-%d-%s' % (class_id, idx, row['id_code']) )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 3. ทำ auto-cropping\n\nในหัวข้อนี้เราก็จะเพิ่มประสิทธิภาพการ preprocess ของเราขึ้นไปอีกด้วย auto-cropping ขอบที่ไม่จำเป็นออกไปครับ โดยโค้ดของ auto-cropping นั้นสามารถเขียนคร่าวๆ ได้ดังนี้ \n\nหลักการคร่าวๆ ของ auto-cropping คือ detect หาแถวและคอลัมภ์ที่ทั้งแถวและคอลัมภ์นั้นมืดสนิท (ความมืดกำหนดโดยตัวแปร `tol` ซึ่งค่า 0 คือดำสนิทและ 255 คือขาวบริสุทธิ์) และตัดแถวและคอลัมภ์เหล่านั้นออกไปครับ"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"def crop_image_from_gray(img,tol=7):\n    if img.ndim ==2:\n        mask = img>tol\n        return img[np.ix_(mask.any(1),mask.any(0))]\n    elif img.ndim==3:\n        gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)\n        mask = gray_img>tol\n        \n        check_shape = img[:,:,0][np.ix_(mask.any(1),mask.any(0))].shape[0]\n        if (check_shape == 0): # image is too dark so that we crop out everything,\n            return img # return original image\n        else:\n            img1=img[:,:,0][np.ix_(mask.any(1),mask.any(0))]\n            img2=img[:,:,1][np.ix_(mask.any(1),mask.any(0))]\n            img3=img[:,:,2][np.ix_(mask.any(1),mask.any(0))]\n    #         print(img1.shape,img2.shape,img3.shape)\n            img = np.stack([img1,img2,img3],axis=-1)\n    #         print(img.shape)\n        return img\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"def load_ben_color(path, sigmaX=10 ):\n    image = cv2.imread(path)\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n    image = crop_image_from_gray(image)\n    image = cv2.resize(image, (IMG_SIZE, IMG_SIZE))\n    image=cv2.addWeighted ( image,4, cv2.GaussianBlur( image , (0,0) , sigmaX) ,-4 ,128)\n        \n    return image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"%%time\n\nNUM_SAMP=7\nfig = plt.figure(figsize=(25, 16))\nfor class_id in sorted(train_y.unique()):\n    for i, (idx, row) in enumerate(df_train.loc[df_train['diagnosis'] == class_id].sample(NUM_SAMP, random_state=SEED).iterrows()):\n        ax = fig.add_subplot(5, NUM_SAMP, class_id * NUM_SAMP + i + 1, xticks=[], yticks=[])\n        path=f\"../input/train_images/{row['id_code']}.png\"\n        image = load_ben_color(path,sigmaX=28)\n\n        plt.imshow(image)\n        ax.set_title('%d-%d-%s' % (class_id, idx, row['id_code']) )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"\nเราได้ดวงตากลมที่งดงามมากๆ มาแล้วครับ และเราลองมาดูรูปที่สองของแถวที่ 5 กันอีกครั้งครับ จะเห็นว่าคราวนี้เราเห็นรายละเอียดรอยแผลที่ชัดเจนขึ้นมากๆๆ"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"dpi = 80 #inch\n\n# path=f\"../input/aptos2019-blindness-detection/train_images/5c7ab966a3ee.png\" # notice upper part\npath=f\"../input/train_images/cd54d022e37d.png\" # lower-right, can be class3\nimage = load_ben_color(path,sigmaX=10)\n\nheight, width = IMG_SIZE, IMG_SIZE\nprint(height, width)\n\nSCALE=1\nfigsize = (width / float(dpi))/SCALE, (height / float(dpi))/SCALE\n\nfig = plt.figure(figsize=figsize)\nplt.imshow(image, cmap='gray')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# 4. ลองดู Preprocessing บน Test Set\n\nเพื่อความแน่นอนว่าเทคนิก preprocessing ที่เราจะใช้กันในที่นี้นั้นจะสามารถใช้งานได้บนชุดข้อมูลทดสอบ test set ด้วย เราจึงต้องทดลองของจริงกันครับ  จากการทดลองข้างล่างเราพบได้ว่าตัวอย่าง test set ที่เราเลือกขึ้นมาสุ่มๆ ทั้ง 50 ดวงตานั้นมีดวงตาที่ดูเป็นแผลมากมาย นั่นคือ ใน distribution ของ test set นั้นอาจจะมีดวงตาที่ผิดปกติอยู่เป็นสัดส่วนที่มากกว่าใน training set ครับ (mis-matched distribution) นอกจากนี้ส่วนใหญ่ข้อมูลใน test set จะถูก crop ค่อนข้างลึกกว่า training set ทำให้รายละเอียดตรงขอบตาจะหายไปเยอะกว่า\n"},{"metadata":{"trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"%%time\nNUM_SAMP=10\nfig = plt.figure(figsize=(25, 16))\nfor jj in range(5):\n    for i, (idx, row) in enumerate(df_test.sample(NUM_SAMP,random_state=SEED+jj).iterrows()):\n        ax = fig.add_subplot(5, NUM_SAMP, jj * NUM_SAMP + i + 1, xticks=[], yticks=[])\n        path=f\"../input/test_images/{row['id_code']}.png\"\n        image = load_ben_color(path,sigmaX=27)\n        \n        plt.imshow(image)\n        ax.set_title('%d-%s' % (idx, row['id_code']) )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"สำหรับ Pre-processing Workshop นี้ก็จะจบลงเพียงเท่านี้ เป็นอย่างไรบ้างครับ ถ้าเพื่อนๆ มีข้อแนะนำหรือสงสัยเพิ่มเติมสามารถสอบถามได้ในกระทู้ข้างล่างหรือถามได้ใน thaikeres.com/community เลยครับ   สำหรับ Workshop ภาคถัดไปของ project AI-for-Eyes นี้ก็จะเป็นการสร้างโมเดล รวมทั้งการวิเคราะห์ความถูกต้องของโมเดลด้วยเทคนิกการดู Gradient และ Activation Mapping เพื่อวิเคราะห์ว่าระบบ AI ของเราสามารถเข้าใจ concept ของคำว่า \"บาดแผล\" ได้จริงหรือไม่ แล้วเจอกันกับ Workshop ภาคถัดไปเร็วๆ นี้ครับผม\n\n![heatmap](https://i.ibb.co/6FM6VCC/gradcam-resized.png)"},{"metadata":{},"cell_type":"markdown","source":"# ภาคผนวก ก. เมื่อจักษุแพทย์ก็ยังเห็นไม่ตรงกัน\n\nปัญหาการประเมินความรุนแรงของ diabetic retinophaty นี้จริงๆ แล้วเป็นปัญหาที่เรียกได้ว่าเป็น Noisy problem ครับ กล่าวคือจักษุแพทย์แต่ละท่านอาจจะให้ความเห็นไม่ตรงกันได้ว่าดวงตานี้มีความรุนแรงอยู่ในระดับใด ซึ่งสามารถดูได้จากสไลด์ด้านล่างซึ่งเป็น presentation ของทีมงาน tensorflow ครับ\n(ดูฉบับเต็มได้ที่ https://youtu.be/oOeZ7IgEN4o?t=156 )\n\n![inconsistent  estimation in diabetic retinophaty](https://i.ibb.co/6rQ2sFG/inconsistent-estimation.png)\n\nโดยในแต่ละแถวแทนดวงตาหนึ่งดวง และแต่ละคอลัมภ์จะแสดงการประเมินของจักษุแพทย์หนึ่งคนต่อดวงตานั้นๆ ครับ โดยสีน้ำเงินแปลว่าปกติ ส่วนสีแดงแปลว่ารุนแรงในระดับ 4 ครับ"},{"metadata":{},"cell_type":"markdown","source":"# ภาคผนวก ข. Infinite Vision: The Story of Aravind Eye Hospital\n\nอยากให้เพื่อนๆ ได้ลองดู** [clip นี้](https://youtu.be/Jr70IrWM-n8) ** ของโรงพยาบาลดวงตา Aravind ว่ามีความเป็นมาที่มหัศจรรย์อย่างไร เขาทำได้อย่างไรที่บริการคนนับล้านโดยไม่คิดค่าใช้จ่าย ด้วยประสิทธิภาพที่สูงที่สุดในโลก และไม่ได้เงินสนับสนุนจากรัฐบาลแม่แต่แดงเดียว\n\n![Aravind Business Model??](https://i.ibb.co/m4C3xWd/Aravind-Model.png)\n\n"},{"metadata":{},"cell_type":"markdown","source":"แล้วเจอกันครับผม จากทีมงาน [ThAIKeras](http://www.thaikeras.com)"},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}