(Chainer Advent Calendar 2016 5æ¥ç®ã§ãï¼ãã®è¨äºã¯TokyoTechLTã§çºè¡¨ãããã®ã¨åå 容ã®ãã®ã§ãï¼)
ãã®è¨äºã¯ä½ï¼
以åChainer Advent Calendar 2015ã«ããã¦ï¼Chainerãç¨ããRankNet(ã©ã³ã¯å¦ç¿ææ³ã®1ã¤)ã®å®è£
ã紹介しましたï¼
æ¬è¨äºã§ã¯ï¼RankNetãå¿ç¨ããç»åã®é åºäºæ¸¬ãç´¹ä»ãã¾ãï¼
ãããããã¨ã®æ¦è¦
RankNetãå¿ç¨ããç»åé åºäºæ¸¬ã®æ¦è¦å³ã示ãã¾ãï¼
è¨ç·´ãã¼ã¿ã¨ãã¦ï¼æ¢ã«é åºä»ããããç»åéåãç¨ãã¾ãï¼
é åºä»ãã®ä¾ã¨ãã¦ï¼ã¦ã¼ã¶ã¼ã®å¥½ã¿ã«ããã¬ã¤ãã£ã³ã°ãèãããã¾ãï¼ã¯ãªãã¯çãªã©ã使ãæ¹æ³ãå¯è½ã ã¨æãã¾ãï¼
å¾ãããè¨ç·´ãã¼ã¿ãCNNã«å ¥åãå¦ç¿ãã¾ãï¼ç®çé¢æ°ã¯ï¼è¨ç·´ãã¼ã¿ä¸ã®ç»å対ã®é åºãæ£ããèå¥ã§ããããã«è¨å®ãã¾ã(RankNet)ï¼
å¾ãããäºæ¸¬å¨ã«ã¬ã¤ãã£ã³ã°æªç¥ã®ç»åéå(ãã¹ããã¼ã¿)ãå ¥åãã¾ãï¼äºæ¸¬å¨ã®åºåã¯ã¬ã¤ãã£ã³ã°ã表ãã¦ããããï¼ãããç¨ãã¦ç»åéåã®é åºä»ããè¡ãã¾ãï¼
ä½ã«ä½¿ãããï¼
ç»åã好ã¿ã®é çªã«ä¸¦ãã§ããã¨å¬ããã±ã¼ã¹ã¯è²ã èãããã¾ãï¼
- 漫ç»ã®è¡¨ç´è²·ãï¼ã¢ã«ãã ã®ã¸ã£ã±ããè²·ã
- pixivã®ãããªã¤ã©ã¹ãã³ãã¥ãã±ã¼ã·ã§ã³ãµã¼ãã¹ã§ï¼å¥½ã¿ã®ç»åæ¤ç´¢
- Amazonãªã©ã®ã·ã§ããã³ã°ãµã¤ãã§ï¼è³¼è²·çãä¸ãããããªç»åã®è¡¨ç¤º
å®è£
ã¾ãã¯ãããã¯ã¼ã¯ãæ¸ãã¾ãï¼CNNãRankNetãé常ã«ã·ã³ãã«ã«æ¸ãã¾ãã(Chainerå¼·ã)ï¼
CNNã®ãã©ã¡ã¼ã¿ã¯æ±ºãæã¡ã§ãï¼å
¥åç»åã¯RGBã§ãµã¤ãºã¯80Ã80ã¨ãã¾ãï¼
from chainer import Chain import chainer.functions as F import chainer.links as L class CNN(Chain): def __init__(self): """ picture size: 3 * 80 * 80 Convolution2D parameter input_channels, output_channels, filter_size """ super(CNN, self).__init__( conv1=F.Convolution2D(3, 20, 5), conv2=F.Convolution2D(20, 50, 5), l1=L.Linear(14450, 500), l2=L.Linear(500, 1) ) def __call__(self, x): h1 = F.max_pooling_2d(F.relu(self.conv1(x)), 2) h2 = F.max_pooling_2d(F.relu(self.conv2(h1)), 2) h3 = F.relu(self.l1(h2)) y = self.l2(h3) return y class RankNet(Chain): def __init__(self, predictor): super(RankNet, self).__init__(predictor=predictor) def __call__(self, x_i, x_j, t_i, t_j): s_i = self.predictor(x_i) s_j = self.predictor(x_j) s_diff = s_i - s_j if t_i.data > t_j.data: S_ij = 1 elif t_i.data < t_j.data: S_ij = -1 else: S_ij = 0 self.loss = (1 - S_ij) * s_diff / 2. + \ F.math.exponential.Log()(1 + F.math.exponential.Exp()(-s_diff)) return self.loss
次ã¯è¨ç·´ã®ã¹ã¯ãªãããæ¸ãã¾ãï¼
å
¥åã¯è¨ç·´ç»åã¨ã¬ã¤ãã£ã³ã°ãã¡ã¤ã«ã§ãï¼è¨ç·´ç»åã¯numpyã§ã·ãªã¢ã©ã¤ãºããããã¡ã¤ã«(.npy)ã¨ãï¼ã¬ã¤ãã£ã³ã°ãã¡ã¤ã«ã¯åç»åã®ã¬ã¤ãã£ã³ã°ãNè¡ä¸¦ãã ããã¹ããã¡ã¤ã«ã¨ãã¾ãï¼
åºåã¯è¨ç·´ç»åã®ã¬ã¤ãã£ã³ã°çµæã¨ï¼äºæ¸¬å¨ãã·ãªã¢ã©ã¤ãºãããã¡ã¤ã«(.pkl)ã§ãï¼
# -*- coding: utf-8 -*- import argparse import pickle import numpy as np from chainer import Variable, optimizers import net def ndcg(y_true, y_score, k=None): y_true = y_true.ravel() y_score = y_score.ravel() if k is None: k = len(y_true) y_true_sorted = sorted(y_true, reverse=True) ideal_dcg = 0 for i in range(k): ideal_dcg += (2 ** y_true_sorted[i] - 1.) / np.log2(i + 2) dcg = 0 argsort_indices = np.argsort(y_score)[::-1] for i in range(k): dcg += (2 ** y_true[argsort_indices[i]] - 1.) / np.log2(i + 2) ndcg = dcg / ideal_dcg return ndcg if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument("X_train_npy") parser.add_argument("rank_file") parser.add_argument("--output_pred", "-op", default="pred.txt") parser.add_argument("--output_model", "-om", default="model.pkl") parser.add_argument("--image_scale", type=float, default=1/255) parser.add_argument("--n_iter", type=int, default=1000) parser.add_argument("--monitor_step", type=int, default=100) parser.add_argument("--ndcg_k", type=int, default=100) args = parser.parse_args() np.random.seed(0) X_train = np.load(args.X_train_npy) X_train *= args.image_scale y_train = np.loadtxt(args.rank_file) N_train = np.shape(X_train)[0] model = net.RankNet(net.CNN()) optimizer = optimizers.Adam() optimizer.setup(model) for step in range(1, args.n_iter + 1): i, j = np.random.randint(N_train, size=2) # X_train: (N, 3, 80, 80) x_i = X_train[i].reshape((1, ) + X_train[i].shape) x_j = X_train[j].reshape((1, ) + X_train[j].shape) y_i = Variable(np.array(y_train[i])) y_j = Variable(np.array(y_train[j])) model.zerograds() loss = model(x_i, x_j, y_i, y_j) loss.backward() optimizer.update() if step % args.monitor_step == 0: train_pred = model.predictor(X_train).data train_ndcg = ndcg(y_train, train_pred, args.ndcg_k) print("step: {} | NDCG@{} | train: {}".format( step, args.ndcg_k, train_ndcg)) y_pred = model.predictor(X_train).data np.savetxt(args.output_pred, y_pred) out_model = args.output_model with open(out_model, "wb") as out_fp: pickle.dump(model, out_fp)
æå¾ã«äºæ¸¬ã®ã¹ã¯ãªãããæ¸ãã¾ãï¼ã¨ãã£ã¦ããã¹ãç»åã¨äºæ¸¬å¨ãèªã¿è¾¼ãã§äºæ¸¬ããã ãã§ããâ¦
# -*- coding: utf-8 -*- import argparse import pickle import numpy as np if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument("model_pkl") parser.add_argument("X_test_npy") parser.add_argument("--output", "-o", default="pred.txt") args = parser.parse_args() with open(args.model_pkl, "rb") as model_pkl_fp: model = pickle.load(model_pkl_fp) X_test = np.load(args.X_test_npy) y_pred = model.predictor(X_test).data np.savetxt(args.output, y_pred)
使ç¨ä¾
以ä¸ã®å®è£
ã使ã£ã¦ï¼ãã©ãã©ã¤ãï¼ãµã³ã·ã£ã¤ã³!!ãã®ç»åé åºäºæ¸¬ããã£ã¦ã¿ããã¨æãã¾ãï¼
è¨ç·´ãã¼ã¿ã«ã¯ãã©ãã©ã¤ã!ãã®ç»åãç¨ãã¾ããï¼
å¦ç¿ã®æµã
- Lantisã¡ãããããã『TVアニメ「ラブライブ!」先行発表PV』ãåå¾ãã¾ãï¼
- OpenCVãç¨ãã¦é¡é¨åãã¯ãªãããã¾ãï¼277æã®é¡ç»åãçæãã¾ããï¼é¡ç»åèªèã¯lbpcascade_animefaceãåèã«ãã¾ããï¼
- åç»åã«ã¬ã¤ãã£ã³ã°ãä»ãã¾ã(277æã®ç»åã«ã¬ã¤ãã£ã³ã°ãä»ãã¾ãï¼ã¤ããä½æ¥)ï¼
- ä¸è¨ã§å®è£ ããCNN+RankNetã§å¦ç¿ãã¾ãï¼
è¨ç·´ãã¼ã¿ã«å¯¾ããäºæ¸¬çµæ
ã¾ãï¼ä¸è¨ã®å®è£
ãæ£ããåãã¦ãããã¨ã確èªããããã«ï¼è¨ç·´ãã¼ã¿ã«å¯¾ãã¦äºæ¸¬ãè¡ãæ£ããé åºä»ãããã¦ãããã確èªãã¾ãï¼
ã¬ã¤ãã£ã³ã°å¤ã¯å¥½ã¿åº¦ã表ãã¦ãã¾ãï¼å·¦ã«è¡ãã»ã©å¥½ãã§ãï¼ï¼
ã«ãã«ã¼ã¨å¸ã¡ãããä¸ä½ã«ããããæ¥ã¦ã¾ãï¼è±é½ã¡ããã¯1æã ãè¦å½ããã¾ãï¼ã¬ã¤ãã£ã³ã°ä¸ä½ã®ãã£ã©ã¯ã¿ã¼ã¨é¡ä¼¼æ§ãé«ãããã§ããããâ¦
è¨ç·´ãã¼ã¿å
ã«é常ã«é¡ä¼¼ããç»åãå«ã¾ãã¦ãã¾ããï¼ããã¯ã¯ãªããã³ã°å¾ã«ã¯ã©ã¹ã¿ãªã³ã°çãè¡ã£ã¦ããªãããã§ãï¼åé·ãªãã¼ã¿ã¯è¨ç·´ãã¼ã¿ããåãé¤ããæ¹ãè¯ãã¨æãã¾ãï¼
ãã¹ããã¼ã¿ã«å¯¾ããäºæ¸¬çµæ
å¦ç¿ã®çµæå¾ãããäºæ¸¬å¨ã使ã£ã¦ï¼ãã©ãã©ã¤ãï¼ãµã³ã·ã£ã¤ã³!!ãã®ç»åé åºäºæ¸¬ããã¾ãï¼
ãã¹ãç»åã¯Lantisã¡ããããããラブライブ!サンシャイン!! Aqoursメンバー紹介PVãåå¾ãï¼å
ç¨ã¨åæ§ã«é¡ç»åãã¯ãªãããã¾ãï¼åãã£ã©æ¯ã«2種é¡ã®ç»åãåãåºãã¦è¨18æã®ç»åããã¹ããã¼ã¿ã¨ãã¾ããï¼
ä¸ãç§ãã©ã³ã¯ä»ãããçµæ(å·¦ã«è¡ãã»ã©å¥½ã)ã§ï¼ä¸ãCNN+RankNetã«ããäºæ¸¬çµæã§ãï¼
ãªããªãç§ã®ã©ã³ã¯ä»ãçµæã¨ã¯ä¸è´ãã¾ãããï¼è¨ç·´ãã¼ã¿ã®å¾åã¯åæ ãã¦ããããã«è¦ãã¾ãï¼
ã¾ãï¼åããã£ã©ã¯ã¿ã¼ã®ç»åã¯ä¼¼ããããªé ä½ã«æ¥ã¦ãããã¨ããããã¾ãï¼
ã¾ã¨ã
ãã®è¨äºã§ã¯CNN+RankNetã使ã£ãç»åã®é åºäºæ¸¬ã«ã¤ãã¦ï¼å®è£
ããã³ä½¿ç¨ä¾ãç´¹ä»ãã¾ããï¼
使ç¨ä¾ã§ç´¹ä»ãããã£ã©ã¯ã¿ã¼é åºäºæ¸¬ã¯é£ããåé¡ã§ãï¼ã©ã³ã¯ä»ãã®éã«ï¼ãã£ã©ã¯ã¿ã¼ã¸ã®æãå
¥ããå
¥ã£ã¦ãã¾ãã®ã§â¦
ãã£ã©ã¯ã¿ã¼é åºäºæ¸¬ã«æ¬æ°ã§åãçµãéã«ã¯ï¼ãã£ã©ã¯ã¿ã¼ã®æ§æ ¼ãå¦ç¿ã«ã©ãã«ããã¦åãå
¥ããå¿
è¦ãããããã§ãï¼
ããã«ã¤ãã¦ã¯ï¼TokyoTechLTã§çºè¡¨å¾ã«ä»¥ä¸ã®ãããªæè¦ãããã ãã¾ããï¼
ãã£ã©ã¯ã¿ã¼ã®æ§æ ¼ã¯å°è©éããâ¦ï¼å°å£°ï¼#TokyoTechLT
— ã¡ã¿ (@Meta1127) October 19, 2016
ãã£ã©ã®ã»ãªãããã¼ã¿ã¨ãã¦ä½¿ãã°æ§æ ¼ã®èæ ®ã¯ã¡ãã£ã¨ã§ããã#TokyoTechLT
— ããã¼ (@phoro3) October 19, 2016
ãã«ãã¢ã¼ãã«å¦ç¿ã«ãªã£ã¦ãã¾ãããï¼ããã¹ãã§é ä½ä»ããã¦ããä¾ã¯ã¾ãã«webãã¼ã¸ã©ã³ãã³ã°ã§ããï¼ç»åæ å ±ãçµåããã©ã³ãã³ã°äºæ¸¬ãªãã¦ãããã¦ãããã§ããããâ¦ï¼ï¼æ°ããç 究ãã¿ã«ãªãããã§ãï¼
ã¬ã¤ãã£ã³ã°ãä»ããä½æ¥ã¯çµæ§å¤§å¤ã§ãï¼ãã®ããå¦ç¿ãã¼ã¿ãµã¤ãºãå°ãããªã£ã¦ãã¾ãã¨ããåé¡ç¹ãããã¾ãï¼ããã«ã¤ãã¦ã¯æ¢åã®å¦ç¿æ¸ã¿äºæ¸¬å¨ãfine tuningãããï¼èªåã§ã¬ã¤ãã£ã³ã°ãå¾ãæ¹æ³(ç»åã¯ãªãã¯ç)ãèããã¨è¯ãããã§ãï¼
ãã¾ãChainerèªä½ã®è©±ã¯ãã¦ãã¾ããã§ãããï¼Pylearn2 -> Caffe -> Chainerã¨ç§»ãå¤ãã£ã¦ãã身ããããã¨ï¼Chainerã¯ããªã楽ã«ãããã¯ã¼ã¯ãæ¸ããã®ã§å¥½ãã§ãï¼Deep Learningãã¬ã¼ã ã¯ã¼ã¯ã溢ãã¦ãããæä¸ã§ããï¼ä½ã§ãè¯ãã®ã§1ã¤ä½¿ããããã«ãã¦ããã°è¯ãã¨æãã¾ãâ¦è²ã ãªãã¬ã¼ã ã¯ã¼ã¯ãå¹³åçã«ç¥ã£ã¦ãããããï¼1ã¤ã®ãã¬ã¼ã ã¯ã¼ã¯ã極ããæ¹ãè¯ãããããªãããªã(ã»ãã»)