åæ©
TensorFlowã®ç»å ´ããã£ããã« æ©æ¢°å¦ç¿ã«ããã¢ã¤ãã«é¡èå¥ ã¨ããåãçµã¿ããã¦ãã¦ã3年以ä¸ããã¦ã³ãã³ãã¨ã¢ã¤ãã«ã®èªæ®ããåéãã¦ã©ãã«ãã¤ãã¦ãã¼ã¿ã»ãããä½ã£ã¦ãããã©ã ã¢ã¤ãã«ã²ã¿ã¯ã¯ããè¾ãã¦ãã¾ã£ã¦ ç¾å ´ã«ãå ¨ç¶è¡ããªããªããåæ¥ã»è±éã®æ å ±ã追ããªããã©ãã«ãæ´æ°ãã¦ããä½æ¥ãç¶ããæ ç±ã¯ãã£ããèãã¦ãã¾ã£ãã ããã¢ã¤ãã«é¡èå¥ããã¸ã§ã¯ãã¯çµäºã«ããããã¨æã£ãã
ãããæè§ä»ã¾ã§éãããã¼ã¿ãæ¨ã¦ã¦ãã¾ãã®ã¯å¿ä½ç¡ããããã¦æå¾ã«ä½ãæ´»ç¨ã§ããªããã®ãã ã¨èãã¦ããç»åçæãã«åã³åãçµãã§ã¿ããã¨ã«ããã
éå»ã«è©¦ãããã¨ã¯ãã£ããã©ãããã»ã©ä¸æãã¯ãã£ã¦ããªãã
- TensorFlowã«ããDCGANã§ã¢ã¤ãã«ã®é¡ç»åçæ
- TensorFlowã«ããDCGANã§ã¢ã¤ãã«ã®é¡ç»åçæ ãã®å¾ã®å®é¨ãªã©
ãã®è¨äºãæ¸ããã®ã2016å¹´ã
ãã®å¾ã®æ°å¹´ã ãã§ãGANã®æè¡ã¯ããã¾ããé²æ©ãã¦ãã¦ãä»ã 1024x1024
ã®ãããªé«è§£å度㮠åçã¨è¦åããã¤ããªããããã®ç¶ºéºãªé¡ç»åãçæã§ããããã«ãªã£ãããããæ¯éã¨ã試ãã¦ã¿ããã¨ããã ã
ç®æ¨
PGGAN (Progressive Growing of GANs) ã StyleGAN ã§ä½¿ããã CelebA-HQ
datasetã¯ã1024x1024
ãµã¤ãºã®é«è§£å度ã®ç»åã 30,000
æç¨æãã¦ä½ããã¦ããããã ã
ä»åã¯ããã¾ã§ãããªãã¨ãããã㦠512x512
ã®ç»åã 10,000
æãããã¯éãããã
è¨è¨ã®å¤±æ
ãããèªåãã¢ã¤ãã«é¡èå¥ã®ããã«åéãã¦ã©ãã«ä»ããããã¼ã¿ã»ããã¯ãæ稿ãããèªæ®ãç»åããé¡é åãæ¤åºã 96x96
ã«ãªãµã¤ãºãã¦åãæãããã®ã ãããä¿åãã¦ããªãã£ãã
ãã¾ãã¹ãã¬ã¼ã¸ã«ä½è£ãç¡ãã±ãã£ãéç¨ããã¦ãããããå
ã®é«è§£å度ã®ç»åãã¯ã©ã¦ãä¸ã«æ®ãã¦ãããªã©ãã¾ã£ãããã¦ããªãã£ãã
ã¤ã¾ã 96x96
ãããé«è§£å度ã®é¡ç»åã¯æã«å
¥ããªãâ¦ã
éãç´ã
DBããåè£ã¨ãªãç»åURLãæ½åº
ã¨ã¯ãããæå ã«ã¯ãå ç»åã®URLããå ç»åã«ã²ãã¥ãããæ½åºãããé¡ç»åããé¡ç»åã«å¯¾ããã©ãã«ãã®ãã¼ã¿ã¯æ®ã£ã¦ããã
- åã¢ã¤ãã«ã®Twitterããåå¾ããç»åæ
å ±
1,654,503
件 - èªä½ã®æ¤åºå¨ã§æ¤åºãã¦æ½åºããé¡ç»å
2,158,681
件- ãã®ãã¡ã人åã®æä½æ¥ã§ã©ãã«ä»ããããã®
204,791
件
- ãã®ãã¡ã人åã®æä½æ¥ã§ã©ãã«ä»ããããã®
ãªã©ããèªåã3年以ä¸ããã¦ç¶ããã¢ããã¼ã·ã§ã³ä½æ¥ã®ææã ã
é«è§£å度ã®ã¢ã¤ãã«é¡ç»åãã¼ã¿ã»ãããæ§ç¯ããããã«ã¯ãresize & crop ããåã®å ç»åãåå¾ããªããã¦ãä»åº¦ã¯è§£å度ãä¿ã£ãã¾ã¾ã§é¡é åãæ½åºããªããã°è¯ãã
ç®å½ã¦ã®ãã¢ã¤ãã«ã®èªæ®ãé¡ç»åãã ããé¸å¥ããã«ã¯ã
- åçã®ä¸ã«1æã ãé¡ãæ¤åºããã¦ãã
- â éååçãªã©ã§ã¯ãªãåç¬ã®èªæ®ã㧠é«è§£å度ã§åã£ã¦ããå¯è½æ§ãé«ã
- ãã®é¡ç»åãæ£ããã¢ã¤ãã«ã¨ãã¦ã©ãã«ä»ãããã¦ãã
- â é¡æ¤åºããã¦ãã¦ã誤æ¤åºãä¸å®å²åã§èµ·ãã¦ããããèªè対象å¤ã®ã©ãã«ä»ãããã¦ãããããã®ã§ãããããé¤å¤ãã
ã¨ããæ¡ä»¶ã®ãã®ãæ½åºããã°ã§ããã¯ãã
SELECT faces.id, photos.id, photos.source_url, photos.photo_url, photos.posted_at, labels.id, labels.name FROM faces INNER JOIN photos ON photos.id = faces.photo_id INNER JOIN labels ON labels.id = faces.label_id WHERE photos.id in ( SELECT photos.id FROM faces INNER JOIN photos ON photos.id = faces.photo_id WHERE faces.label_id IS NOT NULL GROUP BY photos.id HAVING COUNT(faces.id) = 1 ) ORDER BY faces.updated_at DESC
ãããã¦ããããããã¢ã¤ãã«ãåç¬ã§åã£ã¦ããã§ãããå
ç»åã196,455
æã®URLãåå¾ã§ããã
ããã ç»åURLãåå¾ã§ãã¦ãã¦ãããããæ稿ããã¢ã¤ãã«ãããåæ¥ã»è§£æ£ãªã©ã®å¾ã«Twitterã¢ã«ã¦ã³ããåé¤ããããéå ¬éã«ãªã£ã¦ãããããã¨ããããã®ç»åã¯åç §ã§ããªããªã£ã¦ãã¾ãã
å®éã«åå¾ã試ã¿ã¦ãã¦ã³ãã¼ãã§ããã®ã¯ ãã®ãã¡ 132,513
件ã ã£ãã
ã¡ããã©ä¼ç ã¢ã«ã¦ã³ãåé¤ã¨ããã®ãæè¿ãã¥ã¼ã¹ã«ãªã£ããåæ¥å¾ã«æ®ã£ã¦ããã¢ã¤ãã«ã®ã¢ã«ã¦ã³ããã¡ã¯ã©ããªã£ã¦ãã¾ãã®ã ãããâ¦ãä»ã®ãã¡ã«ç»åã ãã§ãåå¾ãã¦ãããã¨ãåºæ¥ã¦è¯ãã£ãã®ãããããªãã
Dlibã«ããåä¸é¡æ¤åº
ãã¦ãé«è§£å度(ã¨ãã£ã¦ã 900x1200
ç¨åº¦ã ãã©)ã® ã¢ã¤ãã«ãããã¡ã®ç»åãå
¥æãããã¨ãåºæ¥ãã
以åã¯ãããã OpenCV ã® Haar Feature-based Cascade Classifiers ã使ã£ã¦é¡æ¤åºãããã®é åã resize & crop ãã¦ãã¼ã¿ã¨ãã¦ä½¿ã£ã¦ããã ã¾ããã¢ã¤ãã«ã®èªæ®ãã®ç¹å¾´ã¨ãã¦ãæãã«å¾ãã¦åã£ã¦ãããã®ããå¤ãæ¤åºãã¥ããåé¡ãããããããèæ ®ãã¦å転è£æ£ãããã¦æ¤åºããã¨ããä»çµã¿ãèªä½ãã¦ããã
ä»åãåæ§ã®æ¤åºããããã¨ã«ãªãããããé«ç²¾åº¦ã« ã¾ãç®ã»å£ã®ä½ç½®ãæ¤åºãããã¨ããã®ããããããã§ã¯ dlib ã使ã£ã¦ã¿ããã¨ã«ããã dlib 㯠OpenCVåæ§ã«é¡é åãæ¤åºã§ããã»ãããã®é¡é åå ã®landmarkã¨ãã¦é¡ã®è¼ªéãç®ã»é¼»ã»å£ãªã©ã®ä½ç½®ã¾ã§ç°¡åã«æ¤åºãããã¨ãã§ããã
ãã¯ãæãã«å¾ããé¡ãªã©ã«ã¯ãã¾ãå¼·ããªããããªã®ã§ã以åã®ãã®ã¨åæ§ã«å転è£æ£ãããã¦æ¤åºã試ã¿ãã¨ãã£ããã¨ã¯å¿ è¦ããã ã£ãã ãã ä»åã¯ããããã対象ã®ç»åã«ã¯é¡ãä¸ã¤ã ãåã£ã¦ãããã¨ããä»®å®ã§ ãã®åä¸ã®é¡ã®é¨åã ãæ¤åºã§ããã°è¯ãã®ã§ å°ãå¦çã¯ç°¡åã«ãªãã
ä¾ãã°ãå®å®ä¸è¼ãã´ããã´ããã¢ã¤ãã« å®ä½ç¾å¹¸ä¹ã¡ãã ã®å ´åã
ã¾ãã¯ç»åãå転ãããã¨ã«ãã£ã¦ã¯ã¿åºãã¦æ¶ãã¦ãã¾ãé¨åããªãããã« å ç»å対è§ç·ã®é·ããæã¤æ£æ¹å½¢é åãä½ã£ã¦ããã®ä¸å¤®ã«å ç»åãé ç½®ããã
def detect(self, img): # Create a large image that does not protrude by rotation h, w, c = img.shape hypot = math.ceil(math.hypot(h, w)) hoffset = round((hypot-h)/2) woffset = round((hypot-w)/2) padded = np.zeros((hypot, hypot, c), np.uint8) padded[hoffset:hoffset+h, woffset:woffset+w, :] = img
ãã®ç»åãããããå°ããã¤å転ããããã®ãçæããããããã«å¯¾ãã¦é¡æ¤åºã試ã¿ãã
ãã®ã¨ãã fhog_object_detector.run(image, upsample_num_times, adjust_threshold)
ã®APIã§æ¤åºãããããã¨ã§ããã®æ¤åºçµæã® confidence score ãåå¾ã§ããã®ã§ ããããå«ãã¦å
¨ãã¿ã¼ã³ã®çµæãéããã
æå
ã§è©¦ããéãã§ã¯ -48
° ã +48
° 㧠12
°ãã¤ã®å転å¹
ã§è©¦ãã®ããå¤ãã®å転è§ãå°ãªãæ¤åºè©¦è¡ã§ç¶²ç¾
ã§ãã¦è¯ãããã ã£ãã
self.detector = dlib.get_frontal_face_detector() self.predictor = dlib.shape_predictor(datafile) ... # Attempt detection by rotating at multiple angles results = [] for angle in [-48, -36, -24, -12, 0, 12, 24, 36, 48]: rotated = self._rotate(padded, angle) dets, scores, indices = self.detector.run(rotated, 0, 0.0) if len(dets) == 1: results.append([dets[0], scores[0], angle, rotated]) if len(results) == 0: self.logger.info('there are no detected faces') return def _rotate(self, img, angle): h, w, _ = img.shape mat = cv2.getRotationMatrix2D((w/2, h/2), angle, 1.0) return cv2.warpAffine(img, mat, (w, h), cv2.INTER_LANCZOS4)
9ã¤ã®ãã¿ã¼ã³ã®ä¸ã§ãã£ã¨ãé«ãscoreã§é¡ãæ¤åºããããã®ããããããæãæ£è§£ã«è¿ãå¾ãè§åº¦ã§ãããã¨ã㦠ãããæ¡ç¨ããã
ãã®å ´åã¯ã¾ã£ããå転ããªã 0
° ã§ãé¡ã¯æ¤åºããã¦ãã(score: 0.3265
)ããå°ãå¾ãã -12
°ã®ãã®ã®æ¹ã 0.5834
ã¨é«ãscoreã«ãªã£ã¦ããã®ã§ããã¡ããä»®ã®å転è§ã¨ãã¦æ¡ç¨ããã
ãã®å転å¾ã®ç»åã«å¯¾ã㦠landmark ãæ¤åºããå·¦å³ã®ç®ã®ä¸å¤®ä½ç½®ãç®åºããã
æ£ããå転ãã¦çã£ç´ãã«ãªã£ã¦ãããç®ã®é«ãã¯åãã«ãªãã¯ããããããºã¬ã¦ããã®ãªã ãã®ã¶ãã ãã¾ã å°ãå¾ãããããã¨ããèãã§ããã®å·¦å³ã®ç®ã®ä½ç½®åº§æ¨ãã atan2
ã使ã£ã¦ãã®å¾®å¦ãªè§åº¦ãè¨ç®ããã
... # Choose the best angle by scores, and then adjust the angle using the eyes coordinates results.sort(key=lambda x: x[1], reverse=True) det, _, angle, rotated = results[0] shape = self.predictor(rotated, det) eyel, eyer = self._eye_center(shape) d = eyer - eyel angle += math.degrees(math.atan2(d[1], d[0])) self.logger.info(f'angle: {angle:.5f}') def _eye_center(self, shape): eyel, eyer = np.array([0, 0]), np.array([0, 0]) for i in range(36, 42): eyel[0] += shape.part(i).x eyel[1] += shape.part(i).y for i in range(42, 48): eyer[0] += shape.part(i).x eyer[1] += shape.part(i).y return eyel / 6, eyer / 6
å
ã
ã®å転è§åº¦ã¨ è¨ç®ããè§åº¦ã足ãã¦ãæçµçãªå転è§ã¨ããã
ãã®ç»åã®å ´å㯠-12 + 0.156403
= -11.843597
° ã®å転ã§ã»ã¼çã£ç´ãã®ç¶æ
ã«ãªããã¨è¨ç®ãããã
ãã®å転è§ã§ã®ç»åãããä¸åº¦çæããæ£ããé¡ã¨landmarkãæ¤åºããããã¨ã確èªããã
... # Detect face and shapes from adjusted angle adjusted = self._rotate(padded, angle) dets = self.detector(adjusted) if len(dets) != 1: self.logger.info('faces are not detected in the rotated image') return shape = self.predictor(adjusted, dets[0])
次ã«ãè¦åãã¦ããé¨åã®è£å®ãè¡ãã ãã¼ã¿ã»ããã«ã¯é¡ã®å¨è¾ºé¨åã¾ã§å«ãã¦åãåã£ã¦ä½¿ããã¨ã«ãªãã®ã§ããã®å¨è¾ºé¨åã§ç»åãåãã¦ãããããã¨é常ã«ä¸èªç¶ãªé åãåå¨ãã¦ãã¾ããã¨ã«ãªãã
PGGANã®ææ³ã§ã¯ å ã®ç»åããé¡é¢åå°ããç»åãç¹ãã¦åºãã¦(mirror padding)ãããããåãåããã¨ã§ä¸èªç¶ããåããã¦ããããã ã åæ§ã«ãã£ã¦ã¿ãã
... # Create a large mirrored image to rotate and crop margin = math.ceil(hypot * (math.sqrt(2) - 1.0) / 2) mirrored = np.pad( img, ((hoffset + margin, hypot - h - hoffset + margin), (woffset + margin, hypot - w - woffset + margin), (0, 0)), mode='symmetric') rotated = self._rotate(mirrored, angle)[margin:margin+hypot, margin:margin+hypot, :]
ãããã«èæ¯ã®å£ãªã©ã¯ãã®ã¾ã¾ç¶ãã¦ãããã®ããã«è¦ãã¦ä¸èªç¶ãªé åã¯æ¸ãããã ã
ããããã両ç®ã®ä½ç½®ã¨å£ã®ç«¯ã®ä½ç½®ã»ãã®åç¹éã®è·é¢ã使ã£ã¦ åãåãã¹ãé¡é åã®ä¸å¿åº§æ¨ã¨å¤§ãããç®åºãã¦ããã è«æå ã®ææ³ã§ã¯
x
: 両ç®ã®å¹= e1 - e0
y
: 両ç®ã®ä¸å¿ ãã å£ã®ä¸å¿ ã®è·é¢= (e0 + e1) / 2 - (m0 + m1) / 2
c
: åãåãä¸å¿åº§æ¨= (e0 + e1) / 2 - 0.1 * y
s
: åãåããµã¤ãº= max(4.0 * x, 3.6 * y)
ã¨ãã£ãè¨ç®ã§ãã£ã¦ããããã ããã®ã¾ã¾ä½¿ã£ã¦é©ç¨ãã¦ã¿ãã
# Calculate the center position and cropping size # https://arxiv.org/pdf/1710.10196v3.pdf e0, e1 = self._eye_center(shape) m0 = np.array([shape.part(48).x, shape.part(48).y]) m1 = np.array([shape.part(54).x, shape.part(54).y]) x = e1 - e0 y = (e0 + e1) / 2 - (m0 + m1) / 2 c = (e0 + e1) / 2 + y * 0.1 s = max(np.linalg.norm(x) * 4.0, np.linalg.norm(y) * 3.6) xoffset = int(np.rint(c[0] - s/2)) yoffset = int(np.rint(c[1] - s/2)) if xoffset < 0 or yoffset < 0 or xoffset + s >= hypot or yoffset + s >= hypot: self.logger.info('cropping area has exceeded the image area') return size = int(np.rint(s)) cropped = rotated[yoffset:yoffset+size, xoffset:xoffset+size, :]
ããæãã«ããã£ã½ããæ£è¦åãããé¡ç»åã¨ãã¦åãæããã¨ãåºæ¥ããã ã
ããã㦠æ¤åºå¨ãåºæ¥ãã®ã§ã132,513
件ã®URLããå®éã«ãã®æ¹æ³ã«ããæ¤åºã試ã¿ãã
ããããéãå¦çã§ã¯ãããã®ã®ãæå
ã®MacBookã§ãæ°æ¥ããã¦ãã£ããå®è¡ãç¶ããçµæ 72,334
件ã»ã©ã®é¡ç»åãåéãããã¨ãã§ããã
è¦åãé åã®å¤ãç»åã«èµ·ããåé¡ç¹
ãããã¦è¦ãã¨è¯ãç»åãã¼ã¿ãæã£ã¦ããããã«è¦ããããå®éã«ã¯å ¨ç¶ãããªã«ä¸æãã¯ãããªãã
å¤ãã®èªæ®ãç»å㯠ããªãå¯ãæ°å³ã«æ®ããã¦ãã¦ãé¡ãé ã®è¼ªéã¾ã§å ¨é¨ã¯åã£ã¦ããªãå ´åãå¤ãã ããããã¨ã©ããªãããé¡é¢åå°ã§è£å®ãã¦ãè¦åããé¡ãé ãåå°ããã¦æ ãã ã㧠çµå±ä¸èªç¶ãªç»åã«ãªã£ã¦ãã¾ãã
ä¾ãã°åè¿°ã®ä¾ã§ãããããã£ã¨å¯ãæ°å³ã«æ®ããã¦ãã¦é ãªã©ãè¦åãã¦ãããâ¦
ã¨ããæãã«ãªã£ã¦ãé¡ãlandmarkã¯ç¢ºãã«æ¤åºããããããããªããã©ãé ãä»ã®é¨åãå¤ãªå½¢ã«ç¹ãã£ã¦ãã¾ã£ã¦ããããªãã®ã«ãªã£ã¦ãã¾ãã
ã¡ãã£ã¨ããããªãåé¡ãªããããããªããã©ãæµç³ã«ç®ãè¤æ°è¦ãã¦ããããã®ã¯ã¤ãããâ¦
æ½åºããé¡ç»åã使ã£ãçæãã¹ã
ã¨ããããã¯å¤ãªå½¢ã«ãªã£ã¦ãã¾ã£ããã¼ã¿ãåå¨ãã¦ãã¾ã£ã¦ãã¦ãä»æ¹ãªããã¨å²ãåã£ã¦ãæ¤åºãã¦å¾ããã¨ãåºæ¥ãé¡ç»åã 10,000
件ã»ã©ä½¿ã£ã¦çæã¢ãã«ã§ã®å¦ç¿ã試ã¿ã¦ã¿ãã
512 x 512
ã«ãªãµã¤ãºãããã®ããã¼ã¿ã»ããã¨ãã¦ä½¿ãã StyleGAN ã使ã£ã¦ä½epochãå¦ç¿ãã¦ã¿ãã
確ãã«ã¢ã¤ãã«ã®é¡ã£ã½ãç»åãçæããããããã¯ãå³ä¸ãå·¦ä¸ãªã©ã«é¡é¢åå°ããé¡ãç¹ãã£ã¦ãããããªå¥å¦ãªå½¢ã®ãã®ãçæãããããããã ãã
ã¾ããããããç»åãå«ãã ãã®ãå¦ç¿ãã¼ã¿ã¨ãã¦ä¸ãã¦ãã¾ã£ã¦ããã®ã§ãããªãã®ã¯å½ç¶ã®çµæã§ã¯ããã
ç»åé¸å¥ã¨ç®¡çã®ããã®Webã¢ããªã±ã¼ã·ã§ã³
ã¨ãªãã¨ä»åº¦ã¯ãã¼ã¿ã®ã¯ãªã¼ãã³ã°ãå¿ è¦ã«ãªã£ã¦ããã
ç®è¦ã§1æ1æ ç»åã確èªãããå¦ç¿ãã¼ã¿ã«ä½¿ãããé¡å ¨ä½ããããã«å ¥ã£ã¦ããç»åãã¨ãå¦ç¿ãã¼ã¿ã«ä½¿ããããªããä¸èªç¶ãªç»åããé¸å¥ãããã¨ã«ããã
ãã¼ã«ã«ç°å¢ã§ãã¼ã¿ã管çããããªããèªå好ã¿ã®UIã§ä½æ¥ã»ç¢ºèªãããããªã©ã®çç±ããããä¾ã«ãã£ã¦ç®¡çç¨ã®Webã¢ããªã±ã¼ã·ã§ã³ãèªä½ããã
Google App Engine ä¸ã§åä½ãããããç»åã Cloud Storage ã«ã¢ãããã¼ããããã«ã²ãã¥ãæ å ±ã Cloud Firestore ã«ä¿å (以å㯠Cloud Datastore ã ã£ãã㩠次ã®æ代ã¯Firestoreããããã¨ãããã¨ã§ä»ååãã¦è§¦ã£ã¦ã¿ã)ãFrontendã Create React App ã§ä½ã£ã¦ãSPAãã App Engine Go Standard Environment ã§ä½ã£ã API ãå©ãå½¢ã®ã¢ããªã±ã¼ã·ã§ã³ãèªåããé²è¦§ã»æä½ã§ããªããã Firebase Authentication ã§èªè¨¼ããããã«ãã¦ããã
åç»åã«å¯¾ã㦠Status
ã¨ãããã£ã¼ã«ããç¨æãã¦ããã Ready
, NG
, Pending
, OK
ã®4ã¤ã®å¤ãã»ããã§ããããã«ãããåæå¤ã¯ãã¹ã¦ Ready
ã Ready
ã®ãã®ãã²ãããè¦ã¦ãã£ã¦ããããã§ä½¿ããããªãã®ã OK
ããã¡ãããªãã®ã NG
ã«å¤æ´ãããå¤æã«è¿·ã£ããã®ã¯ Pending
ã«ã1
, 2
, 3
ã®ãã¿ã³æä½1ã¤ã§æ¬¡ã
ã¹ãã¼ãã£ã¼ã«æ´æ°ãã¦ãããããã«UIã工夫ããã
誤æä½ãæãå¾ãã®ã§ NG
ã ããã¨ãã£ã¦åé¤ãããã¯ããã NG
ã¨ãã¦æ®ãã¦ããããããå¾ã§å½¹ã«ç«ã£ãã
ãããã¦é¸å¥ä½æ¥ãã¦ãã£ã¦ãOK
ã«ãªã£ããã®ã ããæ½åºãã¦å¦ç¿ãã¼ã¿ã«ä½¿ãã°ããã£ã¨ããããªç»åãçæã§ããããã«ãªãã¯ãâ¦
é¸å¥ä½æ¥å¹çåã¸
ä½æ¥ã¯1æ1ç§ç¨åº¦ã§ãµã¯ãµã¯é²ãããå®éã«ãã£ã¦ã¿ã㨠NG
ã®ç»åãé常ã«å¤ããã¨ãåãã£ãã
ãã¯ãå¤ãã®ã¢ã¤ãã«ããã¯é¡ã¾ã§ã¯åãã¦ãã¦ãé å ¨ä½ã¾ã§åããããªèªæ®ãããã¦ãããã¨ã¯å°ãªããããã«ãã£ã¦mirror paddingããããã®ã¯ã ãããé ã®å½¢ãããããç»åã«ãªã£ã¦ãã¾ãã
8,500
æã»ã©é¸å¥ä½æ¥ãã¦ã¿ã¦ãããã OK
ã®ãã®ã 1,250
æã»ã©ã ç´7æã«1æããç¾ããã8å²ä»¥ä¸ã¯ NG
ããã㯠Pending
ã«ããæãã«ãªã£ããæã£ã以ä¸ã« NG
ã®å±±ã®ä¸ããå°æ°ã® OK
ãæ¢ãã®ã¯ã¹ãã¬ã¹ãã«ã ãå¹çãæªãã
NG
ã® é ã®å½¢ããããããªã£ã¦ããããªç»åãªãã¦èª°ã§ãåºå¥ã§ãããæ©æ¢°ã«ã§ãããããã°ããããâ¦
ã¨æã£ãã®ã§ãä¸æ¬¡é¸å¥ããããã®æ©æ¢°å¦ç¿ã¢ãã«ãèªä½ãããã¨ã«ããã
幸ãã NG
ã«ããç»åãåé¤ããã«æ確ã«ãNG
ã§ãããã¨ã©ãã«ä»ãããç¶æ
ã§æ®ãã¦ããã
ç»åãå
¥åãã¦ããOK
ã NG
ããã ããäºæ¸¬ããåé¡ã¢ãã«ãç¨æããã
ç»åã«åã£ã¦ãã人ç©ã誰ããã¯é¢ä¿ãªããçæç¨ã®ãã¼ã¿ã¨ã㦠OK
ãªãã®ã NG
ãªãã®ããã ããå¤å¥ãããã¢ãã«ã¨ãã¦å¦ç¿ããããã¨ã«ãªãã
ããã¾ã§å³å¯ã«ç²¾åº¦ãæ±ãããã®ã§ããªãããé©å½ã« TensorFlow Hub ããImageNetã§å¦ç¿æ¸ã¿ã® InceptionV3
ãå©ç¨ã㦠2 classes ã® classification ã®ããã®modelã¨ããã
import tensorflow as tf import tensorflow_hub as hub IMAGE_SIZE = (299, 299) def cnn() return hub.KerasLayer("https://tfhub.dev/google/imagenet/inception_v3/feature_vector/4", trainable=trainable, arguments=dict(batch_norm_momentum=0.997)) def train(): labels = ['ok', 'ng'] model = tf.keras.Sequential([ cnn(), tf.keras.layers.Dropout(rate=0.1), tf.keras.layers.Dense( len(labels), activation='softmax', kernel_regularizer=tf.keras.regularizers.l2(1e-4)), ]) model.build([None, *IMAGE_SIZE, 3]) model.summary() model.compile( optimizer=tf.keras.optimizers.RMSprop(), loss=tf.keras.losses.CategoricalCrossentropy(), metrics=[tf.keras.metrics.CategoricalAccuracy()])
ãã¼ã¿ã»ããã¨ãã¦ã¯ãæ¢ã«ã©ãã«ä»ãæ¸ã¿ã® NG
ã®ãã®ã 4,800
件ã OK
ã®ãã®ã 1,200
件 æ½åºãã¦ä½¿ç¨ããã
ããããã 4000:800
, 1000:200
㧠train
㨠validation & test
ã«åå²ã
æåã¯å ¨çµå層ãå¦ç¿ãããã ãã®è»¢ç§»å¦ç¿ã ãã§ã©ãã«ããªãããªãã¨æã£ã¦ã¡ãã£ã¨è©¦ãã¦ã¿ããã©ãã¡ããã ã£ãã®ã§ãçµå±ãããã¯ã¼ã¯å ¨ä½ãå¦ç¿ãããfine-tuningã§ã Google Colaboratory ã®GPU Runtimeã§æ°ååã»ã©å¦ç¿ã
NG
ãã¼ã¿ã®æ¹ãå¤ãã®ã§å¦ç¿åæ㯠NG
ã«å
¨æ¯ãã㦠accuracy 0.8
ã¨ãã«ãªããã©ãã ãã ãæ¹åãã¦ãã£ã¦ 40 epochã»ã©é²ãã㨠0.947
ã¾ã§ä¸ãã£ãã
æçµçãªçµæã¨ãã¦ã¯ãå¦ç¿ã«ä½¿ããªãã£ã validation & test
ã»ããã«å¯¾ããæ¨è«ã§ 以ä¸ã®ãããªConfusion Matrixã«ãªã£ãã
OK
label ã«å¯¾ãã¦ã¯ Precision 0.9016
, Recall 0.8250
ã¨ãã£ãã¨ããã§ãã¾ããããªãã«å¦ç¿ãã¦ããã¦ãããã¨ããæè¦ã§ã¯ããã
å®éã«ãæªä½¿ç¨ã® Ready
ã®ç»å 1,000
æã«å¯¾ãã¦ãã®åé¡ã¢ãã«ã«å¤å¥ããã¦ã¿ãã¨ããã197
æã OK
ã¨ãã¦åé¡ãããã
ããããç®è¦ã§ç¢ºèªãã¦ã¿ãã¨ããã ãã®ãã¡ 128
æã OK
ã«ãªã£ãã
æå¾
ããããã¯ä½ãã£ãããããã¾ã§ã¯ æ°æã«1æããç¾ããªã OK
ãæ¢ãç¶ããä½æ¥ã ã£ãã®ã ä»å¾ã¯ãã® ä¸æ¬¡é¸å¥ããããã®ããä½æ¥ããã° åæ°ä»¥ä¸ã¯ OK
ãé¸ã¹ãã®ã§ãä½æ¥ã®å¿ççã¹ãã¬ã¹ã¯æ ¼æ®µã«è»½æ¸ããã¦å¹ççã«ãªãã
ã¾ããä»å¾ããã«ãã¼ã¿ãå¢ããã ãã®åé¡ã¢ãã«ãå度å¦ç¿ããããã¨ã§ãããã«é«ç²¾åº¦ã«ä¸æ¬¡é¸å¥ãé²ãããã¨ãåºæ¥ãããã«ãªããã¨ãæå¾ ã§ããã
ç¾ç¶ã¨ä»å¾
ãããã¦ãç¾æç¹ã§ 1,900
æãããã¾ã§ã¯ OK
ãªç»åãéãããã¨ãã§ããã
ããå°ãå¢ããããããã使ã£ã¦çæãå度試ãã¦ã¿ããã¨ããã
ããå
¨ä½ã®ææ°ã¨å²åã§æ¦ç®ãã㨠ä»ãããã¹ã¦ã®åéç»åã«å¯¾ãã¦é¸å¥ãã¦ãã¾ã OK
ã 10,000
æã«å±ããªããããããªãâ¦ã
èªæ®ãã®ãã¬ã¤ãªãªã¹ã¹ã¡ã¢ã¤ãã«ããããåç¥ã®æ¹ãããã£ããã£ããæ¯éã¨ãæãã¦ããã ãããã¨ãããã