AI-For-Beginners/translations/el/lessons/2-Symbolic/Animals.ipynb

477 lines
22 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"# Υλοποίηση ενός Συστήματος Ειδικού για Ζώα\n",
"\n",
"Ένα παράδειγμα από το [AI for Beginners Curriculum](http://github.com/microsoft/ai-for-beginners).\n",
"\n",
"Σε αυτό το δείγμα, θα υλοποιήσουμε ένα απλό σύστημα βασισμένο σε γνώση για να προσδιορίσουμε ένα ζώο βάσει ορισμένων φυσικών χαρακτηριστικών. Το σύστημα μπορεί να αναπαρασταθεί από το ακόλουθο δέντρο AND-OR (αυτή είναι ένα μέρος του συνολικού δέντρου, μπορούμε εύκολα να προσθέσουμε κι άλλους κανόνες):\n",
"\n",
"![](../../../../../../translated_images/el/AND-OR-Tree.5592d2c70187f283.webp)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Το δικό μας κέλυφος συστημάτων ειδικών με οπισθοδρομική συμπερασματολογία\n",
"\n",
"Ας προσπαθήσουμε να ορίσουμε μια απλή γλώσσα για την αναπαράσταση γνώσης βασισμένη σε κανόνες παραγωγής. Θα χρησιμοποιήσουμε τις κλάσεις Python ως λέξεις-κλειδιά για τον ορισμό κανόνων. Θα υπάρχουν ουσιαστικά 3 τύποι κλάσεων:\n",
"* Η `Ask` αναπαριστά μια ερώτηση που πρέπει να τεθεί στον χρήστη. Περιέχει το σύνολο των πιθανών απαντήσεων.\n",
"* Η `If` αναπαριστά έναν κανόνα και είναι απλώς μια γλωσσική συντόμευση για την αποθήκευση του περιεχομένου του κανόνα.\n",
"* Οι `AND`/`OR` είναι κλάσεις που αναπαριστούν τα υποδέντρα AND/OR. Απλώς αποθηκεύουν τη λίστα των ορισμάτων στο εσωτερικό τους. Για να απλοποιηθεί ο κώδικας, όλες οι λειτουργίες ορίζονται στην κλάση γονέα `Content`.\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"class Ask():\n",
" def __init__(self,choices=['y','n']):\n",
" self.choices = choices\n",
" def ask(self):\n",
" if max([len(x) for x in self.choices])>1:\n",
" for i,x in enumerate(self.choices):\n",
" print(\"{0}. {1}\".format(i,x),flush=True)\n",
" x = int(input())\n",
" return self.choices[x]\n",
" else:\n",
" print(\"/\".join(self.choices),flush=True)\n",
" return input()\n",
"\n",
"class Content():\n",
" def __init__(self,x):\n",
" self.x=x\n",
" \n",
"class If(Content):\n",
" pass\n",
"\n",
"class AND(Content):\n",
" pass\n",
"\n",
"class OR(Content):\n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Στο σύστημά μας, η εργαζόμενη μνήμη θα περιέχει τη λίστα των **γεγονότων** ως **ζεύγη ιδιοτήτων-τιμών**. Η βάση γνώσεων μπορεί να οριστεί ως ένα μεγάλο λεξικό που αντιστοιχίζει ενέργειες (νέα γεγονότα που πρέπει να εισαχθούν στην εργαζόμενη μνήμη) σε συνθήκες, εκφρασμένες ως εκφράσεις ΚΑΙ-Ή. Επίσης, ορισμένα γεγονότα μπορούν να `Ask`-θούν.\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"rules = {\n",
" 'default': Ask(['y','n']),\n",
" 'color' : Ask(['red-brown','black and white','other']),\n",
" 'pattern' : Ask(['dark stripes','dark spots']),\n",
" 'mammal': If(OR(['hair','gives milk'])),\n",
" 'carnivor': If(OR([AND(['sharp teeth','claws','forward-looking eyes']),'eats meat'])),\n",
" 'ungulate': If(['mammal',OR(['has hooves','chews cud'])]),\n",
" 'bird': If(OR(['feathers',AND(['flies','lies eggs'])])),\n",
" 'animal:monkey' : If(['mammal','carnivor','color:red-brown','pattern:dark spots']),\n",
" 'animal:tiger' : If(['mammal','carnivor','color:red-brown','pattern:dark stripes']),\n",
" 'animal:giraffe' : If(['ungulate','long neck','long legs','pattern:dark spots']),\n",
" 'animal:zebra' : If(['ungulate','pattern:dark stripes']),\n",
" 'animal:ostrich' : If(['bird','long nech','color:black and white','cannot fly']),\n",
" 'animal:pinguin' : If(['bird','swims','color:black and white','cannot fly']),\n",
" 'animal:albatross' : If(['bird','flies well'])\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Για να πραγματοποιήσουμε την οπισθογόρηση, θα ορίσουμε την κλάση `Knowledgebase`. Θα περιέχει:\n",
"* Εργασιακή `μνήμη` - ένα λεξικό που αντιστοιχεί χαρακτηριστικά σε τιμές\n",
"* Κανόνες της Βάσης Γνώσης `rules` στη μορφή που ορίζεται παραπάνω\n",
"\n",
"Δύο κύριες μέθοδοι είναι:\n",
"* `get` για να λάβουμε την τιμή ενός χαρακτηριστικού, πραγματοποιώντας οινοποίηση αν χρειάζεται. Για παράδειγμα, το `get('color')` θα πάρει την τιμή ενός πεδίου χρώματος (θα ρωτήσει αν χρειάζεται και θα αποθηκεύσει την τιμή για μελλοντική χρήση στην εργασιακή μνήμη). Αν ζητήσουμε `get('color:blue')`, θα ζητήσει χρώμα και μετά θα επιστρέψει τιμή `y`/`n` ανάλογα με το χρώμα.\n",
"* `eval` εκτελεί την πραγματική λογική, δηλαδή διασχίζει το δέντρο AND/OR, αξιολογεί υπο-στόχους κλπ.\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"class KnowledgeBase():\n",
" def __init__(self,rules):\n",
" self.rules = rules\n",
" self.memory = {}\n",
" \n",
" def get(self,name):\n",
" if ':' in name:\n",
" k,v = name.split(':')\n",
" vv = self.get(k)\n",
" return 'y' if v==vv else 'n'\n",
" if name in self.memory.keys():\n",
" return self.memory[name]\n",
" for fld in self.rules.keys():\n",
" if fld==name or fld.startswith(name+\":\"):\n",
" # print(\" + proving {}\".format(fld))\n",
" value = 'y' if fld==name else fld.split(':')[1]\n",
" res = self.eval(self.rules[fld],field=name)\n",
" if res!='y' and res!='n' and value=='y':\n",
" self.memory[name] = res\n",
" return res\n",
" if res=='y':\n",
" self.memory[name] = value\n",
" return value\n",
" # field is not found, using default\n",
" res = self.eval(self.rules['default'],field=name)\n",
" self.memory[name]=res\n",
" return res\n",
" \n",
" def eval(self,expr,field=None):\n",
" # print(\" + eval {}\".format(expr))\n",
" if isinstance(expr,Ask):\n",
" print(field)\n",
" return expr.ask()\n",
" elif isinstance(expr,If):\n",
" return self.eval(expr.x)\n",
" elif isinstance(expr,AND) or isinstance(expr,list):\n",
" expr = expr.x if isinstance(expr,AND) else expr\n",
" for x in expr:\n",
" if self.eval(x)=='n':\n",
" return 'n'\n",
" return 'y'\n",
" elif isinstance(expr,OR):\n",
" for x in expr.x:\n",
" if self.eval(x)=='y':\n",
" return 'y'\n",
" return 'n'\n",
" elif isinstance(expr,str):\n",
" return self.get(expr)\n",
" else:\n",
" print(\"Unknown expr: {}\".format(expr))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Τώρα ας ορίσουμε τη βάση γνώσεων για τα ζώα μας και να πραγματοποιήσουμε τη διαβούλευση. Σημειώστε ότι αυτή η κλήση θα σας κάνει ερωτήσεις. Μπορείτε να απαντήσετε πληκτρολογώντας `y`/`n` για ερωτήσεις ναι-όχι, ή καθορίζοντας έναν αριθμό (0..N) για ερωτήσεις με μεγαλύτερες απαντήσεις πολλαπλής επιλογής.\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"hair\n",
"y/n\n",
"sharp teeth\n",
"y/n\n",
"claws\n",
"y/n\n",
"forward-looking eyes\n",
"y/n\n",
"color\n",
"0. red-brown\n",
"1. black and white\n",
"2. other\n",
"has hooves\n",
"y/n\n",
"long neck\n",
"y/n\n",
"long legs\n",
"y/n\n",
"pattern\n",
"0. dark stripes\n",
"1. dark spots\n"
]
},
{
"data": {
"text/plain": [
"'giraffe'"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"kb = KnowledgeBase(rules)\n",
"kb.get('animal')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Χρήση του Experta για Προώθηση Συμπερασμάτων\n",
"\n",
"Στο επόμενο παράδειγμα, θα προσπαθήσουμε να υλοποιήσουμε προώθηση συμπερασμάτων χρησιμοποιώντας μία από τις βιβλιοθήκες για αναπαράσταση γνώσης, το [Experta](https://github.com/nilp0inter/experta). **Το Experta** είναι μία βιβλιοθήκη για τη δημιουργία συστημάτων προώθησης συμπερασμάτων σε Python, η οποία έχει σχεδιαστεί ώστε να είναι παρόμοια με το κλασικό παλιό σύστημα [CLIPS](http://www.clipsrules.net/index.html).\n",
"\n",
"Θα μπορούσαμε επίσης να υλοποιήσουμε την προώθηση συμπερασμάτων μόνοι μας χωρίς πολλά προβλήματα, αλλά οι απλές υλοποιήσεις συνήθως δεν είναι πολύ αποδοτικές. Για πιο αποτελεσματική αντιστοίχιση κανόνων χρησιμοποιείται ένας ειδικός αλγόριθμος [Rete](https://en.wikipedia.org/wiki/Rete_algorithm).\n"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Collecting git+https://github.com/nilp0inter/experta\n",
" Cloning https://github.com/nilp0inter/experta to /tmp/pip-req-build-7qurtwk3\n",
" Running command git clone --filter=blob:none --quiet https://github.com/nilp0inter/experta /tmp/pip-req-build-7qurtwk3\n",
" Resolved https://github.com/nilp0inter/experta to commit c6d5834b123861f5ae09e7d07027dc98bec58741\n",
" Installing build dependencies ... \u001b[?25ldone\n",
"\u001b[?25h Getting requirements to build wheel ... \u001b[?25ldone\n",
"\u001b[?25h Preparing metadata (pyproject.toml) ... \u001b[?25ldone\n",
"\u001b[?25hRequirement already satisfied: frozendict~=2.4.6 in /opt/conda/envs/ai4beg/lib/python3.12/site-packages (from experta==1.9.5.dev1) (2.4.7)\n",
"Collecting schema~=0.6.7 (from experta==1.9.5.dev1)\n",
" Downloading schema-0.6.8-py2.py3-none-any.whl.metadata (14 kB)\n",
"Downloading schema-0.6.8-py2.py3-none-any.whl (14 kB)\n",
"Building wheels for collected packages: experta\n",
" Building wheel for experta (pyproject.toml) ... \u001b[?25ldone\n",
"\u001b[?25h Created wheel for experta: filename=experta-1.9.5.dev1-py3-none-any.whl size=34804 sha256=888c459512a5e713f4b674caa9a0f96cfdf07ec0d6eb56cc318ce0653d218014\n",
" Stored in directory: /tmp/pip-ephem-wheel-cache-1eeii9zy/wheels/3d/e8/bb/22d7956359603fa8dd679aa09f5b8efb3f29991c3986fdc787\n",
"Successfully built experta\n",
"Installing collected packages: schema, experta\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2/2\u001b[0m [experta]\n",
"\u001b[1A\u001b[2KSuccessfully installed experta-1.9.5.dev1 schema-0.6.8\n"
]
}
],
"source": [
"import sys\n",
"!{sys.executable} -m pip install git+https://github.com/nilp0inter/experta"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"from experta import *\n",
"#import experta"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Θα ορίσουμε το σύστημά μας ως μια κλάση που υποκλάσης την `KnowledgeEngine`. Κάθε κανόνας ορίζεται από μια ξεχωριστή συνάρτηση με τη σημείωση `@Rule`, η οποία καθορίζει πότε πρέπει να ενεργοποιηθεί ο κανόνας. Μέσα στον κανόνα, μπορούμε να προσθέσουμε νέα γεγονότα χρησιμοποιώντας τη συνάρτηση `declare`, και η προσθήκη αυτών των γεγονότων θα έχει ως αποτέλεσμα ορισμένοι ακόμα κανόνες να καλούνται από τη μηχανή εμπρόθετης συμπερασματολογίας.\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"trusted": true
},
"outputs": [],
"source": [
"class Animals(KnowledgeEngine):\n",
" @Rule(OR(\n",
" AND(Fact('sharp teeth'),Fact('claws'),Fact('forward looking eyes')),\n",
" Fact('eats meat')))\n",
" def cornivor(self):\n",
" self.declare(Fact('carnivor'))\n",
" \n",
" @Rule(OR(Fact('hair'),Fact('gives milk')))\n",
" def mammal(self):\n",
" self.declare(Fact('mammal'))\n",
"\n",
" @Rule(Fact('mammal'),\n",
" OR(Fact('has hooves'),Fact('chews cud')))\n",
" def hooves(self):\n",
" self.declare('ungulate')\n",
" \n",
" @Rule(OR(Fact('feathers'),AND(Fact('flies'),Fact('lays eggs'))))\n",
" def bird(self):\n",
" self.declare('bird')\n",
" \n",
" @Rule(Fact('mammal'),Fact('carnivor'),\n",
" Fact(color='red-brown'),\n",
" Fact(pattern='dark spots'))\n",
" def monkey(self):\n",
" self.declare(Fact(animal='monkey'))\n",
"\n",
" @Rule(Fact('mammal'),Fact('carnivor'),\n",
" Fact(color='red-brown'),\n",
" Fact(pattern='dark stripes'))\n",
" def tiger(self):\n",
" self.declare(Fact(animal='tiger'))\n",
"\n",
" @Rule(Fact('ungulate'),\n",
" Fact('long neck'),\n",
" Fact('long legs'),\n",
" Fact(pattern='dark spots'))\n",
" def giraffe(self):\n",
" self.declare(Fact(animal='giraffe'))\n",
"\n",
" @Rule(Fact('ungulate'),\n",
" Fact(pattern='dark stripes'))\n",
" def zebra(self):\n",
" self.declare(Fact(animal='zebra'))\n",
"\n",
" @Rule(Fact('bird'),\n",
" Fact('long neck'),\n",
" Fact('cannot fly'),\n",
" Fact(color='black and white'))\n",
" def straus(self):\n",
" self.declare(Fact(animal='ostrich'))\n",
"\n",
" @Rule(Fact('bird'),\n",
" Fact('swims'),\n",
" Fact('cannot fly'),\n",
" Fact(color='black and white'))\n",
" def pinguin(self):\n",
" self.declare(Fact(animal='pinguin'))\n",
"\n",
" @Rule(Fact('bird'),\n",
" Fact('flies well'))\n",
" def albatros(self):\n",
" self.declare(Fact(animal='albatross'))\n",
" \n",
" @Rule(Fact(animal=MATCH.a))\n",
" def print_result(self,a):\n",
" print('Animal is {}'.format(a))\n",
" \n",
" def factz(self,l):\n",
" for x in l:\n",
" self.declare(x)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Αφού ορίσουμε μια βάση γνώσης, γεμίζουμε τη μνήμη εργασίας μας με μερικά αρχικά δεδομένα και στη συνέχεια καλούμε τη μέθοδο `run()` για να εκτελέσουμε την επαγωγή. Μπορείτε να δείτε ως αποτέλεσμα ότι νέα συμπερασμένα δεδομένα προστίθενται στη μνήμη εργασίας, συμπεριλαμβανομένου του τελικού δεδομένου για το ζώο (αν έχουμε ορίσει σωστά όλα τα αρχικά δεδομένα).\n"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"trusted": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Animal is tiger\n"
]
},
{
"data": {
"text/plain": [
"FactList([(0, InitialFact()),\n",
" (1, Fact(color='red-brown')),\n",
" (2, Fact(pattern='dark stripes')),\n",
" (3, Fact('sharp teeth')),\n",
" (4, Fact('claws')),\n",
" (5, Fact('forward looking eyes')),\n",
" (6, Fact('gives milk')),\n",
" (7, Fact('mammal')),\n",
" (8, Fact('carnivor')),\n",
" (9, Fact(animal='tiger'))])"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ex1 = Animals()\n",
"ex1.reset()\n",
"ex1.factz([\n",
" Fact(color='red-brown'),\n",
" Fact(pattern='dark stripes'),\n",
" Fact('sharp teeth'),\n",
" Fact('claws'),\n",
" Fact('forward looking eyes'),\n",
" Fact('gives milk')])\n",
"ex1.run()\n",
"ex1.facts"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n\n<!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**Αποποίηση ευθυνών**: \nΑυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία μετάφρασης AI [Co-op Translator](https://github.com/Azure/co-op-translator). Παρότι επιδιώκουμε ακρίβεια, παρακαλούμε να γνωρίζετε ότι οι αυτοματοποιημένες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα πρέπει να θεωρείται ως η έγκυρη πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική μετάφραση από άνθρωπο. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή λανθασμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης.\n<!-- CO-OP TRANSLATOR DISCLAIMER END -->\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.7.4 64-bit (conda)",
"metadata": {
"interpreter": {
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
}
},
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.2"
},
"coopTranslator": {
"original_hash": "8ef43db4b9182239fd150a76bd494fdb",
"translation_date": "2026-01-15T14:05:47+00:00",
"source_file": "lessons/2-Symbolic/Animals.ipynb",
"language_code": "el"
}
},
"nbformat": 4,
"nbformat_minor": 2
}