Ejemplo n.º 1
0
def activate_model(model_name=None, debug=0):
	"""
	Active le modèle choisi en l'installant depuis le model store vers grobid
	
	Pour l'instant n'est jamais utilisé dans les scénarios ligne de commande
	mais peut-être très utile en usages avancés
	"""
	model_object = CRFModel(model_type, existing_mid=model_name)
	
	# crée le symlink +  enregistre les changements 
	# de paramètres dans le store (sous 'last') ET
	# chez grobid (dans config/grobid.properties)
	model_object.push_to_gb(debug_lvl=debug)
Ejemplo n.º 2
0
def eval_model(model_names=[], eval_set=None, 
               save_tab=True, do_graphs=False, debug = 0):
	"""
	Stats et eval proprement dites
	1 - balisage initial d'un sample GOLD
	2 - lancement indirect de eval_xml_refbibs.pl
	(si pas de model_names, on évalue le dernier modèle)
	
	commande équivalente:
	eval_xml_refbibs.pl -x evaluations/temp.output_bibs.dir/ -r corpora/EVAL_CORPUS/data/C-goldxmltei/
	"""
	
	# (0) trouver le script d'évaluation dès avant le balisage
	which_eval_script = CONF['eval']['SCRIPT_PATH']
	
	# si usage de la variable spéciale relative au fichier bako.py
	if search("<BAKO_INSTALL_DIR>", which_eval_script):
		bako_script_dir = path.dirname(path.realpath(__file__))
		which_eval_script = sub("<BAKO_INSTALL_DIR>",bako_script_dir, which_eval_script)
	
	# si le script n'est pas là ?
	if not path.exists(which_eval_script):
		print("EVAL_MODEL: warning => can't find evaluation script in configured path %s" % which_eval_script)
		
		# on tente ../eval/eval_xml_refbibs.pl
		stack_default_path = path.join(path.abspath(__file__),"..","bib-eval","eval_xml_refbibs.pl")
		if path.exists(stack_default_path):
			print("EVAL_MODEL: warning => using refbibs-stack default path %s for evaluation script" % stack_default_path)
			which_eval_script = stack_default_path
		else:
			print("EVAL_MODEL: please set correct path to eval_xml_refbibs.pl in config file ('%s')" % CONF_PATH)
			exit(1)
	
	
	# (1) récupération du corpus ---------------------------
	if eval_set is None:
		eval_set = CONF['eval']['CORPUS_NAME']
	
	eval_corpus = take_set(eval_set)
	
	# (2) préparer eval_id et activer le ou les modèles ----
	
	# suivi local
	changed_models = {
		'bibzone':None,
		'biblines':None,
		'bibfields':None,
		'authornames':None
		}
	
	# cf. anciennement dans CoLTrAnE/eval
	# ${CORPUS_SHORTNAME}-${GB_NAME}_avec_${MY_NEW_SAMP}
	mon_eval_id = ""
	
	# cas où l'on évalue les modèles courants
	# => aucune substitution entre le store et les modèles actifs
	if not len(model_names):
		# use case courant: une eval vanilla qui est fréquente
		#                   pour "calibrer" les attentes
		print('/!\\ EVALUATING CURRENT MODELS /!\\', file=stderr)
		
		# juste modèles courants (= vanilla)
		mon_eval_id = eval_corpus.name+'-BASELINE-'+GB_VERSION+'_avec_vanillas'
		
	# cas avec un ou des modèle(s) donné(s)
	else:
		all_models_str = "-".join(model_names)
		mon_eval_id = eval_corpus.name+'--'+GB_VERSION+'_avec_'+all_models_str
		for model_name in model_names:
			# £TODO à remplacer avec un changement dans l'init de CRFModel()
			model_type = search(r'^([^-]+)-', model_name).groups()[0]
			model_object = CRFModel(model_type, existing_mid=model_name)
			model_object.push_to_gb(debug_lvl=debug)
			
			# suivi
			changed_models[model_object.mtype] = True
	
	# (3) lancer balisage -----------------------------------------------
	evals_dir = path.join(CONF['workshop']['HOME'], CONF['workshop']['EVALS_HOME'])
	
	# pour l'instant les refbibs résultantes sont toujours au même endroit
	newbibs_path = path.join(evals_dir,"temp.output_bibs.dir")
	if not path.isdir(newbibs_path):
		makedirs(newbibs_path)
	
	# £TODO corriger bug grobid sur les xml:id ou reprendre bib-get
	jarfile = 'grobid-core-'+GB_RAW_VERSION+'.one-jar.jar'
	print ('vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv', file = stderr)
	print ('--- Balisage en cours sur %s ---' % eval_corpus.name , file = stderr)
	baliseur = call(
		  ['java',
		  '-Xmx1024m',
		  '-jar', path.join(CONF['grobid']['GROBID_DIR'], 'grobid-core','target', jarfile),
		  '-gH', path.join(CONF['grobid']['GROBID_DIR'],'grobid-home'),
		  '-gP', path.join(CONF['grobid']['GROBID_DIR'],'grobid-home','config','grobid.properties'),
		  '-exe', 'processReferences',
		  '-dIn',eval_corpus.shelf_path('PDF0'),
		  '-dOut',newbibs_path
		  ]
		  )
	print ('--- Balisage terminé (=>dossier %s)---' % newbibs_path, file = stderr)
	print ('^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^', file = stderr)
	
	# (4) évaluer
	# NB si table existe >> append résultats
	report_table = CONF['eval']['TABLE_PATH']
	
	# resultat_eval sera rempli par une grande table pour 
	# chaque paire (bib gold - bib évaluée) de chaque doc
	resultat_eval = bytes()
	
	# >>> appel basique perl <<<
	eval_call_elts = ['perl', which_eval_script, '-x', newbibs_path, '-g',  eval_corpus.shelf_path('GTEI'), '-e', 'references.tei.xml']
	
	# option debug
	if debug > 0:
		eval_call_elts += ["-d"]
	
	# option save tab
	if save_tab:
		# initialisation si nécessaire...
		if not path.exists(report_table):
			evals_tab = open(report_table, "w")
			print("NDOCS\tnbibs_gold\tRappel\tPrécision\t match_tit\tmatch_vol\tmatch_au+date\tmatchs_TOTAL\tEVAL_ID", file=evals_tab)
			evals_tab.close()
		
		# ...et passage aux arguments du script perl
		eval_call_elts += ['--logreport',report_table,'--regreport', mon_eval_id]
	
	if debug > 1:
		print("APPEL eval:", eval_call_elts)
	
	# ---------- run eval -----------------------
	resultat_eval = check_output(eval_call_elts)
	
	# STDOUT: TSV en str depuis bytes
	resultat_eval = resultat_eval.decode("UTF-8")
	
	# (5) stocker
	this_eval_dir = path.join(evals_dir,mon_eval_id)
	if not path.isdir(this_eval_dir):
		makedirs(this_eval_dir)
	
	output = open(path.join(this_eval_dir, 'tableau_detail_eval.tab'), 'w')
	output.write(resultat_eval)
	output.close()
	
	# (6) remettre les modèles comme avant (si nécessaire)
	if len(model_names):
		print("EVAL_MODEL: restauration des modèles précédents")
		for model_type in changed_models:
			if changed_models[model_type]:
				gb_vanilla_restore(model_type)
Ejemplo n.º 3
0
def run_training(model_type, corpora, debug=0):
	""" 
	Entraînement proprement dit
	
	/!\ Ici un seul model_type, plusieurs corpus potentiels /!\
	
	(appel de grobid-trainer)
	  - appel système
	  - commande shell équivalente
	      mvn generate-resources -P train_<model_type>
	      
	  Chaîne d'invocation réelle:
	     bako => shell => maven => grobid-trainer => wapiti
	
	/!\ La commande shell ne renvoit pas le modèle
	    mais va aller l'écrire directement dans grobid-home/models
	    
	    Quant à nous, on le récupère a posteriori pour le ranger.
	
	"""
	
	# cas vanilla: on entraîne sur les dataset existants
	if corpora is None:
		# use case rare (ex: pour comparer avec repository)
		# (contrairement à une eval vanilla qui est fréquente)
		print("/!\\ RE-TRAINING VANILLA MODEL /!\\", file=stderr)
		# juste modèle
		new_model = CRFModel(model_type,debug_lvl=debug)
	
	# cas normal avec liste de corpus à reprendre
	else:
		corpora_objs = []
		# (1) vérif existence
		for c_name in corpora:
			try:
				corpora_objs.append(TrainingCorpus(c_name))
			except FileNotFoundError as e:
				print("ERR: Le corpus '%s' n'existe pas." % e.corpus_name,file=stderr)
				exit(1)
		
		# (2) vérif étagère(s) requise(s)
		for c_obj in corpora_objs:
			for tgtdir in PREP_DATASET[model_type]:
				needed_sh = PREP_DATASET[model_type][tgtdir]
				if not c_obj.shelfs[needed_sh]:
					print("ERR: Le corpus '%s' n'a pas d'étagère %s pour %s" % (c_obj.name,needed_sh,model_type) ,file=stderr)
					exit(1)
		
		# (3) vérif doublons
		# dict de vérification local
		dedup_check = dict()
		for cobj in corpora_objs:
			# liste rattachée par objet
			cobj.temp_ignore = defaultdict(lambda: False)
			for filename in cobj.bnames:
				if filename not in dedup_check:
					# le premier arrivé à gagné
					dedup_check[filename] = cobj.name
				else:
					print("DOUBLON entre %s et %s: %s" % (
							dedup_check[filename],
							cobj.name,
							filename
							)
						)
					# stockage temporaire
					cobj.temp_ignore[filename] = True
		
		# --- initialisation modele -----------------------------
		new_model = CRFModel(
			model_type,
			# NB ce sont juste les noms mais à présent vérifiés
			the_samples=corpora,
			debug_lvl=debug
			)
		# !! symlinks de substitution dossiers !!
		_prepare_dirs(new_model, corpora_objs, debug_lvl=debug)
	
	
	# 2) train_params = _call_grobid_trainer()
	
	# lancement grobid-trainer
	print("training new model %s" % new_model.mid)
	
	# ==================================================#
	#  E N T R A I N E M E N T    G R O B I D    C R F  #
	# ==================================================#
	(mvnlog, crflog) = new_model.call_grobid_trainer()  #
	# ==================================================#
	
	# vérification simple
	# si le CRF n'a pas été lancé c'est que le maven a planté
	if not len(crflog.lines):
		print("!!!--------- ERREUR GROBID-TRAINER ---------!!!", file=stderr)
		print("\n".join(mvnlog.lines), file=stderr)
		exit(1)
	# cas normal ------------------------------------------------------
	else:
		new_model.ran = True
	
	# 3) pick_n_store : récupération du modèle
	stored_location = new_model.pick_n_store(logs = [mvnlog, crflog])
	print("new model %s stored into dir %s" % (new_model.mid, stored_location), file=stderr)
	
	# nouveau scénario prudent pour tout utilisateur:
	#  on réactive chaque fois les vanilla ensuite
	# 4) restauration a posteriori du modèle vanilla
	restored_mid = gb_vanilla_restore(model_type)
	print("new model %s deactivated in grobid (restored previous: %s)" % (new_model.mid, restored_mid))