al_util.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. import numpy as np
  2. import scipy as sp
  3. from scipy.optimize import root
  4. import scipy.linalg as sla
  5. from scipy.stats import norm
  6. def get_acc(u, labels, unlabeled = None):
  7. u_ = np.sign(u)
  8. u_[u_ == 0] = 1
  9. if unlabeled is None:
  10. corr = sum(1.*(u_ == labels))
  11. return corr, corr/u.shape[0]
  12. else:
  13. corr = sum(1.*(u_[unlabeled] == labels[unlabeled]))
  14. return corr, corr/len(unlabeled)
  15. def get_acc_multi(u, labels, unlabeled=None):
  16. """
  17. Assuming that u and labels are NOT in one-hot encoding. i.e. ith entry of
  18. u and labels is the integer class in {0,1,2,...num_classes}.
  19. """
  20. if unlabeled is None:
  21. corr = sum(1.*(u == labels))
  22. return corr, corr/u.shape[0]
  23. else:
  24. corr = sum(1.*(u[unlabeled] == labels[unlabeled]))
  25. return corr, corr/len(unlabeled)
  26. ############# Gaussian Regression functions (Full Storage Model)##############
  27. def gr_C(Z, gamma, d, v):
  28. H_d = len(Z) *[1./gamma**2.]
  29. vZ = v[Z,:]
  30. post = sp.sparse.diags(d, format='csr') \
  31. + vZ.T @ sp.sparse.diags(H_d, format='csr') @ vZ
  32. return v @ sp.linalg.inv(post) @ v.T
  33. def gr_map(Z, y, gamma, d, v):
  34. C = gr_C(Z, gamma, d, v)
  35. return (C[:,Z] @ y)/(gamma * gamma)
  36. ########### ProbitNorm Jacobian and Hessian entry Calculations ##########
  37. def jac_calc(uj_, yj_, gamma):
  38. return -yj_*(norm.pdf(uj_*yj_, scale=gamma)/norm.cdf(uj_*yj_, scale=gamma))
  39. def hess_calc(uj_, yj_, gamma):
  40. return (norm.pdf(uj_*yj_,scale=gamma)**2 - pdf_deriv(uj_*yj_, gamma)*norm.cdf(uj_*yj_,scale=gamma))/(norm.cdf(uj_*yj_,scale=gamma)**2)
  41. ########### (Full Storage Model) Functions #############
  42. def probit_map_dr(Z_, yvals, gamma, Ct):
  43. """
  44. Probit MAP estimator, using dimensionality reduction via Representer Theorem.
  45. *** This uses cdf of normal distribution ***
  46. """
  47. Ctp = Ct[np.ix_(Z_,Z_)]
  48. Jj = len(yvals)
  49. def f(x):
  50. vec = [jac_calc(x[j], yj, gamma) for j,yj in enumerate(yvals)]
  51. if np.any(vec == np.inf):
  52. print('smally in f')
  53. return x + Ctp @ vec
  54. def fprime(x):
  55. H = Ctp * np.array([hess_calc(x[j],yj, gamma)
  56. for j, yj in enumerate(yvals)])
  57. if np.any(H == np.inf):
  58. print('smally')
  59. H[np.diag_indices(Jj)] += 1.0
  60. return H
  61. x0 = np.random.rand(Jj)
  62. x0[np.array(yvals) < 0] *= -1
  63. res = root(f, x0, jac=fprime)
  64. #print(np.allclose(0., f(res.x)))
  65. tmp = sla.inv(Ctp) @ res.x
  66. return Ct[:, Z_] @ tmp
  67. def Hess_inv(u, Z, y, gamma, Ct):
  68. Ctp = Ct[np.ix_(Z, Z)]
  69. H_d = np.zeros(len(y))
  70. for i, (j, yj) in enumerate(zip(Z, y)):
  71. H_d[i] = 1./hess_calc(u[j], yj, gamma)
  72. temp = sp.linalg.inv(sp.sparse.diags(H_d, format='csr') + Ctp)
  73. return Ct - Ct[:, Z] @ temp @ Ct[Z, :]
  74. def Hess_inv_st(u, Z, y, w, v, gamma, debug=False):
  75. H_d = np.zeros(len(Z))
  76. vZ = v[Z,:]
  77. for i, (j, yj) in enumerate(zip(Z, y)):
  78. H_d[i] = hess_calc2(u[j], yj, gamma)
  79. post = sp.sparse.diags(w, format='csr') \
  80. + vZ.T @ sp.sparse.diags(H_d, format='csr') @ vZ
  81. return v @ sp.linalg.inv(post) @ v.T
  82. ################ Logistic and Hessian entry Calculations##################
  83. def jac_calc2(uj_, yj_, gamma):
  84. return -yj_*(np.exp(-uj_*yj_/gamma))/(gamma*(1.0 + np.exp(-uj_*yj_/gamma)))
  85. def hess_calc2(uj_, yj_, gamma):
  86. return np.exp(-uj_*yj_/gamma)/(gamma**2. * (1. + np.exp(-uj_*yj_/gamma))**2.)
  87. ########### (Full Storage Model) Functions #############
  88. def probit_map_dr2(Z_, yvals, gamma, Ct):
  89. """
  90. Probit MAP estimator, using dimensionality reduction via Representer Theorem.
  91. *** This uses logistic cdf ***
  92. """
  93. Ctp = Ct[np.ix_(Z_,Z_)]
  94. Jj = len(yvals)
  95. def f(x):
  96. vec = [jac_calc2(x[j], yj, gamma)
  97. for j,yj in enumerate(yvals)]
  98. return x + Ctp @ vec
  99. def fprime(x):
  100. H = Ctp * np.array([hess_calc2(x[j], yj, gamma)
  101. for j, yj in enumerate(yvals)])
  102. if np.any(H == np.inf):
  103. print('smally')
  104. H[np.diag_indices(Jj)] += 1.0
  105. return H
  106. x0 = np.random.rand(Jj)
  107. x0[np.array(yvals) < 0] *= -1
  108. res = root(f, x0, jac=fprime)
  109. tmp = sla.inv(Ctp) @ res.x
  110. return Ct[:, Z_] @ tmp
  111. def Hess2_inv(u, Z, y, gamma, Ct):
  112. Ctp = Ct[np.ix_(Z, Z)]
  113. H_d = np.zeros(len(y))
  114. for i, (j, yj) in enumerate(zip(Z, y)):
  115. H_d[i] = 1./hess_calc2(u[j], yj, gamma)
  116. temp = sp.linalg.inv(sp.sparse.diags(H_d, format='csr') + Ctp)
  117. return Ct - Ct[:, Z] @ temp @ Ct[Z, :]
  118. def Hess_inv_st2(u, Z, y, w, v, gamma, debug=False):
  119. H_d = np.zeros(len(Z))
  120. vZ = v[Z,:]
  121. for i, (j, yj) in enumerate(zip(Z, y)):
  122. H_d[i] = hess_calc2(u[j], yj, gamma)
  123. post = sp.sparse.diags(w, format='csr') \
  124. + vZ.T @ sp.sparse.diags(H_d, format='csr') @ vZ
  125. return v @ sp.linalg.inv(post) @ v.T
  126. ##################################################################################
  127. ################### Helper Functions for Reduced Model ###########################
  128. ##################################################################################
  129. def Hess_inv_st_alpha(alpha, y, d, v_Z, gamma):
  130. '''
  131. This method keeps everything in the "alpha"-space, of dimension num_eig x num_eig
  132. '''
  133. Dprime = sp.sparse.diags([1./hess_calc(np.inner(v_Z[i,:],alpha), yi, gamma) for i, yi in enumerate(y)], format='csr')
  134. A = d[:, np.newaxis] * ((v_Z.T @ sp.linalg.inv(Dprime + v_Z @ (d[:, np.newaxis] * (v_Z.T))) @ v_Z) * d)
  135. return np.diag(d) - A
  136. def Hess_inv_st2_alpha(alpha, y, d, v_Z, gamma):
  137. '''
  138. This method keeps everything in the "alpha"-space, of dimension num_eig x num_eig
  139. '''
  140. Dprime = sp.sparse.diags([1./hess_calc2(np.inner(v_Z[i,:],alpha), yi, gamma) for i, yi in enumerate(y)], format='csr')
  141. A = d[:, np.newaxis] * ((v_Z.T @ sp.linalg.inv(Dprime + v_Z @ (d[:, np.newaxis] * (v_Z.T))) @ v_Z) * d)
  142. return np.diag(d) - A
  143. def probit_map_st_alpha(Z, y, gamma, w, v):
  144. n,l = v.shape[1], len(y)
  145. def f(x):
  146. vec = np.zeros(l)
  147. for j, (i,yi) in enumerate(zip(Z,y)):
  148. vec[j] = - jac_calc(np.inner(v[i,:], x), yi, gamma)
  149. return w * x - v[Z,:].T @ vec
  150. def fprime(x):
  151. vec = np.zeros(l)
  152. for j, (i,yi) in enumerate(zip(Z, y)):
  153. vec[j] = -hess_calc(np.inner(v[i,:], x), yi, gamma)
  154. H = (-v[Z,:].T * vec) @ v[Z,:]
  155. H[np.diag_indices(n)] += w
  156. return H
  157. x0 = np.random.rand(len(w))
  158. res = root(f, x0, jac=fprime)
  159. #print(f"Root Finding is successful: {res.success}")
  160. return res.x
  161. def probit_map_st2_alpha(Z, y, gamma, w, v):
  162. n,l = v.shape[1], len(y)
  163. def f(x):
  164. vec = np.zeros(l)
  165. for j, (i,yi) in enumerate(zip(Z,y)):
  166. vec[j] = - jac_calc2(np.inner(v[i,:], x), yi, gamma)
  167. return w * x - v[Z,:].T @ vec
  168. def fprime(x):
  169. vec = np.zeros(l)
  170. for j, (i,yi) in enumerate(zip(Z, y)):
  171. vec[j] = -hess_calc2(np.inner(v[i,:], x), yi, gamma)
  172. H = (-v[Z,:].T * vec) @ v[Z,:]
  173. H[np.diag_indices(n)] += w
  174. return H
  175. x0 = np.random.rand(len(w))
  176. res = root(f, x0, jac=fprime)
  177. #print(f"Root Finding is successful: {res.success}")
  178. return res.x
  179. # class Classifier(object):
  180. # def __init__(self, name, gamma, tau, v=None, w=None, Ct=None):
  181. # self.gamma = gamma
  182. # self.tau = tau
  183. # self.v = v
  184. # self.w = w
  185. # if Ct is not None:
  186. # self.Ct = Ct
  187. # else:
  188. # self.d = (self.tau ** (2.)) * ((self.w + self.tau**2.) ** (-1.))
  189. # self.Ct = (self.v * self.d) @ self.v.T
  190. # self.name = name
  191. # return
  192. #
  193. # def get_m(self, Z, y):
  194. # if self.name == "probit":
  195. # if len(y) <= len(self.w):
  196. # return probit_map_dr(Z, y, self.gamma, self.Ct)
  197. # else:
  198. # return probit_map_st(Z, y, self.gamma, 1./self.d, self.v)
  199. # elif self.name == "probit2":
  200. # if len(y) <= len(self.w):
  201. # return probit_map_dr2(Z, y, self.gamma, self.Ct)
  202. # else:
  203. # return probit_map_st2(Z, y, self.gamma, 1./self.d, self.v)
  204. # elif self.name == "gr":
  205. # #return gr_map(Z, y, self.gamma, self.Ct)
  206. # return gr_map(Z, y, self.gamma, 1./self.d, self.v)
  207. # else:
  208. # pass
  209. #
  210. # def get_C(self, Z, y, m):
  211. # if self.name in ["probit", "probit-st"]:
  212. # if len(y) > len(self.w):
  213. # return Hess_inv_st(m, Z, y, 1./self.d, self.v, self.gamma)
  214. # else:
  215. # return Hess_inv(m, Z, y, self.gamma, self.Ct)
  216. # elif self.name in ["probit2", "probit2-st"]:
  217. # if len(y) > len(self.w):
  218. # return Hess_inv_st2(m, Z, y, 1./self.d, self.v, self.gamma)
  219. # else:
  220. # return Hess2_inv(m, Z, y, self.gamma, self.Ct)
  221. # elif self.name in ["gr"]:
  222. # #return gr_C(Z, self.gamma, self.Ct)
  223. # return gr_C(Z, self.gamma, 1./self.d, self.v)
  224. # else:
  225. # pass
  226. #
  227. #
  228. # class Classifier_HF(object):
  229. # def __init__(self, tau, L):
  230. # self.tau = tau
  231. # if sps.issparse(L):
  232. # self.sparse = True
  233. # self.L = L + self.tau**2. * sps.eye(L.shape[0])
  234. # else:
  235. # self.sparse = False
  236. # self.L = L + self.tau**2. * np.eye(L.shape[0])
  237. # return
  238. #
  239. # def get_m(self, Z, y):
  240. # Zbar = list(filter(lambda x: x not in Z, range(self.L.shape[0])))
  241. # self.m = -self.get_C(Z, Zbar=Zbar) @ self.L[np.ix_(Zbar, Z)] @ y
  242. # return self.m
  243. #
  244. # def get_C(self, Z, Zbar=None):
  245. # if Zbar is None:
  246. # Zbar = list(filter(lambda x: x not in Z, range(self.L.shape[0])))
  247. # if self.sparse:
  248. # self.C = scipy.sparse.linalg.inv(self.L[np.ix_(Zbar, Zbar)]).toarray() # inverse will be dense anyway
  249. # return self.C
  250. # else:
  251. # self.C = sla.inv(self.L[np.ix_(Zbar, Zbar)])
  252. # return self.C
  253. #
  254. #
  255. # ###############################################################################
  256. # ############### Gaussian Regression Helper Functions ##########################
  257. #
  258. #
  259. # def get_init_post(C_inv, labeled, gamma2):
  260. # """
  261. # calculate the risk of each unlabeled point
  262. # C_inv: prior inverse (i.e. graph Laplacian L)
  263. # """
  264. # N = C_inv.shape[0]
  265. # #unlabeled = list(filter(lambda x: x not in labeled, range(N)))
  266. # B_diag = [1 if i in labeled else 0 for i in range(N)]
  267. # B = sp.sparse.diags(B_diag, format='csr')
  268. # return sp.linalg.inv(C_inv + B/gamma2)
  269. #
  270. #
  271. # def calc_next_m(m, C, y, lab, k, y_k, gamma2):
  272. # ck = C[k,:]
  273. # ckk = ck[k]
  274. # ip = np.dot(ck[lab], y[lab])
  275. # val = ((gamma2)*y_k -ip )/(gamma2*(gamma2 + ckk))
  276. # m_k = m + val*ck
  277. # return m_k
  278. #
  279. #
  280. # def get_probs(m, sigmoid=False):
  281. # if sigmoid:
  282. # return 1./(1. + np.exp(-3.*m))
  283. # m_probs = m.copy()
  284. # # simple fix to get probabilities that respect the 0 threshold
  285. # m_probs[np.where(m_probs >0)] /= 2.*np.max(m_probs)
  286. # m_probs[np.where(m_probs <0)] /= -2.*np.min(m_probs)
  287. # m_probs += 0.5
  288. # return m_probs
  289. #
  290. #
  291. # def EEM_full(k, m, C, y, lab, unlab, m_probs, gamma2):
  292. # N = C.shape[0]
  293. # m_at_k = m_probs[k]
  294. # m_k_p1 = calc_next_m(m, C, y, lab, k, 1., gamma2)
  295. # m_k_p1 = get_probs(m_k_p1)
  296. # risk = m_at_k*np.sum([min(m_k_p1[i], 1.- m_k_p1[i]) for i in range(N)])
  297. # m_k_m1 = calc_next_m(m, C, y, lab, k, -1., gamma2)
  298. # m_k_m1 = get_probs(m_k_m1)
  299. # risk += (1.-m_at_k)*np.sum([min(m_k_m1[i], 1.- m_k_m1[i]) for i in range(N)])
  300. # return risk
  301. #
  302. #
  303. # def EEM_opt_record(m, C, y, labeled, unlabeled, gamma2):
  304. # m_probs = get_probs(m)
  305. # N = C.shape[0]
  306. # risks = [EEM_full(j, m, C, y, labeled, unlabeled, m_probs, gamma2) for j in range(N)]
  307. # k = np.argmin(risks)
  308. # return k, risks
  309. #
  310. #
  311. # def Sigma_opt(C, unlabeled, gamma2):
  312. # sums = np.sum(C[np.ix_(unlabeled,unlabeled)], axis=1)
  313. # sums = np.asarray(sums).flatten()**2.
  314. # s_opt = sums/(gamma2 + np.diag(C)[unlabeled])
  315. # k_max = unlabeled[np.argmax(s_opt)]
  316. # return k_max
  317. #
  318. #
  319. # def V_opt_record(C, unlabeled, gamma2):
  320. # ips = np.array([np.inner(C[k,:], C[k,:]) for k in unlabeled]).flatten()
  321. # v_opt = ips/(gamma2 + np.diag(C)[unlabeled])
  322. # k_max = unlabeled[np.argmax(v_opt)]
  323. # return k_max, v_opt
  324. #
  325. #
  326. # def V_opt_record2(u, C, unlabeled, gamma2, lam):
  327. # ips = np.array([np.inner(C[k,:], C[k,:]) for k in unlabeled]).flatten()
  328. # v_opt = ips/(gamma2 + np.diag(C)[unlabeled])
  329. # print(np.max(v_opt), np.min(v_opt))
  330. # v_opt += lam*(np.max(v_opt) + np.min(v_opt))*0.5*(1./np.absolute(u[unlabeled])) # add term that bias toward decision boundary
  331. # k_max = unlabeled[np.argmax(v_opt)]
  332. # return k_max, v_opt
  333. #
  334. #
  335. # def Sigma_opt_record(C, unlabeled, gamma2):
  336. # sums = np.sum(C[np.ix_(unlabeled,unlabeled)], axis=1)
  337. # sums = np.asarray(sums).flatten()**2.
  338. # s_opt = sums/(gamma2 + np.diag(C)[unlabeled])
  339. # k_max = unlabeled[np.argmax(s_opt)]
  340. # return k_max, s_opt
  341. #
  342. #
  343. #
  344. #
  345. # ################################################################################
  346. # ################## Plotting Helper Functions ###################################
  347. #
  348. #
  349. # def plot_iter(m, X, labels, labeled, k_next=-1, title=None, subplot=False):
  350. # '''
  351. # Assuming labels are +1, -1
  352. # '''
  353. # m1 = np.where(m >= 0)[0]
  354. # m2 = np.where(m < 0)[0]
  355. #
  356. # #sup1 = list(set(labeled).intersection(set(np.where(labels == 1)[0])))
  357. # #sup2 = list(set(labeled).intersection(set(np.where(labels == -1)[0])))
  358. #
  359. # corr1 = list(set(m1).intersection(set(np.where(labels == 1)[0])))
  360. # incorr1 = list(set(m2).intersection(set(np.where(labels == 1)[0])))
  361. # corr2 = list(set(m2).intersection(set(np.where(labels == -1)[0])))
  362. # incorr2 = list(set(m1).intersection(set(np.where(labels == -1)[0])))
  363. #
  364. # print("\tnum incorrect = %d" % (len(incorr1) + len(incorr2)))
  365. #
  366. # if k_next >= 0:
  367. # plt.scatter(X[k_next,0], X[k_next,1], marker= 's', c='y', alpha= 0.7, s=200) # plot the new points to be included
  368. # plt.title(r'Dataset with Label for %s added' % str(k_next))
  369. # elif k_next == -1:
  370. # if not title:
  371. # plt.title(r'Dataset with Initial Labeling')
  372. # else:
  373. # plt.title(title)
  374. #
  375. # plt.scatter(X[corr1,0], X[corr1,1], marker='x', c='b', alpha=0.2)
  376. # plt.scatter(X[incorr1,0], X[incorr1,1], marker='x', c='r', alpha=0.2)
  377. # plt.scatter(X[corr2,0], X[corr2,1], marker='o', c='r',alpha=0.15)
  378. # plt.scatter(X[incorr2,0], X[incorr2,1], marker='o', c='b',alpha=0.15)
  379. # # plt.scatter(X[corr1,0], X[corr1,1], marker='x', c='b', alpha=0.8)
  380. # # plt.scatter(X[incorr1,0], X[incorr1,1], marker='x', c='r', alpha=0.8)
  381. # # plt.scatter(X[corr2,0], X[corr2,1], marker='o', c='r',alpha=0.8)
  382. # # plt.scatter(X[incorr2,0], X[incorr2,1], marker='o', c='b',alpha=0.8)
  383. #
  384. # sup1 = list(set(labeled).intersection(set(np.where(labels == 1)[0])))
  385. # sup2 = list(set(labeled).intersection(set(np.where(labels == -1)[0])))
  386. # plt.scatter(X[sup1,0], X[sup1,1], marker='x', c='k', alpha=1.0)
  387. # plt.scatter(X[sup2,0], X[sup2,1], marker='o', c='k', alpha=1.0)
  388. # plt.axis('equal')
  389. # if subplot:
  390. # return
  391. # plt.show()
  392. # return
  393. #
  394. # ################################################################################
  395. # ########## MAP estimators of Probit model (with normal distribution's pdf )
  396. # ################################################################################
  397. #
  398. #
  399. def pdf_deriv(t, gamma):
  400. return -t*norm.pdf(t, scale = gamma)/(gamma**2)
  401. #
  402. # def jac_calc(uj_, yj_, gamma):
  403. # return -yj_*(norm.pdf(uj_*yj_, scale=gamma)/norm.cdf(uj_*yj_, scale=gamma))
  404. #
  405. #
  406. # def hess_calc(uj_, yj_, gamma):
  407. # return (norm.pdf(uj_*yj_,scale=gamma)**2 - pdf_deriv(uj_*yj_, gamma)*norm.cdf(uj_*yj_,scale=gamma))/(norm.cdf(uj_*yj_,scale=gamma)**2)
  408. #
  409. # def Hess(u, y, labeled, Lt, gamma, debug=False):
  410. # """
  411. # Assuming matrices are sparse, since L_tau should be relatively sparse,
  412. # and we are perturbing with diagonal matrix.
  413. # """
  414. # H_d = np.zeros(u.shape[0])
  415. # for j, yj in zip(labeled, y):
  416. # H_d[j] = hess_calc(u[j], yj, gamma)
  417. # if debug:
  418. # print(H_d[np.nonzero(H_d)])
  419. # # if np.any(H_d == np.inf):
  420. # # print('smally')
  421. # return Lt + sp.sparse.diags(H_d, format='csr')
  422. #
  423. #
  424. # def J(u, y, labeled, Lt, gamma, debug=False):
  425. # vec = np.zeros(u.shape[0])
  426. # for j, yj in zip(labeled,y):
  427. # vec[j] = -yj*norm.pdf(u[j]*yj, gamma)/norm.cdf(u[j]*yj, gamma)
  428. # if debug:
  429. # print(vec[np.nonzero(vec)])
  430. # return Lt @ u + vec
  431. #
  432. #
  433. # def probit_map_dr(Z_, yvals, gamma, Ct):
  434. # """
  435. # Probit MAP estimator, using dimensionality reduction via Representer Theorem.
  436. # *** This uses cdf of normal distribution ***
  437. # """
  438. # Ctp = Ct[np.ix_(Z_,Z_)]
  439. # Jj = len(yvals)
  440. #
  441. # def f(x):
  442. # vec = [jac_calc(x[j], yj, gamma) for j,yj in enumerate(yvals)]
  443. # if np.any(vec == np.inf):
  444. # print('smally in f')
  445. # return x + Ctp @ vec
  446. #
  447. # def fprime(x):
  448. # H = Ctp * np.array([hess_calc(x[j],yj, gamma)
  449. # for j, yj in enumerate(yvals)])
  450. # if np.any(H == np.inf):
  451. # print('smally')
  452. # H[np.diag_indices(Jj)] += 1.0
  453. # return H
  454. #
  455. # x0 = np.random.rand(Jj)
  456. # x0[np.array(yvals) < 0] *= -1
  457. # res = root(f, x0, jac=fprime)
  458. # #print(np.allclose(0., f(res.x)))
  459. # tmp = sla.inv(Ctp) @ res.x
  460. # return Ct[:, Z_] @ tmp
  461. #
  462. #
  463. #
  464. # ################################################################################
  465. # ################### Probit with logit likelihood
  466. # ################################################################################
  467. #
  468. # ###################### Psi = cdf of logistic #######################
  469. # def log_pdf(t, g):
  470. # return np.exp(-t/g)/(g*(1. + np.exp(-t/g)**2.))
  471. #
  472. #
  473. # def log_cdf(t, g):
  474. # return 1.0/(1.0 + np.exp(-t/g))
  475. #
  476. #
  477. # def log_pdf_deriv(t, g):
  478. # return -np.exp(-t/g)/((g*(1. + np.exp(-t/g)))**2.)
  479. #
  480. # def jac_calc2(uj_, yj_, gamma):
  481. # return -yj_*(np.exp(-uj_*yj_/gamma))/(gamma*(1.0 + np.exp(-uj_*yj_/gamma)))
  482. #
  483. # def hess_calc2(uj_, yj_, gamma):
  484. # return np.exp(-uj_*yj_/gamma)/(gamma**2. * (1. + np.exp(-uj_*yj_/gamma))**2.)
  485. #
  486. #
  487. # def Hess2(u, y, labeled, Lt, gamma, debug=False):
  488. # """
  489. # Assuming matrices are sparse, since L_tau should be relatively sparse,
  490. # and we are perturbing with diagonal matrix.
  491. # """
  492. # H_d = np.zeros(u.shape[0])
  493. # for j, yj in zip(labeled, y):
  494. # H_d[j] = hess_calc2(u[j], yj, gamma)
  495. # if debug:
  496. # print(H_d[np.nonzero(H_d)])
  497. # if np.any(H_d == np.inf):
  498. # print('smally')
  499. # return Lt + sp.sparse.diags(H_d, format='csr')
  500. #
  501. #
  502. # def J2(u, y, labeled, Lt, gamma, debug=False):
  503. # vec = np.zeros(u.shape[0])
  504. # for j, yj in zip(labeled,y):
  505. # vec[j] = jac_calc2(u[j], yj, gamma)
  506. # if debug:
  507. # print(vec[np.nonzero(vec)])
  508. # return Lt @ u + vec
  509. #
  510. #
  511. # def probit_map_dr2(Z_, yvals, gamma, Ct):
  512. # """
  513. # Probit MAP estimator, using dimensionality reduction via Representer Theorem.
  514. # *** This uses logistic cdf ***
  515. # """
  516. # Ctp = Ct[np.ix_(Z_,Z_)]
  517. # Jj = len(yvals)
  518. #
  519. # def f(x):
  520. # vec = [jac_calc2(x[j], yj, gamma)
  521. # for j,yj in enumerate(yvals)]
  522. # return x + Ctp @ vec
  523. #
  524. # def fprime(x):
  525. # H = Ctp * np.array([hess_calc2(x[j], yj, gamma)
  526. # for j, yj in enumerate(yvals)])
  527. # if np.any(H == np.inf):
  528. # print('smally')
  529. # H[np.diag_indices(Jj)] += 1.0
  530. # return H
  531. #
  532. # x0 = np.random.rand(Jj)
  533. # x0[np.array(yvals) < 0] *= -1
  534. # res = root(f, x0, jac=fprime)
  535. # tmp = sla.inv(Ctp) @ res.x
  536. # return Ct[:, Z_] @ tmp
  537. #
  538. #
  539. #
  540. # ################################################################################
  541. # # Spectral truncation
  542. # ################################################################################
  543. # """
  544. #
  545. # def pdf_deriv(t, gamma):
  546. # return -t*norm.pdf(t, scale = gamma)/(gamma**2)
  547. #
  548. # def jac_calc(uj_, yj_, gamma):
  549. # return -yj_*(norm.pdf(uj_*yj_, scale=gamma)/norm.cdf(uj_*yj_, scale=gamma))
  550. #
  551. #
  552. # def hess_calc(uj_, yj_, gamma):
  553. # return (norm.pdf(uj_*yj_,scale=gamma)**2 - pdf_deriv(uj_*yj_, gamma)*norm.cdf(uj_*yj_,scale=gamma))/(norm.cdf(uj_*yj_,scale=gamma)**2)
  554. #
  555. # """
  556. # def probit_map_st(Z, y, gamma, w, v):
  557. # N = v.shape[0]
  558. # n = v.shape[1]
  559. # def f(x):
  560. # vec = np.zeros(N)
  561. # tmp = v @ x
  562. # for i, yi in zip(Z, y):
  563. # vec[i] = - jac_calc(tmp[i], yi, gamma)
  564. # #vec[i] = yi*norm.pdf(tmp[i]*yi, scale=gamma)/norm.cdf(tmp[i]*yi, scale=gamma)
  565. # return w * x - v.T @ vec
  566. # def fprime(x):
  567. # tmp = v @ x
  568. # vec = np.zeros(N)
  569. # for i, yi in zip(Z, y):
  570. # vec[i] = -hess_calc(tmp[i], yi, gamma)
  571. # #vec[i] = (pdf_deriv(tmp[i]*yi,gamma)*norm.cdf(tmp[i]*yi,scale=gamma)
  572. # # - norm.pdf(tmp[i]*yi,scale=gamma)**2)/ (norm.cdf(tmp[i]*yi,scale=gamma)**2)
  573. # H = (-v.T * vec) @ v
  574. # H[np.diag_indices(n)] += w
  575. # return H
  576. # x0 = np.random.rand(len(w))
  577. # res = root(f, x0, jac=fprime)
  578. # #print(f"Root Finding is successful: {res.success}")
  579. # return v @ res.x
  580. #
  581. # # OLD Code
  582. # # def Hess_inv_st(u, Z, y, w, v, gamma, debug=False):
  583. # # """
  584. # # Assuming matrices are sparse, since L_tau should be relatively sparse,
  585. # # and we are perturbing with diagonal matrix.
  586. # # """
  587. # # H_d = np.zeros(u.shape[0])
  588. # # for j, yj in zip(Z, y):
  589. # # H_d[j] = hess_calc(u[j], yj, gamma)
  590. # # post = sp.sparse.diags(w, format='csr') \
  591. # # + v.T @ sp.sparse.diags(H_d, format='csr') @ v
  592. # # return v @ sp.linalg.inv(post) @ v.T
  593. #
  594. # def Hess_inv_st(u, Z, y, w, v, gamma, debug=False):
  595. # H_d = np.zeros(len(Z))
  596. # vZ = v[Z,:]
  597. # for i, (j, yj) in enumerate(zip(Z, y)):
  598. # H_d[i] = hess_calc2(u[j], yj, gamma)
  599. # post = sp.sparse.diags(w, format='csr') \
  600. # + vZ.T @ sp.sparse.diags(H_d, format='csr') @ vZ
  601. # return v @ sp.linalg.inv(post) @ v.T
  602. #
  603. #
  604. #
  605. # def probit_map_st2(Z, y, gamma, w, v):
  606. # N = v.shape[0]
  607. # n = v.shape[1]
  608. # def f(x):
  609. # vec = np.zeros(N)
  610. # tmp = v @ x
  611. # for i, yi in zip(Z, y):
  612. # vec[i] = - jac_calc2(tmp[i], yi, gamma)
  613. # #vec[i] = yi*norm.pdf(tmp[i]*yi, scale=gamma)/norm.cdf(tmp[i]*yi, scale=gamma)
  614. # return w * x - v.T @ vec
  615. # def fprime(x):
  616. # tmp = v @ x
  617. # vec = np.zeros(N)
  618. # for i, yi in zip(Z, y):
  619. # vec[i] = -hess_calc2(tmp[i], yi, gamma)
  620. # #vec[i] = (pdf_deriv(tmp[i]*yi,gamma)*norm.cdf(tmp[i]*yi,scale=gamma)
  621. # # - norm.pdf(tmp[i]*yi,scale=gamma)**2)/ (norm.cdf(tmp[i]*yi,scale=gamma)**2)
  622. # H = (-v.T * vec) @ v
  623. # H[np.diag_indices(n)] += w
  624. # return H
  625. # x0 = np.random.rand(len(w))
  626. # res = root(f, x0, jac=fprime)
  627. # #print(f"Root Finding is successful: {res.success}")
  628. # return v @ res.x
  629. #
  630. # # OLD code
  631. # # def Hess_inv_st2(u, Z, y, w, v, gamma, debug=False):
  632. # # """
  633. # # Assuming matrices are sparse, since L_tau should be relatively sparse,
  634. # # and we are perturbing with diagonal matrix.
  635. # # """
  636. # # H_d = np.zeros(u.shape[0])
  637. # # for j, yj in zip(Z, y):
  638. # # H_d[j] = hess_calc2(u[j], yj, gamma)
  639. # # post = sp.sparse.diags(w, format='csr') \
  640. # # + v.T @ sp.sparse.diags(H_d, format='csr') @ v
  641. # # return v @ sp.linalg.inv(post) @ v.T
  642. #
  643. # def Hess_inv_st2(u, Z, y, w, v, gamma, debug=False):
  644. # H_d = np.zeros(len(Z))
  645. # vZ = v[Z,:]
  646. # for i, (j, yj) in enumerate(zip(Z, y)):
  647. # H_d[i] = hess_calc2(u[j], yj, gamma)
  648. # post = sp.sparse.diags(w, format='csr') \
  649. # + vZ.T @ sp.sparse.diags(H_d, format='csr') @ vZ
  650. # return v @ sp.linalg.inv(post) @ v.T
  651. #
  652. #
  653. # def Hess_inv(u, Z, y, gamma, Ct):
  654. # Ctp = Ct[np.ix_(Z, Z)]
  655. # H_d = np.zeros(len(y))
  656. # for i, (j, yj) in enumerate(zip(Z, y)):
  657. # H_d[i] = 1./hess_calc(u[j], yj, gamma)
  658. # temp = sp.linalg.inv(sp.sparse.diags(H_d, format='csr') + Ctp)
  659. # return Ct - Ct[:, Z] @ temp @ Ct[Z, :]
  660. #
  661. # def Hess2_inv(u, Z, y, gamma, Ct):
  662. # Ctp = Ct[np.ix_(Z, Z)]
  663. # H_d = np.zeros(len(y))
  664. # for i, (j, yj) in enumerate(zip(Z, y)):
  665. # H_d[i] = 1./hess_calc2(u[j], yj, gamma)
  666. # temp = sp.linalg.inv(sp.sparse.diags(H_d, format='csr') + Ctp)
  667. # return Ct - Ct[:, Z] @ temp @ Ct[Z, :]
  668. #
  669. # # OLD inefficient
  670. # # def gr_C(Z, gamma, Ct):
  671. # # Ctp = Ct[np.ix_(Z, Z)]
  672. # # H_d = np.ones(len(Z)) * (gamma * gamma)
  673. # # temp = sp.linalg.inv(sp.sparse.diags(H_d, format='csr') + Ctp)
  674. # # return Ct - Ct[:, Z] @ temp @ Ct[Z, :]
  675. #
  676. # def gr_C(Z, gamma, d, v):
  677. # H_d = len(Z) *[1./gamma**2.]
  678. # vZ = v[Z,:]
  679. # post = sp.sparse.diags(d, format='csr') \
  680. # + vZ.T @ sp.sparse.diags(H_d, format='csr') @ vZ
  681. # return v @ sp.linalg.inv(post) @ v.T
  682. #
  683. # def gr_map(Z, y, gamma, d, v):
  684. # C = gr_C(Z, gamma, d, v)
  685. # return (C[:,Z] @ y)/(gamma * gamma)