ãã®è¨äºã¯ä½ï¼
szdr.hatenablog.com
ã«å¼ãç¶ããããã¤ãºæ¨è«ã«ããæ©æ¢°å¦ç¿å
¥éãã§ç´¹ä»ããã¦ããã¢ã«ã´ãªãºã ãå®è£
ã»å®é¨ãã¦ããã¾ãã
ä»åã¯4ç« ã®ããã¢ã½ã³æ··åã¢ãã«ã«ãããæ¨è«ãã§ç´¹ä»ããã¦ããããã¢ã½ã³æ··åã¢ãã«ã®ããã®ã®ãã¹ãµã³ããªã³ã°ã»ãã¢ã½ã³æ··åã¢ãã«ã®ããã®å¤åæ¨è«ãå®è£
ã»å®é¨ãã¾ããã
ãããããã¨
以ä¸ã®å³ã§è¡¨ããããããªäºå³°æ§ã®1次å
ãã¼ã¿ãèãã¾ãã
ãã®ãã¼ã¿ã¯ããã300åãµã³ããªã³ã°ããã200åãµã³ããªã³ã°ããåè¨500åã®ãµã³ãã«ã§ãã
ãã®1次å ãã¼ã¿ãã¤ã®ã¯ã©ã¹ã¿ã«å²ãå½ã¦ãåé¡ããã®è¨äºã§ã¯èãã¾ãã
æ··åã¢ãã«ã®ãã¼ã¿çæéç¨ã以ä¸ã®ããã«èãã¾ãã
- 2ã¤ã®ã¯ã©ã¹ã¿ã®æ··åæ¯çãäºååå¸ããçæããã
- ããããã®ã¯ã©ã¹ã¿ã«å¯¾ãã観測ã¢ãã«ã®ãã©ã¡ã¼ã¿ãäºååå¸ããçæããã
- ã«é¢ãã¦ãã«å¯¾å¿ããã¯ã©ã¹ã¿ã®å²ãå½ã¦ãããçæããã
- ã«é¢ãã¦ãã«ãã£ã¦é¸æãããçªç®ã®ç¢ºçåå¸ãããã¼ã¿ãçæããã
ã°ã©ãã£ã«ã«ã¢ãã«ã§è¡¨ãã¨ä»¥ä¸ã®å³ã®ããã«ãªãã¾ãã
äºå¾åå¸ãæ±ã¾ãã¨å¬ããã®ã§ãããäºå¾åå¸ã®å¼ã解æçã«æ±ããã®ã¯é£ããã®ã§ã®ãã¹ãµã³ããªã³ã°ãå¤åæ¨è«ã¨ãã£ãè¿ä¼¼æ¨è«ãç¨ãããã¾ãã
è¿ä¼¼æ¨è«ã®ã¢ã«ã´ãªãºã ã®å°åºã¯æ¬ãåèã«ãã¦ããã ãã¨ãã¦ããã®è¨äºã§ã¯ã©ã®ããã«å®è£ ããããç´¹ä»ãã¦ããã¾ãã
注æï¼æ¬ãããã¯èè
ã®ããã°è¨äº(以ä¸åç
§)ãèªãã§ããªãã¨ããªããããªã¢ã«ã´ãªãºã ãåºã¦ããã®ããªã©æå³ä¸æã ã¨æãã®ã§ããã²ãã¡ããåç
§ãã¦ãã ããã
machine-learning.hatenablog.com
machine-learning.hatenablog.com
ãã¢ã½ã³æ··åã¢ãã«ã®ããã®ã®ãã¹ãµã³ããªã³ã°
ã¢ã«ã´ãªãºã ã¯ä»¥ä¸ã®ããã«ãªãã¾ãã (æ¬ã®P133)
FOR i = 1, ..., MAXITER
ãFOR n = 1, ..., N
ãããæ±ãã
ããã¨ãã¦ãµã³ããªã³ã°
ãEND FOR
ãFOR k = 1, ..., K
ããã¨ãã¦ãµã³ããªã³ã°
ãEND FOR
ãã¨ãã¦ãµã³ããªã³ã°
END FOR
ãµã³ããªã³ã°çµæãè¦ããã¨ã§ãåãã¼ã¿ã®ã¯ã©ã¹ã¿å²ãå½ã¦ç¢ºçã»åã¯ã©ã¹ã¿ã®ãã¢ã½ã³åå¸ã®ãã©ã¡ã¼ã¿ã»ã¯ã©ã¹ã¿ã®æ··åæ¯çãæ¨è«ã§ãã¾ãã
ããã§ã¯ããã®ã¢ã«ã´ãªãºã ãå®è£ ãã¦ã¿ã¾ãã
# gibbs sampling (4.2) def mixture_poisson_gibbs_sampling(X, K, max_iter): # X: shape -> (N, 1) lmd = np.zeros((K, 1)) + 1 # (1, 1, ..., 1)ã§åæå pi = np.zeros((K, 1)) + 1 / K # (1/K, 1/K, ..., 1/K)ã§åæå a = 1 # ã¬ã³ãåå¸ãã¤ãã¼ãã©ã¡ã¼ã¿ b = 1 # ã¬ã³ãåå¸ãã¤ãã¼ãã©ã¡ã¼ã¿ alpha = np.zeros((K, 1)) + 1 # ãã£ãªã¯ã¬åå¸ãã¤ãã¼ãã©ã¡ã¼ã¿ N = X.shape[0] sampled_lmd = [] sampled_pi = [] sampled_S = [] for i in range(max_iter): # s_nããµã³ãã« tmp = X.dot(np.log(lmd).reshape(1, -1)) - lmd.reshape(1, -1) + np.log(pi).reshape(1, -1) log_Z = - log_sum_exp(tmp) eta = np.exp(tmp + log_Z) S = np.zeros((N, K)) for n in range(N): S[n] = multinomial.rvs(n=1, p=eta[n], size=1) sampled_S.append(S.copy()) # lmd_kããµã³ãã« hat_a = X.T.dot(S).reshape(-1, 1) + a hat_b = np.sum(S, axis=0).reshape(-1, 1) + b for k in range(K): lmd[k] = gamma.rvs(a=hat_a[k], scale=1/hat_b[k]) sampled_lmd.append(lmd.copy()) # piããµã³ãã« hat_alpha = np.sum(S, axis=0).reshape(-1, 1) + alpha pi = dirichlet.rvs(hat_alpha.reshape(-1), size=1).reshape(-1, 1) sampled_pi.append(pi.copy()) return np.array(sampled_lmd).reshape(-1, K), np.array(sampled_pi).reshape(-1, K), np.array(sampled_S).reshape(-1, N, K)
ãæ±ããé¨åã§åã1ã«ãªãããã«æ£è¦åããã¾ãã
ãã®é¨åã§ä½ãèããã«ææ°è¨ç®ããã¨ãªã¼ãã¼ããã¼ãã¦ãã¾ãã®ã§ãlogsumexpãã¯ã使ãã¾ããlogsumexpã«é¢ãã¦ã¯混合ガウス分布とlogsumexp - Qiitaãªã©ãåèã«ãã¦ãã ããã
ä»åã¯logsumexpã以ä¸ã®ããã«å®è£
ãã¦ã¿ã¾ããã
def log_sum_exp(X): # \log(\sum_{i=1}^{N}\exp(x_i)) max_x = np.max(X, axis=1).reshape(-1, 1) return np.log(np.sum(np.exp(X - max_x), axis=1).reshape(-1, 1)) + max_x
100åãµã³ããªã³ã°(max_iter=100)ãè¡ãã¾ãããã¾ãã¯ã®ãµã³ããªã³ã°çµæãä¸å³ã«ç¤ºãã¾ãã
ã®ãµã³ããªã³ã°çµæã®å¹³åå¤ã¯14.852ãã¯29.728ã§ãããçµæ§è¯ã精度ãåºã¦ãã¾ãã
次ã«ã®ãµã³ããªã³ã°çµæãä¸å³ã«ç¤ºãã¾ãããªã®ã§ãã®çµæã示ãã¾ãã
ã®ãµã³ããªã³ã°çµæã®å¹³åå¤ã¯0.590ã§ãããå
ãã¼ã¿ã¯ã¯ã©ã¹ã¿1ãã300åã»ã¯ã©ã¹ã¿2ãã200åãµã³ããªã³ã°ãã¦ããã®ã§ãæ··åæ¯çã¯300 / (300 + 200) = 0.6ã¨ãªãããã¡ããçµæ§è¯ã精度ãåºã¦ãã¾ãã
ããã§ã¯åãã¼ã¿ã®ã¯ã©ã¹ã¿å²ãå½ã¦ç¢ºçãè¦ã¦ã¿ã¾ãã
ãã¹ãã°ã©ã ã®åãã³æ¯ã«ããã³ã«å«ã¾ãããã¼ã¿ã®ã¯ã©ã¹ã¿å²ãå½ã¦ç¢ºçã®å¹³åå¤ãæ±ãããã®å¤ã«ãã£ã¦èµ¤ãéã§å¡ãåãã¦ã¿ã¾ããã
ãå°ããã»ã©èµ¤è²ã£ã½ãã大ããã»ã©éè²ã£ã½ããªã£ã¦ã¿ã¾ãã
k-meansã®ãããªã¯ã©ã¹ã¿ãªã³ã°ã¢ã«ã´ãªãºã ã¨éã£ã¦ãåãã¼ã¿ã«å¯¾ããã¯ã©ã¹ã¿å²ãå½ã¦ç¢ºçãæ±ã¾ãã¾ãã
ãã®ãããã©ããããèªä¿¡ãæã£ã¦åãã¼ã¿ããã®ã¯ã©ã¹ã¿ã«å±ãããã¨ãããã¨ãè©ä¾¡ã§ãã¾ãã楽ããã§ããã
ãã¢ã½ã³æ··åã¢ãã«ã®ããã®å¤åæ¨è«
ã¢ã«ã´ãªãºã ã¯ä»¥ä¸ã®ããã«ãªãã¾ãã(æ¬ã®P137)
FOR i = 1, ..., MAXITER
ãFOR n = 1, ..., N
ãããæ±ãã
ãããæ´æ°
ãEND FOR
ãFOR k = 1, ..., K
ãããæ´æ°
ãEND FOR
ããæ´æ°
END FOR
æå¾
å¤è¨ç®ãã¢ã«ã´ãªãºã ä¸ã«å«ã¾ãã¦ãã¾ãããããã¯ä»¥ä¸ã®å¼ã§ä¸ãããã¾ãã
ããã§ãã¯ãã£ã¬ã³ãé¢æ°ã§ãã
ããã§ã¯ããã®ã¢ã«ã´ãªãºã ãå®è£ ãã¦ã¿ã¾ãã
# variational inference (4.3) def mixture_poisson_variational_inference(X, K, max_iter): init_a = np.ones((K, 1)) init_b = np.ones((K, 1)) init_alpha = np.random.rand(K, 1) a = init_a.copy() b = init_b.copy() alpha = init_alpha.copy() for i in range(max_iter): # q(s_n)ãæ´æ° ln_lmd_mean = digamma(a) - np.log(b) lmd_mean = a / b ln_pi_mean = digamma(alpha) - digamma(np.sum(alpha)) tmp = X.dot(ln_lmd_mean.reshape(1, -1)) - lmd_mean.reshape(1, -1) + ln_pi_mean.reshape(1, -1) log_Z = - log_sum_exp(tmp) eta = np.exp(tmp + log_Z) # q(lmd_k)ãæ´æ° a = X.T.dot(eta).reshape(-1, 1) + init_a b = np.sum(eta, axis=0).reshape(-1, 1) + init_b # q(pi)ãæ´æ° alpha = np.sum(eta, axis=0).reshape(-1, 1) + init_alpha return a, b, eta, alpha
100ååãã¦ã¿ã¾ãã(max_iter=100)ã
ã¾ãã¯ãå¾ããããç¨ãã¦ãå³ç¤ºãã¾ãã
ã¯ã©ã¹ã¿1ã«å¯¾å¿ãããã¢ã½ã³åå¸ã®ãã©ã¡ã¼ã¿ã¯15ãããã§ãã¯ã©ã¹ã¿2ã«å¯¾å¿ãããã¢ã½ã³åå¸ã®ãã©ã¡ã¼ã¿ã¯29ãããã§ãã¼ã¯ãç«ã£ã¦ãã¾ãã
次ã«ãå¾ããããç¨ãã¦ãå³ç¤ºãã¾ãã
æ··åæ¯çã®ãã¼ã¯ã¯0.59ãããã§ç«ã£ã¦ãã¾ããã裾ãããåºãã«æããã¾ãããã ãæ··åæ¯çã¯0.59ã§ãï¼ãã£ã¦è¨ãã®ã§ã¯ãªãã¦ããå¤å0.59ããããªããããªãã§ãããã¼ãã¨è¨ããã®ãé¢ç½ãã§ãã
æå¾ã«ãå¾ããããç¨ãã¦åãã¼ã¿ã®ã¯ã©ã¹ã¿å²ãå½ã¦ç¢ºçãè¦ã¦ã¿ã¾ããã§ãããã¨ããããã¯ã©ã¹ã¿å²ãå½ã¦ç¢ºçã¨ãã¦è§£éã§ãã¾ãã
å³ç¤ºæ¹æ³ã¯ã®ãã¹ãµã³ããªã³ã°ã§ãã£ãæã¨åãã§ããã®ãã¹ãµã³ããªã³ã°ã®æã¨åããããªçµæãå¾ããã¦ãã¾ããã
ãã®ä»
- å®éã«å®è£ ãã¦ã¿ãã¨ãã®ãã¹ãµã³ããªã³ã°ã¨å¤åæ¨è«ã®é¡ä¼¼ç¹ãåããã¾ãã
- å®è£ ãã¦ã¿ã¦ããããã¢ã«ã´ãªãºã ã®æ°æã¡ãåããã¾ãããæåããã®å¤§äºã§ããããã
- ã¯ã©ã¹ã¿ãªã³ã°å¯è¦åã®å³ãæãã®ã«çµæ§æéåãã¾ãããå®è£ ãè¼ãã¦ããã¾ã(ã¡ãã£ã¨æ±ãã§ããããã)
def plot_clustering(prob_mat, bin_num): bins = np.linspace(np.min(X), np.max(X), num=bin_num) X_inds = np.digitize(X, bins) norms = np.zeros(bin_num + 1) cnts = np.zeros(bin_num + 1) for x_ind, prob_n in zip(X_inds[:, 0], prob_mat): norms[x_ind - 1] += prob_n[0] cnts[x_ind - 1] += 1 for i in range(bin_num + 1): if cnts[i] != 0: norms[i] /= cnts[i] plt.figure(figsize=(8, 4)) _, _, patches = plt.hist(X, bins=bins) cm = matplotlib.cm.get_cmap("coolwarm") colors = [cm(norm) for norm in norms] for patch, color in zip(patches, colors): patch.set_fc(color) plt.show()