You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

model_selection_precomputed.py 13 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. def model_selection_for_precomputed_kernel(datafile, estimator,
  2. param_grid_precomputed, param_grid,
  3. model_type, NUM_TRIALS=30,
  4. datafile_y=''):
  5. """Perform model selection, fitting and testing for precomputed kernels using nested cv. Print out neccessary data during the process then finally the results.
  6. Parameters
  7. ----------
  8. datafile : string
  9. Path of dataset file.
  10. estimator : function
  11. kernel function used to estimate. This function needs to return a gram matrix.
  12. param_grid_precomputed : dictionary
  13. Dictionary with names (string) of parameters used to calculate gram matrices as keys and lists of parameter settings to try as values. This enables searching over any sequence of parameter settings.
  14. param_grid : dictionary
  15. Dictionary with names (string) of parameters used as penelties as keys and lists of parameter settings to try as values. This enables searching over any sequence of parameter settings.
  16. model_type : string
  17. Typr of the problem, can be regression or classification.
  18. NUM_TRIALS : integer
  19. Number of random trials of outer cv loop. The default is 30.
  20. datafile_y : string
  21. Path of file storing y data. This parameter is optional depending on the given dataset file.
  22. Examples
  23. --------
  24. >>> import numpy as np
  25. >>> import sys
  26. >>> sys.path.insert(0, "../")
  27. >>> from pygraph.utils.model_selection_precomputed import model_selection_for_precomputed_kernel
  28. >>> from pygraph.kernels.weisfeilerLehmanKernel import weisfeilerlehmankernel
  29. >>>
  30. >>> datafile = '../../../../datasets/acyclic/Acyclic/dataset_bps.ds'
  31. >>> estimator = weisfeilerlehmankernel
  32. >>> param_grid_precomputed = {'height': [0,1,2,3,4,5,6,7,8,9,10], 'base_kernel': ['subtree']}
  33. >>> param_grid = {"alpha": np.logspace(-2, 2, num = 10, base = 10)}
  34. >>>
  35. >>> model_selection_for_precomputed_kernel(datafile, estimator, param_grid_precomputed, param_grid, 'regression')
  36. """
  37. import numpy as np
  38. from matplotlib import pyplot as plt
  39. from sklearn.kernel_ridge import KernelRidge
  40. from sklearn.svm import SVC
  41. from sklearn.metrics import accuracy_score, mean_squared_error
  42. from sklearn.model_selection import KFold, train_test_split, ParameterGrid
  43. import sys
  44. sys.path.insert(0, "../")
  45. from pygraph.utils.graphfiles import loadDataset
  46. from tqdm import tqdm
  47. # setup the model type
  48. model_type = model_type.lower()
  49. if model_type != 'regression' and model_type != 'classification':
  50. raise Exception(
  51. 'The model type is incorrect! Please choose from regression or classification.')
  52. print()
  53. print('--- This is a %s problem ---' % model_type)
  54. # Load the dataset
  55. print()
  56. print('1. Loading dataset from file...')
  57. dataset, y = loadDataset(datafile, filename_y=datafile_y)
  58. # Grid of parameters with a discrete number of values for each.
  59. param_list_precomputed = list(ParameterGrid(param_grid_precomputed))
  60. param_list = list(ParameterGrid(param_grid))
  61. # Arrays to store scores
  62. train_pref = np.zeros(
  63. (NUM_TRIALS, len(param_list_precomputed), len(param_list)))
  64. val_pref = np.zeros(
  65. (NUM_TRIALS, len(param_list_precomputed), len(param_list)))
  66. test_pref = np.zeros(
  67. (NUM_TRIALS, len(param_list_precomputed), len(param_list)))
  68. gram_matrices = [] # a list to store gram matrices for all param_grid_precomputed
  69. gram_matrix_time = [] # a list to store time to calculate gram matrices
  70. # calculate all gram matrices
  71. print()
  72. print('2. Calculating gram matrices. This could take a while...')
  73. for params_out in param_list_precomputed:
  74. Kmatrix, current_run_time = estimator(dataset, **params_out)
  75. print()
  76. print('gram matrix with parameters', params_out, 'is: ')
  77. print(Kmatrix)
  78. plt.matshow(Kmatrix)
  79. plt.colorbar()
  80. plt.show()
  81. # plt.savefig('../../notebooks/gram_matrix_figs/{}_{}'.format(estimator.__name__, params_out))
  82. gram_matrices.append(Kmatrix)
  83. gram_matrix_time.append(current_run_time)
  84. print()
  85. print('3. Fitting and predicting using nested cross validation. This could really take a while...')
  86. # Loop for each trial
  87. pbar = tqdm(total=NUM_TRIALS * len(param_list_precomputed) * len(param_list),
  88. desc='calculate performance', file=sys.stdout)
  89. for trial in range(NUM_TRIALS): # Test set level
  90. # loop for each outer param tuple
  91. for index_out, params_out in enumerate(param_list_precomputed):
  92. # split gram matrix and y to app and test sets.
  93. X_app, X_test, y_app, y_test = train_test_split(
  94. gram_matrices[index_out], y, test_size=0.1)
  95. split_index_app = [y.index(y_i) for y_i in y_app if y_i in y]
  96. split_index_test = [y.index(y_i) for y_i in y_test if y_i in y]
  97. X_app = X_app[:, split_index_app]
  98. X_test = X_test[:, split_index_app]
  99. y_app = np.array(y_app)
  100. y_test = np.array(y_test)
  101. # loop for each inner param tuple
  102. for index_in, params_in in enumerate(param_list):
  103. inner_cv = KFold(n_splits=10, shuffle=True, random_state=trial)
  104. current_train_perf = []
  105. current_valid_perf = []
  106. current_test_perf = []
  107. # For regression use the Kernel Ridge method
  108. if model_type == 'regression':
  109. KR = KernelRidge(kernel='precomputed', **params_in)
  110. # loop for each split on validation set level
  111. # validation set level
  112. for train_index, valid_index in inner_cv.split(X_app):
  113. KR.fit(X_app[train_index, :]
  114. [:, train_index], y_app[train_index])
  115. # predict on the train, validation and test set
  116. y_pred_train = KR.predict(
  117. X_app[train_index, :][:, train_index])
  118. y_pred_valid = KR.predict(
  119. X_app[valid_index, :][:, train_index])
  120. y_pred_test = KR.predict(X_test[:, train_index])
  121. # root mean squared errors
  122. current_train_perf.append(
  123. np.sqrt(mean_squared_error(y_app[train_index], y_pred_train)))
  124. current_valid_perf.append(
  125. np.sqrt(mean_squared_error(y_app[valid_index], y_pred_valid)))
  126. current_test_perf.append(
  127. np.sqrt(mean_squared_error(y_test, y_pred_test)))
  128. # For clcassification use SVM
  129. else:
  130. KR = SVC(kernel='precomputed', **params_in)
  131. # loop for each split on validation set level
  132. # validation set level
  133. for train_index, valid_index in inner_cv.split(X_app):
  134. KR.fit(X_app[train_index, :]
  135. [:, train_index], y_app[train_index])
  136. # predict on the train, validation and test set
  137. y_pred_train = KR.predict(
  138. X_app[train_index, :][:, train_index])
  139. y_pred_valid = KR.predict(
  140. X_app[valid_index, :][:, train_index])
  141. y_pred_test = KR.predict(X_test[:, train_index])
  142. # root mean squared errors
  143. current_train_perf.append(accuracy_score(
  144. y_app[train_index], y_pred_train))
  145. current_valid_perf.append(accuracy_score(
  146. y_app[valid_index], y_pred_valid))
  147. current_test_perf.append(
  148. accuracy_score(y_test, y_pred_test))
  149. # average performance on inner splits
  150. train_pref[trial][index_out][index_in] = np.mean(
  151. current_train_perf)
  152. val_pref[trial][index_out][index_in] = np.mean(
  153. current_valid_perf)
  154. test_pref[trial][index_out][index_in] = np.mean(
  155. current_test_perf)
  156. pbar.update(1)
  157. pbar.clear()
  158. print()
  159. print('4. Getting final performances...')
  160. # averages and confidences of performances on outer trials for each combination of parameters
  161. average_train_scores = np.mean(train_pref, axis=0)
  162. average_val_scores = np.mean(val_pref, axis=0)
  163. average_perf_scores = np.mean(test_pref, axis=0)
  164. # sample std is used here
  165. std_train_scores = np.std(train_pref, axis=0, ddof=1)
  166. std_val_scores = np.std(val_pref, axis=0, ddof=1)
  167. std_perf_scores = np.std(test_pref, axis=0, ddof=1)
  168. if model_type == 'regression':
  169. best_val_perf = np.amin(average_val_scores)
  170. else:
  171. best_val_perf = np.amax(average_val_scores)
  172. print()
  173. best_params_index = np.where(average_val_scores == best_val_perf)
  174. best_params_out = [param_list_precomputed[i] for i in best_params_index[0]]
  175. best_params_in = [param_list[i] for i in best_params_index[1]]
  176. # print('best_params_index: ', best_params_index)
  177. print('best_params_out: ', best_params_out)
  178. print('best_params_in: ', best_params_in)
  179. print()
  180. print('best_val_perf: ', best_val_perf)
  181. # below: only find one performance; muitiple pref might exist
  182. best_val_std = std_val_scores[best_params_index[0]
  183. [0]][best_params_index[1][0]]
  184. print('best_val_std: ', best_val_std)
  185. final_performance = average_perf_scores[best_params_index[0]
  186. [0]][best_params_index[1][0]]
  187. final_confidence = std_perf_scores[best_params_index[0]
  188. [0]][best_params_index[1][0]]
  189. print('final_performance: ', final_performance)
  190. print('final_confidence: ', final_confidence)
  191. train_performance = average_train_scores[best_params_index[0]
  192. [0]][best_params_index[1][0]]
  193. train_std = std_train_scores[best_params_index[0]
  194. [0]][best_params_index[1][0]]
  195. print('train_performance: ', train_performance)
  196. print('train_std: ', train_std)
  197. print()
  198. average_gram_matrix_time = np.mean(gram_matrix_time)
  199. std_gram_matrix_time = np.std(gram_matrix_time, ddof=1)
  200. best_gram_matrix_time = gram_matrix_time[best_params_index[0][0]]
  201. print('time to calculate gram matrix with different hyperpapams: {:.2f}±{:.2f}'
  202. .format(average_gram_matrix_time, std_gram_matrix_time))
  203. print('time to calculate best gram matrix: ', best_gram_matrix_time, 's')
  204. # print out as table.
  205. from collections import OrderedDict
  206. from tabulate import tabulate
  207. table_dict = {}
  208. if model_type == 'regression':
  209. for param_in in param_list:
  210. param_in['alpha'] = '{:.2e}'.format(param_in['alpha'])
  211. else:
  212. for param_in in param_list:
  213. param_in['C'] = '{:.2e}'.format(param_in['C'])
  214. table_dict['params'] = [{**param_out, **param_in}
  215. for param_in in param_list for param_out in param_list_precomputed]
  216. table_dict['gram_matrix_time'] = ['{:.2f}'.format(gram_matrix_time[index_out])
  217. for param_in in param_list for index_out, _ in enumerate(param_list_precomputed)]
  218. table_dict['valid_perf'] = ['{:.2f}±{:.2f}'.format(average_val_scores[index_out][index_in], std_val_scores[index_out][index_in])
  219. for index_in, _ in enumerate(param_list) for index_out, _ in enumerate(param_list_precomputed)]
  220. table_dict['test_perf'] = ['{:.2f}±{:.2f}'.format(average_perf_scores[index_out][index_in], std_perf_scores[index_out][index_in])
  221. for index_in, _ in enumerate(param_list) for index_out, _ in enumerate(param_list_precomputed)]
  222. table_dict['train_perf'] = ['{:.2f}±{:.2f}'.format(average_train_scores[index_out][index_in], std_train_scores[index_out][index_in])
  223. for index_in, _ in enumerate(param_list) for index_out, _ in enumerate(param_list_precomputed)]
  224. keyorder = ['params', 'train_perf', 'valid_perf',
  225. 'test_perf', 'gram_matrix_time']
  226. print()
  227. print(tabulate(OrderedDict(sorted(table_dict.items(),
  228. key=lambda i: keyorder.index(i[0]))), headers='keys'))

A Python package for graph kernels, graph edit distances and graph pre-image problem.