22-02-2022

Cosa ho fatto

  1. Novità relative al file di configurazione di Meta:

    • Invece di 5 directory di output, adesso basta specificarne una, la directory base. Le altre vengono generate automaticamente di conseguenza.
    • Il parametro workers_number ha sostituito run_in_multiprocess. Il valore è un intero, che rappresenta il numero di processori che si intende dedicare al software di Meta.
  2. Ho drasticamente migliorato l’efficienza del sistema di merge di prepare_multiprocess. Il suo obiettivo è fondere le riviste e gli agenti responsabili sulla base dell’id prima che il software di Meta li processi. Ecco come i dati vengono prima organizzati e poi deduplicati:

    1. Ogni id di ogni entità diventa la chiave di un dizionario. In caso di id multipli, vengono generate tante chiavi quanti sono gli id e a ciascuno di essi vengono associati tutti gli altri id in un dizionario con chiave ‘others’.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      # Dati tre item item_1, item_2 e item_3
      item_1 = 'Venue [id:a id:b id:c]'
      item_2 = 'Venue [id:a id:d]'
      item_3 = 'Venue [id:e id:d]'

      # Viene generato il dizionario redundant_dict

      # Nel caso di item_2, dato che 'id:a' esiste già in redundant_dict,
      # 'id:d' viene aggiunto a 'others' in 'id:a'. Dopodiché, viene aggiunta una nuova
      # chiave 'id:d' e 'id:a' viene inserito in 'others' per quella chiave.
      redundant_dict = {
      'id:a': {'others': {'id:b', 'id:c', 'id:d'}, 'name': 'Venue', 'type': 'journal'},
      'id:b': {'others': {'id:c', 'id:a'}, 'name': 'Venue', 'type': 'journal'},
      'id:c': {'others': {'id:b', 'id:a'}, 'name': 'Venue', 'type': 'journal'},
      'id:d': {'others': {'id:e', 'id:a'}, 'name': 'Venue', 'type': 'journal'},
      'id:e': {'others': {'id:d'}, 'name': 'Venue', 'type': 'journal'}}
    2. Dato che ogni id è chiave del dizionario, ciclando sugli elementi di ‘others’ è possibile trovare in O(1) tutti i dizionari relativi alle stesse entità e fonderli, in questo modo:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      def __do_collective_merge(redundant_dict:dict) -> dict:
      merged_by_key:Dict[str, Dict[str, set]] = dict()
      ids_checked = set()
      for id, data in redundant_dict.items():
      if id not in ids_checked:
      all_ids = set()
      all_ids.update(data['others'])
      for other in data['others']:
      if other not in ids_checked:
      ids_found = __find_all_ids_by_key(redundant_dict, key=other)
      all_ids.update({item for item in ids_found if item != id})
      ids_checked.update(ids_found)
      merged_by_key[id] = {'name': data['name'], 'type': data['type'],
      'others': all_ids}
      return merged_by_key

      def __find_all_ids_by_key(redundant_dict:dict, key:str):
      visited_items = set()
      items_to_visit = {item for item in redundant_dict[key]['others']}
      while items_to_visit:
      for item in set(items_to_visit):
      if item not in visited_items:
      visited_items.add(item)
      items_to_visit.update({item for item in items_by_id[item]['others']
      if item not in visited_items})
      items_to_visit.remove(item)
      return visited_items

    Fondere 4,839,636 milioni di entità tra riviste e agenti responsabili in questo modo richiede 8 secondi. Il sistema precedente, che prevedeva la ricerca anche nei valori dei dizionari e non solo nelle chiavi, richiedeva circa più di due giorni (circa 50 ore).

  3. Molto meno efficiente è invece la soluzione adottata per pre-caricare gli agenti responsabili sul triplestore prima del multi-process.

    1. Ogni autore viene inserito in una riga di un CSV al campo ‘author’, anche se editor, tanto il ruolo non viene registrato sul triplestore.
    2. Tale CSV viene processato da Meta. Dato che il campo id è vuoto, il Curator genera un metaid. Infine, il Creator aggiunge al triplestore non solo l’agente responsabile e il suo id, ma anche la risorsa bibliografica con quel metaid e l’AgentRole relativo a quell’agente responsabile.
    3. Successivamente, gli indici generati da Meta vengono utilizzati per cancellare dal triplestore tutte le risorse bibliografiche e gli AgentRole aggiunti in questa fase. Quest’ultimo passaggio avviene in multi-process ma richiede comunque circa 24 ore.
  4. Ho aggiornato Curator e Creator per gestire i nuovi tipi ‘peer review’, ‘proceedings series’ e ‘web content’.

  5. Ho aggiornato il README per documentare il multiprocess e la preparazione del multiprocess.

  6. La provenance viene adesso salvata di default in json-ld.

  7. Ho aggiornato l’articolo per Scientometrics e la lettera di risposta ai revisori relativamente ai criteri di valutazione dei risultati e agli esiti della valutazione.

    1. Ho pubblicato gli esiti della valutazione su Zenodo e li ho citati nell’articolo. Il dataset su Zenodo, a sua volta, menziona il codice utilizzato rimandando alla repository GitHub.

Domande

  1. Esistono algoritmi più efficienti di quello adottato in 2. della sezione Cosa ho fatto per fondere dizionari sulla base di un id che può comparire sia come chiave che come valore? Alternativamente, ci sono strutture dati più adeguate a tale scopo?

22-02-2022
https://arcangelo7.github.io/p/0a2abc825a304bd3980fdd223e311a21/
Author
Arcangelo Massari
Posted on
February 21, 2022
Licensed under