From a92f647fbb34c611f21c5308e050f53029c41bf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Lamercerie?= <aurelien.lamercerie@tetras-libre.fr> Date: Tue, 8 Aug 2023 19:30:00 +0200 Subject: [PATCH] Update module Metrics to refine metrics calculation --- .../__pycache__/__init__.cpython-311.pyc | Bin 607 -> 0 bytes .../__pycache__/metrics.cpython-311.pyc | Bin 2460 -> 0 bytes .../__pycache__/ontology.cpython-311.pyc | Bin 8889 -> 0 bytes ontoScorer/__pycache__/report.cpython-311.pyc | Bin 2283 -> 0 bytes ontoScorer/__pycache__/scorer.cpython-311.pyc | Bin 1772 -> 0 bytes ontoScorer/metrics.py | 82 +++++++++++++++--- ontoScorer/ontology.py | 24 ++--- ontoScorer/report.py | 6 +- tests/test_metrics.py | 36 +++++++- tests/test_ontology.py | 2 +- 10 files changed, 120 insertions(+), 30 deletions(-) delete mode 100644 ontoScorer/__pycache__/__init__.cpython-311.pyc delete mode 100644 ontoScorer/__pycache__/metrics.cpython-311.pyc delete mode 100644 ontoScorer/__pycache__/ontology.cpython-311.pyc delete mode 100644 ontoScorer/__pycache__/report.cpython-311.pyc delete mode 100644 ontoScorer/__pycache__/scorer.cpython-311.pyc diff --git a/ontoScorer/__pycache__/__init__.cpython-311.pyc b/ontoScorer/__pycache__/__init__.cpython-311.pyc deleted file mode 100644 index 15c9d4b5e58309a39ad2614703ebff6ad3759740..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 607 zcmZ3^%ge>Uz`*eQ%$bxW3=9m9K^z!ngEBs|F)}brXGmd4Va#EOg3ydnjHwJ+Oi&dJ z3z%UnWEw>U3$hH1oyxk5k%3_~BaDyAOJS;FU|@)1V`4~U$YO`7No7M-#mJD#h~yFu zm^x%S1!Mxkwb<Q)X6`a328PveJ&X(~jKK_=%r8O4`u$?m*W|p#lwW*{xwx|U7E3{5 zNyaVql+2>M#N5<d?1@RmU=fb^__WNN)cE*Y96p{-@d1t@9=BMNGg2~(Zn0(N6{i-J ztYr8MGVqs!enx(7s(wylZfagurha&SQFd`bVsff}NNPz@VzGXHUP*p&a(+>25ttba zVaCU2=4F<|$LkeT{^GF7%}*)KNwq5yU|?VXg=ldF0|UbcW=2NF2Ml}-DDVb1Z;yGu zeV6?VqdDgD?PuAqu(&8~az)zYBDd)kZqpsi7rCt)IBqa-G%&SrbVyue5W2!3bb&$W u1_N^oM>~HL{{+SfMpMkE+fTAzU~y4c=Zdh-MF!m~47wL!sECh&fdK$ee}YB; diff --git a/ontoScorer/__pycache__/metrics.cpython-311.pyc b/ontoScorer/__pycache__/metrics.cpython-311.pyc deleted file mode 100644 index 261155446af384b3fa8a8d952545d43dda6c6dec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2460 zcmZ3^%ge>Uz`)RHcqwHI3j@Pr5C?`?pp4HB3=9m@8B!Qh7;_kM8KW3;nWC6-nWLB) zL1IifEV-;vtc(my4DJjm%q<KlEX$Y}7*;bubu&b<rLYDwXtKQo31~9k;x8ylP0lRN z%+HH2PR=h%y~R_Mnw*%E1Lbj~8A4c^jJG)a^Gfn_^3yAmL3&}B5z6>11$I{|Llk2Q zLljdAV+%tRa|%-nLljF2b1;J@%Pn@_)RLmi<l<zQ7LZPm!<ZQu7(N?-wWl!FFvNqz z!5GYgs|NEx>LGFr!3>&AenlVwP3BviaDUulgZSVUQ<|YB<1Lor)SR?pkRb}c?DaG9 zb5r$m5_41YvNH9<^NX^J3lfu4^+QriiV}<U^Ycpb!J$wDW(I=-q)0y(;%vQw%3B=q z@tJv<CGqi90#MKB!9@5N7#NDB85kHE7;Z>Pb+GjC-4GM+VCmt$Atc<v(!<`t-ogGE z<nm;YcR>sgW@TVt0P#OhV`N}xXKQDl&QJn!D@cxkfdLeXHH-_8M4%E33=GQ{7#LQ= zxh`n@WsD3AtKs^(*ilSnYGJ5hqJpVxo$L!h;SYBOjM2%4YJV+r2YVW03Udob4Kun+ zYgszj(il@%u*$KPu*1w`V5niKVMR^NH4O2ve8Et{O+Y0ZOumF4#=>DH2TVQ%l*m~9 zP*N<&LSayfH3O&EbcPy+Sg~5h8pZ`MT_`kaG)-jc5f5fq$*_{~7E4}YZt6;=TTFTe zx0sW2ii<%Zsi05<N=U!BY;rP-OOo?*3+$>?VM#4HF(<h+C$S_|&n727IWec$P7k3> z1mq+IaQeHT5CK6Om=_2ymsljRP-=-3MC5`(M3Ddk0|T{vR0Il<B9I%3#6TGV$uC8c z3=9lJdP0<efuRUgkl=A7$d6MQr!#;9o(mN4olIp6MNBCSd5kHH6PbFrgBeyby#%Fw zaNz)UnkI9RILK@X1_p*(f<>umsYR)I$*J+lIf=!^sl~;hJgA`1Py`BmQXC92@3RI2 z1H+F7h6{pz5VXU1Lh%JT{R`qCG(mBK;)Xzo#05b=3O!aN3-Sdhuu*-Ko|>0hlvt9Q zLa~oPu~h^LW3Wp#Id3r+r<UB}PERd?8GVbjG%qthuLu-oMW70+2$Us?K-sSdRGt;_ zFfcG^auo4`!deIs)}YcARDIkMLbw(##to`-ps{g_tunr(s5BKs7ZjzY6e)o`Ee}dp zpq!}y1`ZD3$hyS|&lOdI7#Rf=P{mh4(etB$;jWB4G!vM6UN;ZDWFC6aJp77z_yvWC ziwY4}6e2FlL|&1Jyucwzyvhe+>et0|FNx`1(6hfN=5R&Kp@aJdEFD}B^gEz^LD27_ zpx+fizYaE>5>F*HR)}p7yC`XKMbZLPb=(zGT41)q?4p>_6)_`FC306tYKGYYvx`Dn zSA?`+)d@I;{4`lX)e@*MiI2a<6(66QpHiBW8Xtd)CqBNgG%*JvQv@pWinKui2?`Xj zR&W3ofr1oFfa0sz2wZ|RFhJl3CT3QV4-9aEi;GqJ0|O=jF%D#spC<b){^IPM)Wo7Z zJ!s7dNh#n&0!kmZgh8<msa*9yOi-dI0+r5SXMpo7#6VDP{Ka7d@sVATAp-*gC|eh2 xF)%QEU}j`w{2;=>=)!n`!5J62!Ju&g6@6e4VATG=fJuA=iG2YPXtH3p006+<GA;lB diff --git a/ontoScorer/__pycache__/ontology.cpython-311.pyc b/ontoScorer/__pycache__/ontology.cpython-311.pyc deleted file mode 100644 index b71e1d0f3cad1e8ed6574796cb86610805e54287..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8889 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 diff --git a/ontoScorer/__pycache__/report.cpython-311.pyc b/ontoScorer/__pycache__/report.cpython-311.pyc deleted file mode 100644 index 3ac64f032d3c2903f9d0664b49ed1fe36c6d71ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2283 zcmZ3^%ge>Uz`(Hl!kLt<><kQ#K^z!nfigZTFfcGoXJBG*XGmdaVMt+I#>Bv|nh7e) z5XF$f6wIK>oD35H(TpI1fq~((6j*O6Llk2QLljdAV+%tRa|%-nLljF2b1;J@%PqE` z)Pnq?l4Mq>4iE)0n;E3r4y?O|v4$ZYBo4+kOf?MgF!LE|m}?l~LFyrLEHw=AAe~@d z3PUi1CZnGw%Ppaz)U?#1)V$=>`24(*{G9ys%3DI|sd=eIi6yBi2r<Fr{M>@XqRis_ zy!fKj;?kUwTkN^1B}JLZ#hR?QSc+3~(uzP1En;I}U?^e-5gZH*48<TZ1rYdUr=O9Z zo2s9an46lHm8l<|UzA;3keHmRACg*9lvu0}vc5PuzbLf`%nXJwi@;%^S5SG2BR)Pe zFS8^*zKS0bFnTZnZjeQ)3=9kn3^$ZaI#{l7$irzxBM@KihPYe@OAk*6PY2IuPzWT$ zgNcEG0pvzd(0q1a0!3#EV=ZG1V+vCZLl#IW7-zxN&t{m*RK?4{09M0X0@4ds!N7o` z9%LR^d>JDH!)olhS!x)vU`dGqhYhS~HXzg!V*?w+rD$e=-321DaF~Ino}iuCU=>Ad zHH<0j5F7LC(aZo@2gX#h6KopTP7bJ@tTl`&oDg;mV+t3X#a+XY1&^mJPyz+(MTtos z6g8mqi>ZbeMGYu<W2gyc(B$*0Qnt0VRq%&qCk5BC#GKN^lFa-(1xUhGu(h@2suJZ2 zf@M9pS}TPrEiS*(+@#bZh5R&y<ebFf;?!b=Ops1!Hbqt|#>M3h%c{uYILyGRR+Nj& z8J@Kjg1}kZN}<X%BqLP;UJfXLGAF2PP{>FuR!B=NPc4Ewt|TKdPoX3uRRLa-z*Xy2 zx!^G-H@_&AI8%afn39;6g2QHojKs23uv~FsZmL2adXVZ>iE?ovMT{?`D6^{K;R+~9 zP0lRN%+Iq@sN&=bN=;78$+1$X;^uNQQ~(!BRtlP&;Ii%(OF?2u#x3TY)Vy2l(71w> zf1tE+i?aY`(k-?kuraro(hN13iZ~e<7;bSvO1AjolA>ZzDXpMT1gdaualir{Ud+J+ z1VP1IFeA8_6SeN(dcYxcLCkkW$rXLKEBf9S#C$J^`CjDk?cllrlE^yhe1heQNBk9! z^ouSTS6nhKh-F<6%eu&s1=Z=lLF9^|#}z~03u68k#QZOE_!FV?0~-UU@C7mbiyZnL zTz9$oI!dnat6kyOyU4A7g<F5C@`jWvX1-U<LN6MHT`>x~#2t2lJM0FJ*afM?i#&-P zUL9U{c?BkjToKf`B4}`t*YFCj;a2AzELSZ2uULd%G>N!k5^;$);sS33SWm)5o&=Dd z2OtCTF7o7cc!B*4u^sG7y9Fsra;~V^ToALnAZB-w!w%{Piv=c2Y_2GqT@bUlAZBrq z!vZR9wjg9l%#!#EVrCb_%r0`6b#Oi4m%P9sS;WJ@z~HCJ3aVxD5_41I<8N`r$LHp! zl;(igJn`{`rHMHZnIceqQzXj3z_5}5tPdP<MWC`2On{=X*a%!5H84Qn2PPI)`40?m zf=8TH>H`BN0Wl6_lAk6c*svl=P*n<Y9oUv%95xU~*%g7>51@Lb*qniZ;R7=xBjX1V VIYy}u44A}6kk}UxfhG&K4*(zdK6n5C diff --git a/ontoScorer/__pycache__/scorer.cpython-311.pyc b/ontoScorer/__pycache__/scorer.cpython-311.pyc deleted file mode 100644 index 7696fe257f510bead13598ef2ee71e027b9b4612..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1772 zcmZ3^%ge>Uz`*dy@KTC8D+9x05C?`?pp4Hh3=9m@8B!Qh7;_kM8KW2(L2RZRrd;MI zW-yyMhb5Oaij|RpiNT#Ag{6fdg>@Md1H)=2s0j>FY$<HP44UjOK?0hLw>bRsO7e5^ z(<?O@Z?OfX7UUO|Xfobn_f0J+%1ka!2C0H!MkwR60@xL)3{i|J3{gxej4cdN%qdJQ z3{fm8%q<L2tSKzP44SOBxIjh+C+8QX79}%7^@1o68-zdCfXyj^najYyP{X*4k%3_~ zT%?8}9?nKl$AqB{?!yvxkR=ejjDdk+HG~N=ogp3;k_;&f!3--I{WMvNKu)<ORFs;Q zT9lfXoEo1G4Uk(x>8W|CMTsS;DR8kORt5%!TkN@z(9vYR#ZsJ_lXgoSQ+IqpVoAm= zaZDq?62%}(6%-VH+39EG=celCB<7~(Wo7Dz=NDxc7bGU9>W8G36eSkxgB()~4ni;! z5}NuD5xs)STO9H6nR%Hd@$pr{h|t!93Gy>AFccdzFfcSQ+*Q)LpzU-~$@z+sa|g>6 z4tY!gak+_=Qz|=HdU!f`I(R;Vf-M;y`V0&Vps)kE`|}KNywxydfs}yp0%Uby5fD+s zkOhwwjQ9eX1X9FM!;l3s8O&Y)3STe_nLxG)#Y~ix4NCvP3`Lv_3=EoVMWD=diz_)l zw;-`7HNGUjh#M4hf)Ihs;{3e$qSWHjoRT6QkT_>@Voq{tPGU)_CSwsVDAYh6QYaDt zNwPyUrB(?c1u;}i1f<pp9KtsgRj(*oTvv3yr09IW<%&!6Ma7saiZP(Tmb<~h)5CL} zL+%oX+>DYd@@6|&u2}eA<OsOJ5pV&9ii8*#7*GP7je&sy6ilC|fCC&Q12ANPTnG*& z<RGbG$O7qriNgbS84Cl$YB;Z!u>=$xU{#<@w*X`ll!u^DGY@J6A_q2m5y)V0h=W79 zNR)wr0TQmP1x1;8CAT<W*+7#C9J;sIiohjJF(`Q`K!cedrYIgFStW%O+-PzVpkQ|g z2m4(?@fj>vB=m1c$iPUw8xk^ecs{Z-3#ol!U=~vAVEf9!z{%H<)}P;%f00lA3ZMK% z4uvZm3Kw7q9QJ;iY@qy<mzbLxAAgH0K0Y@;r8Eb`=82ClEKSUT$P@{JyeAGKWEdD2 zRx*G!gOf@TsOSL`d>{vcO6vv&82rG*%&Pc-0Zwo+u?8}JU_c@{SV0Of35W$Cv;8#L zZ*hRi1W<_$F1d=NK@I^&04ODc3n;J)ia@0_L?<W}|KhNLc*m|tiGhIulz58s85kHo xFf%eTeh^_`l)Jzni;QkCNM1liHyETZprQ{f{EUhp7%+*CAh9nX0!<d|AOMULfPer1 diff --git a/ontoScorer/metrics.py b/ontoScorer/metrics.py index 73fd413..feedd33 100644 --- a/ontoScorer/metrics.py +++ b/ontoScorer/metrics.py @@ -2,28 +2,84 @@ # -*-coding:Utf-8 -* #============================================================================== -# ontoScorer: [brief description of the module] +# ontoScorer: Ontology Scoring Module #------------------------------------------------------------------------------ -# Detailed module description +# This module provides metrics to evaluate and compare different ontologies. +# It calculates precision, recall, and F1 score for various ontology elements +# such as classes, object properties, data properties, restrictions, individuals, +# and annotations. It also computes an overall score taking into account all +# the ontology elements. The comparison is performed between a reference ontology +# and a generated ontology, allowing users to evaluate how well the generated +# ontology matches the reference. #============================================================================== + from sklearn.metrics import precision_score, recall_score, f1_score from ontoScorer.ontology import Ontology class Metrics: + + #-------------------------------------------------------------------------- + # Constructor(s) + #-------------------------------------------------------------------------- + def __init__(self): - self.precision = 0 - self.recall = 0 - self.f1 = 0 + self.scores = { + "class": {"precision": 0, "recall": 0, "f1": 0}, + "object_property": {"precision": 0, "recall": 0, "f1": 0}, + "data_property": {"precision": 0, "recall": 0, "f1": 0}, + "restriction": {"precision": 0, "recall": 0, "f1": 0}, + "individual": {"precision": 0, "recall": 0, "f1": 0}, + "annotation": {"precision": 0, "recall": 0, "f1": 0}, + "overall": {"precision": 0, "recall": 0, "f1": 0} + } + + + #-------------------------------------------------------------------------- + # Computing Method(s) + #-------------------------------------------------------------------------- def calculate(self, reference_ontology, generated_ontology): - reference_classes = set([cls.name() for cls in reference_ontology.get_classes()]) - generated_classes = set([cls.name() for cls in generated_ontology.get_classes()]) + methods = [ + ("class", "get_classes"), + ("object_property", "get_object_properties"), + ("data_property", "get_data_properties"), + ("restriction", "get_restrictions"), + ("individual", "get_individuals"), + #("annotation", "get_annotations") + ] + + y_true_overall = [] + y_pred_overall = [] + + for score_name, method_name in methods: + reference_elements = set([elem.name() for elem in getattr(reference_ontology, method_name)()]) + generated_elements = set([elem.name() for elem in getattr(generated_ontology, method_name)()]) + + all_elements = reference_elements.union(generated_elements) + y_true = [1 if elem in reference_elements else 0 for elem in all_elements] + y_pred = [1 if elem in generated_elements else 0 for elem in all_elements] + + self.scores[score_name]["precision"] = precision_score(y_true, y_pred) + self.scores[score_name]["recall"] = recall_score(y_true, y_pred) + self.scores[score_name]["f1"] = f1_score(y_true, y_pred) - all_classes = reference_classes.union(generated_classes) - y_true = [1 if cls in reference_classes else 0 for cls in all_classes] - y_pred = [1 if cls in generated_classes else 0 for cls in all_classes] + y_true_overall.extend(y_true) + y_pred_overall.extend(y_pred) - self.precision = precision_score(y_true, y_pred) - self.recall = recall_score(y_true, y_pred) - self.f1 = f1_score(y_true, y_pred) \ No newline at end of file + self.scores["overall"]["precision"] = precision_score(y_true_overall, y_pred_overall) + self.scores["overall"]["recall"] = recall_score(y_true_overall, y_pred_overall) + self.scores["overall"]["f1"] = f1_score(y_true_overall, y_pred_overall) + + + #-------------------------------------------------------------------------- + # Printing Method(s) + #-------------------------------------------------------------------------- + + def print_scores(self): + for element, scores in self.scores.items(): + print(f"Metrics for {element.capitalize()}:") + print(f"\tPrecision: {scores['precision']:.4f}") + print(f"\tRecall: {scores['recall']:.4f}") + print(f"\tF1 Score: {scores['f1']:.4f}") + print("----------------------------") \ No newline at end of file diff --git a/ontoScorer/ontology.py b/ontoScorer/ontology.py index 90d4329..cb2d501 100644 --- a/ontoScorer/ontology.py +++ b/ontoScorer/ontology.py @@ -114,17 +114,21 @@ class Ontology: return self._get_elements_of_type(OWL.Restriction) def get_individuals(self) -> list: - """Extract all individuals from the ontology.""" - all_types = set(self.graph.subjects(RDF.type)) - non_individuals = {element.reference for element in - self.get_classes() + - self.get_object_properties() + - self.get_data_properties()} + """Extract all individuals from the ontology, including elements explicitly typed as owl:Individual, + owl:NamedIndividual or any class.""" - individuals = all_types - non_individuals - - return [NamedElement(i, self.graph) if isinstance(i, URIRef) else BlankElement(i, self.graph) - for i in individuals] + # Getting elements of type owl:NamedIndividual and owl:Individual + individuals = self._get_elements_of_type(OWL.NamedIndividual) + individuals += self._get_elements_of_type(URIRef("http://www.w3.org/2002/07/owl#Individual")) + + # Getting all elements typed as one of the classes + all_classes = {cls.reference for cls in self.get_classes()} + for cls in all_classes: + individuals += [NamedElement(s, self.graph) if isinstance(s, URIRef) else BlankElement(s, self.graph) + for s, _, o in self.graph.triples((None, RDF.type, cls))] + + return list(set(individuals)) # Ensuring uniqueness + def get_annotations(self): """Extract all annotation comments from the ontology.""" diff --git a/ontoScorer/report.py b/ontoScorer/report.py index 30f7659..a5df58a 100644 --- a/ontoScorer/report.py +++ b/ontoScorer/report.py @@ -33,9 +33,9 @@ class Report: report_str += "The generated ontology and the reference ontology have the same number of classes." report_str += "\n\nEvaluation Metrics:" - report_str += f"\nPrecision: {self.metrics.precision}" - report_str += f"\nRecall: {self.metrics.recall}" - report_str += f"\nF1 Score: {self.metrics.f1}" + report_str += f'\nPrecision: {self.metrics.scores["overall"]["precision"]}' + report_str += f'\nRecall: {self.metrics.scores["overall"]["recall"]}' + report_str += f'\nF1 Score: {self.metrics.scores["overall"]["f1"]}' return report_str diff --git a/tests/test_metrics.py b/tests/test_metrics.py index 4415d78..9dc6501 100644 --- a/tests/test_metrics.py +++ b/tests/test_metrics.py @@ -2,9 +2,39 @@ # -*-coding:Utf-8 -* #============================================================================== -# ontoScorer: [brief description of the module] +# test_metrics: Metrics Testing Module #------------------------------------------------------------------------------ -# Detailed module description, if needed +# Contains tests for verifying functionality of the Metrics class. #============================================================================== -# TODO +import unittest +import os +from context import ontoScorer +from ontoScorer.ontology import Ontology +from ontoScorer.metrics import Metrics + +class TestMetrics(unittest.TestCase): + + def setUp(self): + DATA_FOLDER_PATH = f'{os.path.dirname(os.path.abspath(__file__))}/test_data' + self.ontology1_path = f"{DATA_FOLDER_PATH}/ontology_a.ttl" + self.ontology2_path = f"{DATA_FOLDER_PATH}/ontology_b.ttl" + self.onto1 = Ontology(self.ontology1_path) + self.onto2 = Ontology(self.ontology2_path) + self.metrics = Metrics() + + def test_calculate_scores(self): + self.metrics.calculate(self.onto1, self.onto2) + for key in self.metrics.scores: + self.assertTrue(0 <= self.metrics.scores[key]["precision"] <= 1) + self.assertTrue(0 <= self.metrics.scores[key]["recall"] <= 1) + self.assertTrue(0 <= self.metrics.scores[key]["f1"] <= 1) + + + def test_print_scores(self): + self.metrics.calculate(self.onto1, self.onto2) + self.metrics.print_scores() + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_ontology.py b/tests/test_ontology.py index 8da3b2e..da89d12 100644 --- a/tests/test_ontology.py +++ b/tests/test_ontology.py @@ -68,7 +68,7 @@ class TestOntology(unittest.TestCase): def test_get_individuals(self): individuals_names = {ind.name() for ind in self.onto1.get_individuals()} - + self.assertEqual(len(individuals_names), 1) self.assertIn("SolarSystem", individuals_names) self.assertNotIn("gravitation", individuals_names) -- GitLab