OSCR

Rule-guided Skip-GCN in neural latent information diffusion network for social recommendation.

Code ↔ Paper

The paper beside its authors' code: matches between them have not been computed for this paper yet.

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Python · 646 lines · 34 KB · no license

  1. #-*- coding: utf-8 -*-
  2. from __future__ import division
  3. from cmath import tau
  4. from collections import defaultdict
  5. import numpy as np
  6. from time import time
  7. import random
  8. import tensorflow as tf
  9. tau_uiu = 0.2
  10. tau_ii = 0.3 #### yelp: 0.3 flickr: 0.7
  11. class DataModule():
  12. def __init__(self, conf, filename):
  13. self.conf = conf
  14. self.data_dict = {}
  15. self.terminal_flag = 1
  16. self.filename = filename
  17. self.index = 0
  18. ####### Initalize Procedures #######
  19. def prepareModelSupplement(self, model):
  20. data_dict = {}
  21. if 'CONSUMED_ITEMS_SPARSE_MATRIX' in model.supply_set:
  22. self.generateConsumedItemsSparseMatrix()
  23. #self.arrangePositiveData()
  24. data_dict['CONSUMED_ITEMS_INDICES_INPUT'] = self.consumed_items_indices_list
  25. data_dict['CONSUMED_ITEMS_VALUES_INPUT'] = self.consumed_items_values_list
  26. data_dict['CONSUMED_ITEMS_VALUES_WEIGHT_AVG_INPUT'] = self.consumed_items_values_weight_avg_list
  27. data_dict['CONSUMED_ITEMS_NUM_INPUT'] = self.consumed_item_num_list
  28. data_dict['CONSUMED_ITEMS_NUM_DICT_INPUT'] = self.user_item_num_dict
  29. # data_dict['USER_ITEM_SPARSITY_DICT'] = self.user_item_sparsity_dict ##### 用不到!!!!!!
  30. if 'SOCIAL_NEIGHBORS_SPARSE_MATRIX' in model.supply_set:
  31. self.readSocialNeighbors()
  32. self.generateSocialNeighborsSparseMatrix()
  33. data_dict['SOCIAL_NEIGHBORS_INDICES_INPUT'] = self.social_neighbors_indices_list
  34. data_dict['SOCIAL_NEIGHBORS_VALUES_INPUT'] = self.social_neighbors_values_list
  35. data_dict['SOCIAL_NEIGHBORS_VALUES_WEIGHT_AVG_INPUT'] = self.social_neighbors_values_weight_avg_list
  36. data_dict['SOCIAL_NEIGHBORS_NUM_INPUT'] = self.social_neighbor_num_list
  37. data_dict['SOCIAL_NEIGHBORS_NUM_DICT_INPUT'] = self.social_neighbors_num_dict
  38. # data_dict['USER_USER_SPARSITY_DICT']= self.user_user_sparsity_dict #### 用不到!!!!!!
  39. ##################################################################
  40. ##################################################################
  41. ##################################################################
  42. data_dict['user_user_uiu_indices_input'] = self.user_user_uiu_indices_list
  43. data_dict['user_user_uiu_values_input'] = self.user_user_uiu_values_list
  44. data_dict['user_user_uiu_values_weight_avg_input'] = self.user_user_uiu_values_weight_avg_list
  45. data_dict['user_user_u0u_indices_input'] = self.user_user_u0u_indices_list
  46. data_dict['user_user_u0u_values_input'] = self.user_user_u0u_values_list
  47. data_dict['user_user_u0u_values_weight_avg_input'] = self.user_user_u0u_values_weight_avg_list
  48. if 'ITEM_CUSTOMER_SPARSE_MATRIX' in model.supply_set:
  49. self.generateConsumedItemsSparseMatrixForItemUser()
  50. data_dict['ITEM_CUSTOMER_INDICES_INPUT'] = self.item_customer_indices_list
  51. data_dict['ITEM_CUSTOMER_VALUES_INPUT'] = self.item_customer_values_list
  52. data_dict['ITEM_CUSTOMER_VALUES_WEIGHT_AVG_INPUT'] = self.item_customer_values_weight_avg_list
  53. data_dict['ITEM_CUSTOMER_NUM_INPUT'] = self.item_customer_num_list
  54. data_dict['ITEM_USER_NUM_DICT_INPUT'] = self.item_user_num_dict
  55. ##################################################################
  56. ##################################################################
  57. ##################################################################
  58. data_dict['item_item_iui_indices_input'] = self.item_item_iui_indices_list
  59. data_dict['item_item_iui_values_input'] = self.item_item_iui_values_list
  60. data_dict['item_item_iui_values_weight_avg_input'] = self.item_item_iui_values_weight_avg_list
  61. data_dict['item_item_iui_num_input'] = self.item_item_iui_num_list
  62. data_dict['item_item_iui_num_dict_input'] = self.item_item_iui_num_dict
  63. return data_dict
  64. def initializeRankingTrain(self):
  65. self.readData()
  66. self.arrangePositiveData()
  67. self.arrangePositiveDataForItemUser()
  68. self.generateTrainNegative()
  69. def initializeRankingVT(self):
  70. self.readData()
  71. self.arrangePositiveData()
  72. self.arrangePositiveDataForItemUser()
  73. self.generateTrainNegative()
  74. def initalizeRankingEva(self):
  75. self.readData()
  76. self.getEvaPositiveBatch()
  77. self.generateEvaNegative()
  78. def linkedMap(self):
  79. self.data_dict['USER_LIST'] = self.user_list
  80. self.data_dict['ITEM_LIST'] = self.item_list
  81. self.data_dict['LABEL_LIST'] = self.labels_list
  82. def linkedRankingEvaMap(self):
  83. self.data_dict['EVA_USER_LIST'] = self.eva_user_list
  84. self.data_dict['EVA_ITEM_LIST'] = self.eva_item_list
  85. ####### Data Loading #######
  86. def readData(self):
  87. f = open(self.filename)
  88. total_user_list = set()
  89. hash_data = defaultdict(int)
  90. for _, line in enumerate(f):
  91. arr = line.split("\t")
  92. hash_data[(int(arr[0]), int(arr[1]))] = 1
  93. total_user_list.add(int(arr[0]))
  94. self.total_user_list = list(total_user_list) ####
  95. self.hash_data = hash_data #### hash_data[(userID, itemID)] = 1
  96. # def arrangePositiveData(self): ####
  97. # positive_data = defaultdict(set)
  98. # user_item_num_dict = defaultdict(set)
  99. # total_data = set()
  100. # hash_data = self.hash_data
  101. # for (u, i) in hash_data:
  102. # total_data.add((u, i))
  103. # positive_data[u].add(i)
  104. # user_list = sorted(list(positive_data.keys()))
  105. # for u in range(self.conf.num_users):
  106. # user_item_num_dict[u] = len(positive_data[u]) + 1
  107. # self.positive_data = positive_data #### positive_data
  108. # self.user_item_num_dict = user_item_num_dict #### 一个user
  109. # self.user_item_num_for_sparsity_dict = user_item_num_for_sparsity_dict
  110. # self.total_data = len(total_data) ####(user-item)pair
  111. # def Sparsity_analysis_for_user_item_network(self): #### 用不到!!!!!!!!!!!!!!!
  112. # hash_data_for_user_item = self.hash_data
  113. # sparisty_user_item_dict = {}
  114. def arrangePositiveDataForItemUser(self):
  115. positive_data_for_item_user = defaultdict(set)
  116. item_user_num_dict = defaultdict(int)
  117. total_data_for_item_user = set()
  118. hash_data_for_item_user = self.hash_data
  119. for (u, i) in hash_data_for_item_user:
  120. total_data_for_item_user.add((i, u))
  121. positive_data_for_item_user[i].add(u)
  122. # item_list = sorted(list(positive_data_for_item_user.keys()))
  123. for i in range(self.conf.num_items):
  124. item_user_num_dict[i] = len(positive_data_for_item_user[i]) + 1 #### 一个user
  125. self.item_user_num_dict = item_user_num_dict
  126. self.positive_data_for_item_user = positive_data_for_item_user #### positive_data_for _item_user
  127. self.total_data_for_item_user = len(total_data_for_item_user) #### (item-user)pair
  128. # ----------------------
  129. # This function designes for generating train/val/test negative
  130. def generateTrainNegative(self):
  131. num_items = self.conf.num_items
  132. num_negatives = self.conf.num_negatives
  133. negative_data = defaultdict(set)
  134. total_data = set()
  135. hash_data = self.hash_data #### hash_data[(userID, itemID)] = 1
  136. for (u, i) in hash_data:
  137. total_data.add((u, i))
  138. for _ in range(num_negatives): ####
  139. j = np.random.randint(num_items) ####
  140. while (u, j) in hash_data:
  141. j = np.random.randint(num_items)
  142. negative_data[u].add(j)
  143. total_data.add((u, j)) #### ----
  144. self.negative_data = negative_data
  145. self.terminal_flag = 1 ####
  146. # ----------------------
  147. # This function designes for val/test set, compute loss #### 为validation/test
  148. def getVTRankingOneBatch(self):
  149. positive_data = self.positive_data
  150. negative_data = self.negative_data
  151. total_user_list = self.total_user_list
  152. user_list = []
  153. item_list = []
  154. labels_list = []
  155. for u in total_user_list:
  156. user_list.extend([u] * len(positive_data[u]))
  157. item_list.extend(positive_data[u])
  158. labels_list.extend([1] * len(positive_data[u])) ####
  159. user_list.extend([u] * len(negative_data[u]))
  160. item_list.extend(negative_data[u])
  161. labels_list.extend([0] * len(negative_data[u])) ####
  162. self.user_list = np.reshape(user_list, [-1, 1]) ####
  163. self.item_list = np.reshape(item_list, [-1, 1])
  164. self.labels_list = np.reshape(labels_list, [-1, 1])
  165. # ----------------------
  166. # This function designes for the training process
  167. def getTrainRankingBatch(self): #### 为train
  168. positive_data = self.positive_data
  169. negative_data = self.negative_data
  170. total_user_list = self.total_user_list
  171. index = self.index
  172. batch_size = self.conf.training_batch_size
  173. user_list, item_list, labels_list = [], [], []
  174. if index + batch_size < len(total_user_list):
  175. target_user_list = total_user_list[index:index+batch_size]
  176. self.index = index + batch_size
  177. else:
  178. target_user_list = total_user_list[index:len(total_user_list)]
  179. self.index = 0 ####
  180. self.terminal_flag = 0
  181. for u in target_user_list:
  182. user_list.extend([u] * len(positive_data[u]))
  183. item_list.extend(list(positive_data[u]))
  184. labels_list.extend([1] * len(positive_data[u])) ####
  185. user_list.extend([u] * len(negative_data[u]))
  186. item_list.extend(list(negative_data[u]))
  187. labels_list.extend([0] * len(negative_data[u])) ####
  188. self.user_list = np.reshape(user_list, [-1, 1]) ####
  189. self.item_list = np.reshape(item_list, [-1, 1])
  190. self.labels_list = np.reshape(labels_list, [-1, 1])
  191. # ----------------------
  192. # This function is designed for the positive data
  193. def getEvaPositiveBatch(self):
  194. hash_data = self.hash_data
  195. user_list = []
  196. item_list = []
  197. index_dict = defaultdict(list)
  198. index = 0 ####
  199. for (u, i) in hash_data:
  200. user_list.append(u)
  201. item_list.append(i)
  202. index_dict[u].append(index)
  203. index = index + 1
  204. self.eva_user_list = np.reshape(user_list, [-1, 1])
  205. self.eva_item_list = np.reshape(item_list, [-1, 1])
  206. self.eva_index_dict = index_dict
  207. # ----------------------
  208. #This function is designed for generating negative data
  209. def generateEvaNegative(self):
  210. hash_data = self.hash_data
  211. total_user_list = self.total_user_list
  212. num_evaluate = self.conf.num_evaluate
  213. num_items = self.conf.num_items
  214. eva_negative_data = defaultdict(list) ####
  215. for u in total_user_list:
  216. for _ in range(num_evaluate): ####
  217. j = np.random.randint(num_items)
  218. while (u, j) in hash_data:
  219. j = np.random.randint(num_items)
  220. eva_negative_data[u].append(j)
  221. self.eva_negative_data = eva_negative_data
  222. # ----------------------
  223. #This function designs for generating negative batch in rating evaluation,
  224. def getEvaRankingBatch(self):
  225. batch_size = self.conf.evaluate_batch_size
  226. num_evaluate = self.conf.num_evaluate
  227. eva_negative_data = self.eva_negative_data
  228. total_user_list = self.total_user_list
  229. index = self.index
  230. terminal_flag = 1
  231. total_users = len(total_user_list)
  232. user_list = []
  233. item_list = []
  234. if index + batch_size < total_users: ####
  235. batch_user_list = total_user_list[index:index+batch_size]
  236. self.index = index + batch_size
  237. else:
  238. terminal_flag = 0
  239. batch_user_list = total_user_list[index:total_users]
  240. self.index = 0
  241. for u in batch_user_list:
  242. user_list.extend([u]*num_evaluate) ####
  243. item_list.extend(eva_negative_data[u])
  244. self.eva_user_list = np.reshape(user_list, [-1, 1]) ####
  245. self.eva_item_list = np.reshape(item_list, [-1, 1])
  246. return batch_user_list, terminal_flag
  247. # ----------------------
  248. # Read social network information
  249. def readSocialNeighbors(self, friends_flag = 1): ####
  250. social_neighbors = defaultdict(set)
  251. social_neighbors_num_dict = defaultdict(int)
  252. links_file = open(self.conf.links_filename) ####
  253. for _, line in enumerate(links_file):
  254. tmp = line.split('\t')
  255. u1, u2 = int(tmp[0]), int(tmp[1])
  256. social_neighbors[u1].add(u2)
  257. if friends_flag == 1: ####
  258. social_neighbors[u2].add(u1) #### 无向
  259. # user_list = sorted(list(social_neighbors.keys())) #### ----
  260. for u in range(self.conf.num_users):
  261. social_neighbors_num_dict[u] = len(social_neighbors[u]) + 1 ##### 每个user
  262. self.social_neighbors_num_dict = social_neighbors_num_dict
  263. self.social_neighbors = social_neighbors
  264. def arrangePositiveData(self): ####
  265. positive_data = defaultdict(set)
  266. user_item_num_dict = defaultdict(int)
  267. total_data = set()
  268. hash_data = self.hash_data
  269. ############################################################################
  270. ############################################################################
  271. ############################################################################
  272. item_users = defaultdict(set)
  273. for (u, i) in hash_data:
  274. total_data.add((u, i))
  275. positive_data[u].add(i)
  276. item_users[i].add(u)
  277. user_list = sorted(list(positive_data.keys()))
  278. for u in range(self.conf.num_users):
  279. user_item_num_dict[u] = len(positive_data[u]) + 1
  280. self.positive_data = positive_data
  281. self.user_item_num_dict = user_item_num_dict #### 89
  282. self.total_data = len(total_data)
  283. #############################################################################
  284. #############################################################################
  285. #############################################################################
  286. self.user_items = self.positive_data
  287. self.item_users = item_users
  288. # ----------------------
  289. #Generate Social Neighbors Sparse Matrix Indices and Values
  290. def generateSocialNeighborsSparseMatrix(self):
  291. social_neighbors = self.social_neighbors ####
  292. social_neighbors_num_dict = self.social_neighbors_num_dict #weight avg ####
  293. social_neighbors_indices_list = []
  294. social_neighbors_values_list = []
  295. social_neighbors_values_weight_avg_list = []
  296. social_neighbor_num_list = []
  297. social_neighbors_dict = defaultdict(list)
  298. # user_user_num_for_sparsity_dict = defaultdict(set) ####
  299. # user_user_sparsity_dict = {}
  300. # user_user_sparsity_dict['0-4'] = [] #### 0 <= x < 4 (左闭右开)
  301. # user_user_sparsity_dict['4-8'] = []
  302. # user_user_sparsity_dict['8-16'] = []
  303. # user_user_sparsity_dict['16-32'] = []
  304. # user_user_sparsity_dict['32-64'] = []
  305. # user_user_sparsity_dict['64-'] = []
  306. # for u in range(self.conf.num_users):
  307. # user_user_num_for_sparsity_dict[u] = len(social_neighbors[u]) ####
  308. for u in social_neighbors:
  309. social_neighbors_dict[u] = sorted(social_neighbors[u])
  310. user_list = sorted(list(social_neighbors.keys()))
  311. #node att ####
  312. for user in range(self.conf.num_users):
  313. if user in social_neighbors_dict:
  314. social_neighbor_num_list.append(len(social_neighbors_dict[user])) ####
  315. else:
  316. social_neighbor_num_list.append(1) ####
  317. print("{} 没有trust的朋友!!!!!!!!!!!".format(user)) ####
  318. for user in user_list:
  319. for friend in social_neighbors_dict[user]:
  320. social_neighbors_indices_list.append([user, friend])
  321. social_neighbors_values_list.append(1.0/len(social_neighbors_dict[user]))
  322. social_neighbors_values_weight_avg_list.append(1.0 / ( np.sqrt(social_neighbors_num_dict[user]) * np.sqrt(social_neighbors_num_dict[friend]) ) ) #weight avg
  323. # for u in range(self.conf.num_users):
  324. # cur_user_neighbors_num = user_user_num_for_sparsity_dict[u] ####
  325. # if( (cur_user_neighbors_num >=0) & (cur_user_neighbors_num<4) ):
  326. # user_user_sparsity_dict['0-4'].append(u)
  327. # elif( (cur_user_neighbors_num >=4) & (cur_user_neighbors_num<8) ):
  328. # user_user_sparsity_dict['4-8'].append(u)
  329. # elif( (cur_user_neighbors_num >=8) & (cur_user_neighbors_num<16) ):
  330. # user_user_sparsity_dict['8-16'].append(u)
  331. # elif( (cur_user_neighbors_num >=16) & (cur_user_neighbors_num<32) ):
  332. # user_user_sparsity_dict['16-32'].append(u)
  333. # elif( (cur_user_neighbors_num >=32) & (cur_user_neighbors_num<64) ):
  334. # user_user_sparsity_dict['32-64'].append(u)
  335. # elif( cur_user_neighbors_num >=64):
  336. # user_user_sparsity_dict['64-'].append(u)
  337. # self.user_user_sparsity_dict = user_user_sparsity_dict ####
  338. self.social_neighbors_indices_list = np.array(social_neighbors_indices_list).astype(np.int64)
  339. self.social_neighbors_values_list = np.array(social_neighbors_values_list).astype(np.float32)
  340. self.social_neighbors_values_weight_avg_list = np.array(social_neighbors_values_weight_avg_list).astype(np.float32) # weight avg
  341. self.social_neighbor_num_list = np.array(social_neighbor_num_list).astype(np.int64)
  342. #self.social_neighbors_values_list = tf.Variable(tf.random_normal([len(self.social_neighbors_indices_list)], stddev=0.01)) ####
  343. ################################################################################################
  344. ################################################################################################
  345. ################################################################################################
  346. #### u1与u2之间有共同的item
  347. user_user_uiu_indices_list = []
  348. user_user_uiu_indeces_visited = set() ####
  349. user_user_uiu_values_list = []
  350. user_user_uiu_values_weight_avg_list = []
  351. #### u1与u2之间没有共同的item
  352. user_user_u0u_indices_list = []
  353. user_user_u0u_indices_visited = set()
  354. user_user_u0u_values_list = []
  355. user_user_u0u_values_weight_avg_list = []
  356. print('此时的user-user阈值是{}'.format(tau_uiu))
  357. ID = 0
  358. for u1 in user_list:
  359. u1_items_set = set(self.user_items[u1])
  360. # print(u1_items_set)
  361. for u2 in social_neighbors_dict[u1]:
  362. u1_u2_common_item = set() ####
  363. u2_items_set = set(self.user_items[u2])
  364. for i2 in u2_items_set:
  365. if i2 in u1_items_set:
  366. u1_u2_common_item.add(i2)
  367. # print(have_common_item)
  368. if len(u1_u2_common_item) > 0:
  369. if (u1, u2) in user_user_uiu_indeces_visited:
  370. continue ####
  371. user_user_uiu_indices_list.append([u1, u2])
  372. user_user_uiu_indeces_visited.add((u1, u2)) ####
  373. user_user_uiu_values_list.append(1.0/len(social_neighbors_dict[u1]))
  374. user_user_uiu_values_weight_avg_list.append(1.0 / ( np.sqrt(social_neighbors_num_dict[u1]) * np.sqrt(social_neighbors_num_dict[u2]) ) ) #weight avg
  375. ###################################################################################################
  376. ###################################################################################################
  377. ###################################################################################################
  378. if len(u1_u2_common_item) / len(u1_items_set) >= tau_uiu and len(u1_u2_common_item) / len(u2_items_set) >= tau_uiu:
  379. for u3 in social_neighbors_dict[u2]:
  380. if u1 == u3 or u1 == u2 or u2 == u3:
  381. continue
  382. for i3 in self.user_items[u3]:
  383. if i3 in u1_u2_common_item:
  384. if (u1, u3) in user_user_uiu_indeces_visited:
  385. continue ####
  386. user_user_uiu_indices_list.append([u1, u3])
  387. user_user_uiu_indeces_visited.add((u1, u3)) ####
  388. user_user_uiu_values_list.append(1.0/len(social_neighbors_dict[u1]))
  389. user_user_uiu_values_weight_avg_list.append(1.0 / ( np.sqrt(social_neighbors_num_dict[u1]) * np.sqrt(social_neighbors_num_dict[u3]) ) ) #weight avg
  390. # print(ID)
  391. ID += 1
  392. # for u4 in social_neighbors_dict[u3]:
  393. # if len(set([u1, u2, u3, u4])) != 4:
  394. # continue
  395. # for i4 in self.user_items[u4]:
  396. # if i4 in u1_items_set:
  397. # user_user_uiu_indices_list.append([u1, u4])
  398. # user_user_uiu_values_list.append(1.0/len(social_neighbors_dict[u1]))
  399. # user_user_uiu_values_weight_avg_list.append(1.0 / ( np.sqrt(social_neighbors_num_dict[u1]) * np.sqrt(social_neighbors_num_dict[u4]) ) ) #weight avg
  400. # break
  401. break
  402. else:
  403. if (u1, u2) in user_user_u0u_indices_visited:
  404. continue ####
  405. user_user_u0u_indices_list.append([u1, u2])
  406. user_user_u0u_indices_visited.add((u1, u2)) ####
  407. user_user_u0u_values_list.append(1.0/len(social_neighbors_dict[u1]))
  408. user_user_u0u_values_weight_avg_list.append(1.0 / ( np.sqrt(social_neighbors_num_dict[u1]) * np.sqrt(social_neighbors_num_dict[u2]) ) ) #weight avg
  409. print(ID)
  410. self.user_user_uiu_indices_list = np.array(user_user_uiu_indices_list).astype(np.int64)
  411. self.user_user_uiu_values_list = np.array(user_user_uiu_values_list).astype(np.float32)
  412. self.user_user_uiu_values_weight_avg_list = np.array(user_user_uiu_values_weight_avg_list).astype(np.float32)
  413. self.user_user_u0u_indices_list = np.array(user_user_u0u_indices_list).astype(np.int64)
  414. self.user_user_u0u_values_list = np.array(user_user_u0u_values_list).astype(np.float32)
  415. self.user_user_u0u_values_weight_avg_list = np.array(user_user_u0u_values_weight_avg_list).astype(np.float32)
  416. # ----------------------
  417. #Generate Consumed Items Sparse Matrix Indices and Values
  418. def generateConsumedItemsSparseMatrix(self):
  419. positive_data = self.positive_data
  420. consumed_items_indices_list = []
  421. consumed_items_values_list = []
  422. consumed_items_values_weight_avg_list = []
  423. consumed_item_num_list = []
  424. consumed_items_dict = defaultdict(list)
  425. # user_item_num_for_sparsity_dict = defaultdict(set) #####
  426. # user_item_sparsity_dict = {}
  427. # user_item_sparsity_dict['0-4'] = [] ####
  428. # user_item_sparsity_dict['4-8'] = []
  429. # user_item_sparsity_dict['8-16'] = []
  430. # user_item_sparsity_dict['16-32'] = []
  431. # user_item_sparsity_dict['32-64'] = []
  432. # user_item_sparsity_dict['64-'] = []
  433. consumed_items_num_dict = self.user_item_num_dict #weight avg
  434. #social_neighbors_num_dict = self.social_neighbors_num_dict #weight avg
  435. item_user_num_dict = self.item_user_num_dict #weight avg
  436. for u in positive_data:
  437. consumed_items_dict[u] = sorted(positive_data[u]) ####
  438. user_list = sorted(list(positive_data.keys())) #### userID
  439. # for u in range(self.conf.num_users):
  440. # user_item_num_for_sparsity_dict[u] = len(positive_data[u]) ####
  441. for user in range(self.conf.num_users):
  442. if user in consumed_items_dict:
  443. consumed_item_num_list.append(len(consumed_items_dict[user])) ####
  444. else:
  445. consumed_item_num_list.append(1) ####
  446. for u in user_list:
  447. for i in consumed_items_dict[u]:
  448. consumed_items_indices_list.append([u, i])
  449. consumed_items_values_list.append(1.0/len(consumed_items_dict[u]))
  450. consumed_items_values_weight_avg_list.append(1.0/( np.sqrt(consumed_items_num_dict[u]) * np.sqrt(item_user_num_dict[i]) )) #weight avg
  451. # for u in range(self.conf.num_users): ####
  452. # cur_user_consumed_item_num = user_item_num_for_sparsity_dict[u]
  453. # if( (cur_user_consumed_item_num >=0) & (cur_user_consumed_item_num<4) ):
  454. # user_item_sparsity_dict['0-4'].append(u)
  455. # elif( (cur_user_consumed_item_num >=4) & (cur_user_consumed_item_num<8) ):
  456. # user_item_sparsity_dict['4-8'].append(u)
  457. # elif( (cur_user_consumed_item_num >=8) & (cur_user_consumed_item_num<16) ):
  458. # user_item_sparsity_dict['8-16'].append(u)
  459. # elif( (cur_user_consumed_item_num >=16) & (cur_user_consumed_item_num<32) ):
  460. # user_item_sparsity_dict['16-32'].append(u)
  461. # elif( (cur_user_consumed_item_num >=32) & (cur_user_consumed_item_num<64) ):
  462. # user_item_sparsity_dict['32-64'].append(u)
  463. # elif( cur_user_consumed_item_num >=64):
  464. # user_item_sparsity_dict['64-'].append(u)
  465. # self.user_item_sparsity_dict = user_item_sparsity_dict ####
  466. self.consumed_items_indices_list = np.array(consumed_items_indices_list).astype(np.int64)
  467. self.consumed_items_values_list = np.array(consumed_items_values_list).astype(np.float32)
  468. self.consumed_items_values_weight_avg_list = np.array(consumed_items_values_weight_avg_list).astype(np.float32) #weight avg
  469. self.consumed_item_num_list = np.array(consumed_item_num_list).astype(np.int64)
  470. def generateConsumedItemsSparseMatrixForItemUser(self):
  471. positive_data_for_item_user = self.positive_data_for_item_user
  472. item_customer_indices_list = []
  473. item_customer_values_list = []
  474. item_customer_values_weight_avg_list = []
  475. item_customer_num_list = []
  476. item_customer_dict = defaultdict(list)
  477. consumed_items_num_dict = self.user_item_num_dict #weight avg ####
  478. #social_neighbors_num_dict = self.social_neighbors_num_dict #weight avg
  479. item_user_num_dict = self.item_user_num_dict #weight avg ####
  480. for i in positive_data_for_item_user: ####
  481. item_customer_dict[i] = sorted(positive_data_for_item_user[i])
  482. item_list = sorted(list(positive_data_for_item_user.keys()))
  483. for item in range(self.conf.num_items):
  484. if item in item_customer_dict:
  485. item_customer_num_list.append(len(item_customer_dict[item])) ####
  486. else:
  487. item_customer_num_list.append(1) ####
  488. for i in item_list:
  489. for u in item_customer_dict[i]:
  490. item_customer_indices_list.append([i, u])
  491. item_customer_values_list.append(1.0/len(item_customer_dict[i])) ####
  492. item_customer_values_weight_avg_list.append(1.0/( np.sqrt(consumed_items_num_dict[u]) * np.sqrt(item_user_num_dict[i]) )) #
  493. self.item_customer_indices_list = np.array(item_customer_indices_list).astype(np.int64)
  494. self.item_customer_values_list = np.array(item_customer_values_list).astype(np.float32)
  495. self.item_customer_num_list = np.array(item_customer_num_list).astype(np.int64)
  496. self.item_customer_values_weight_avg_list = np.array(item_customer_values_weight_avg_list).astype(np.float32)
  497. ################################################################################################
  498. ################################################################################################
  499. ################################################################################################
  500. #### u1与u2之间有共同的item
  501. item_item_iui_indices_list = []
  502. item_item_iui_values_list = []
  503. item_item_iui_num_list = []
  504. item_item_iui_values_weight_avg_list = []
  505. self.item_items = defaultdict(set)
  506. self.item_item_iui_num_dict = defaultdict(int)
  507. ######## item-item
  508. print('此时item-item阈值是{}'.format(tau_ii))
  509. ID = 0
  510. for i1 in item_list:
  511. i1_users_set = set(self.item_users[i1])
  512. for u1 in i1_users_set:
  513. for i2 in self.user_items[u1]:
  514. if i1 == i2:
  515. continue
  516. i2_users_set = set(self.item_users[i2])
  517. common_user_set = set()
  518. for u2 in i2_users_set:
  519. if u2 in i1_users_set:
  520. common_user_set.add(u2)
  521. if len(common_user_set) / len(i1_users_set) >= tau_ii and len(common_user_set) / len(i2_users_set) >= tau_ii:
  522. # if len(common_user_set) / len(i1_users_set) >= 0.5 and len(common_user_set) / len(i2_users_set) >= 0.5:
  523. # print(ID) ##########################################################
  524. ID += 1
  525. self.item_items[i1].add(i2)
  526. print(ID)
  527. for i1 in range(self.conf.num_items):
  528. if i1 in self.item_items:
  529. self.item_item_iui_num_dict[i1] = len(self.item_items[i1]) + 1
  530. else:
  531. self.item_item_iui_num_dict[i1] = 1
  532. for i1 in range(self.conf.num_items):
  533. if i1 in self.item_items:
  534. item_item_iui_num_list.append(len(self.item_items[i1]))
  535. else:
  536. item_item_iui_num_list.append(1)
  537. for i1 in self.item_items.keys():
  538. for i2 in self.item_items[i1]:
  539. item_item_iui_indices_list.append([i1, i2])
  540. item_item_iui_values_list.append(1.0 / len(self.item_items[i1]))
  541. item_item_iui_values_weight_avg_list.append(1.0 / ( np.sqrt(self.item_item_iui_num_dict[i1]) * np.sqrt(self.item_item_iui_num_dict[i2]) ) ) #weight avg
  542. self.item_item_iui_indices_list = np.array(item_item_iui_indices_list).astype(np.int64)
  543. self.item_item_iui_values_list = np.array(item_item_iui_values_list).astype(np.float32)
  544. self.item_item_iui_num_list = np.array(item_item_iui_num_list).astype(np.int64)
  545. self.item_item_iui_values_weight_avg_list = np.array(item_item_iui_values_weight_avg_list).astype(np.float32)

DataModule.py at commit 7bf4320, no license · at the source

Overview

Authors: Rui Cao1, Jindong Li1, He Kong1, Qi Wang1,2, Yi Chang1,2,3
  1. School of Artificial Intelligence, Jilin University, Changchun, 130012 China
  2. Engineering Research Center of Knowledge-Driven Human-Machine Intelligence, Ministry of Education, Changchun, China
  3. International Center of Future Science, Jilin University, Changchun, China
Institutions: Jilin University (China)
Journal: Scientific reports, volume 16, issue 1, article 25452
Dates: received 18 April 2024; accepted 14 April 2026; published online 4 June 2026
Type: Research article · Language: English
License: CC BY-NC-ND
Identifiers: DOI 10.1038/s41598-026-49379-1 · PMID 42243206 · PMCID PMC13473486 · OpenAlex W7163566133
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: methods / tools (subfield)
Keywords: Computer science, Information technology
Topic: Recommender Systems and Techniques (Information Systems, Computer Science), according to OpenAlex
Funding: National Natural Science Foundation of China (No. 62206107)
Citations: not cited yet (Europe PMC); 57 references in the paper

Abstract

The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.

Repository

Its files are read in the Code ↔ Paper reader above.

CAorvi/DiffRSG

License: none: the authors keep all their rights
State: the link answers, verified on 27 September 2026
Evidence: files inventoried
Commit: 7bf4320502cab3b875f9f1940e2bbea37a3079a9, 10 August 2025
Languages: Python (8)
Size: 33 files, 8 scripts
Software Heritage: not archived
Found in: “Data availability”
Holds: README, continuous integration
Not found: license file, CITATION.cff, environment file, tests, documentation
Tools: NumPy (4 files), TensorFlow (3 files)
Availability: 1 check, the latest on 27 September 2026: the link answers
  • 27 September 2026: the link answers
9 files

The paper's code and data availability statement is in the Data section.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 8 scripts, each with its path and the digest of its content;
  • no match between paragraphs and code yet;
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Code and data availability statement

The paper has a code and data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

Read it in the paper: doi.org/10.1038/s41598-026-49379-1.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 27 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 5 authors, 2 keywords, 1 funder, 54 references.

Cite

This paper

Cao, R., Li, J., Kong, H., Wang, Q., & Chang, Y. (2026). Rule-guided Skip-GCN in neural latent information diffusion network for social recommendation. Scientific reports, 16(1), 25452. https://doi.org/10.1038/s41598-026-49379-1

BibTeX

@article{cao2026rule,
author = {Cao, Rui and Li, Jindong and Kong, He and Wang, Qi and Chang, Yi},
title = {{Rule-guided Skip-GCN in neural latent information diffusion network for social recommendation}},
journal = {Scientific reports},
year = {2026},
month = jun,
volume = {16},
number = {1},
pages = {25452},
publisher = {Nature Publishing Group},
issn = {2045-2322},
doi = {10.1038/s41598-026-49379-1},
url = {https://doi.org/10.1038/s41598-026-49379-1},
pmid = {42243206},
pmcid = {PMC13473486}
}

RIS

TY - JOUR
AU - Cao, Rui
AU - Li, Jindong
AU - Kong, He
AU - Wang, Qi
AU - Chang, Yi
TI - Rule-guided Skip-GCN in neural latent information diffusion network for social recommendation
T2 - Scientific reports
J2 - Sci Rep
PY - 2026
DA - 2026/06/04
VL - 16
IS - 1
SP - 25452
SN - 2045-2322
PB - Nature Publishing Group
DO - 10.1038/s41598-026-49379-1
UR - https://doi.org/10.1038/s41598-026-49379-1
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s41598-026-49379-1",
"type": "article-journal",
"title": "Rule-guided Skip-GCN in neural latent information diffusion network for social recommendation",
"container-title": "Scientific reports",
"author": [
{
"family": "Cao",
"given": "Rui"
},
{
"family": "Li",
"given": "Jindong"
},
{
"family": "Kong",
"given": "He"
},
{
"family": "Wang",
"given": "Qi"
},
{
"family": "Chang",
"given": "Yi"
}
],
"container-title-short": "Sci Rep",
"volume": "16",
"issue": "1",
"page": "25452",
"DOI": "10.1038/s41598-026-49379-1",
"PMID": "42243206",
"PMCID": "PMC13473486",
"ISSN": "2045-2322",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s41598-026-49379-1",
"language": "en",
"issued": {
"date-parts": [
[
2026,
6,
4
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.7554/elife.110588 [code]
Opening the black box toward a modular approach to spike sorting.
Journal: eLife
In common: TensorFlow, NumPy, methods / tools
[2] doi:10.1162/imag.a.1366 [code]
MICAFlow: Fast and robust MRI preprocessing bridging research neuroimaging and clinical practice.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: TensorFlow, NumPy, methods / tools
[3] doi:10.1126/sciadv.aed3650 [code]
Truthful visualizations for mass spectrometry imaging enable high-spatial-resolution interactive &lt;i&gt;m/z&lt;/i&gt; mapping and exploration.
Journal: Science advances
In common: TensorFlow, NumPy, methods / tools
[4] doi:10.1038/s41592-026-03194-8 [code]
Beyond benchmarking: an expert-guided consensus approach to spatially aware clustering.
Journal: Nature methods
In common: TensorFlow, NumPy, methods / tools
[5] doi:10.1371/journal.pone.0354976 [code]
Improved motor imagery BCI performance via task-unaware compression in the BELT Bayesian Edge-Cloud architecture.
Journal: PloS one
In common: TensorFlow, NumPy, methods / tools
[6] doi:10.1016/j.ncrna.2026.06.004 [code]
LncPNdeep: A long non-coding RNA classifier based on large language model with peptide and nucleotide embedding.
Journal: Non-coding RNA research
In common: TensorFlow, NumPy, methods / tools
[7] doi:10.1093/bioinformatics/btag601 [code]
SIMLINK enables accurate variant pathogenicity prediction through modeling the gene-variant-feature association structure.
Journal: Bioinformatics (Oxford, England)
In common: TensorFlow, NumPy, methods / tools
[8] doi:10.1162/imag.a.1301 [code]
MEG-GPT: A transformer-based foundation model for magnetoencephalography data.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: TensorFlow, NumPy, methods / tools
[9] doi:10.1039/d6ra03343a [code]
A benchmark dataset and interpretable deep learning framework for drug-induced developmental neurotoxicity prediction.
Journal: RSC advances
In common: TensorFlow, NumPy, methods / tools
[10] doi:10.1364/boe.600665 [code]
NeuroSeg-MF: robust neuron segmentation in two-photon Ca&lt;sup&gt;2+&lt;/sup&gt; imaging using multi-feature fusion and detection-guided SAM.
Journal: Biomedical optics express
In common: TensorFlow, NumPy, methods / tools

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.