├── projects ├── TSP │ ├── GA │ │ ├── __init__.py │ │ ├── test │ │ │ ├── __init__.py │ │ │ └── test_tsp_ga.py │ │ └── tsp_ga.py │ └── pyswarm.py ├── seminar │ └── assets │ │ ├── cv.png │ │ ├── rcnn.png │ │ ├── roi.png │ │ ├── ross.png │ │ ├── tasks.png │ │ ├── rcnn-2.png │ │ ├── ImageNet-1.png │ │ ├── fast-rcnn.png │ │ ├── mask-rcnn.png │ │ ├── rcnn-conv.png │ │ ├── rcnn-prob.png │ │ ├── deeplearning.png │ │ ├── fast-rcnn-1.png │ │ ├── faster-rcnn.png │ │ ├── mask-rcnn-1.png │ │ ├── mask-rcnn-2.png │ │ ├── classification.png │ │ └── understanding.png ├── sudoku │ ├── images │ │ ├── fiinished.png │ │ ├── sudoku-board-bare.jpg │ │ ├── Screenshot_20170831_204744.png │ │ └── Screenshot_20170831_204758.png │ ├── utils │ │ ├── __init__.py │ │ ├── assets.py │ │ └── SudokuSquare.py │ ├── README.md │ ├── visualizer.py │ ├── PySudoku.py │ ├── solver.py │ └── solver_test.py └── Naive-Bayes │ └── text-classification-naive-bayes.ipynb ├── 01-Artificial-Intelligence ├── __init__.py ├── tests │ ├── __init__.py │ ├── pytest.ini │ └── test_agents.py ├── assignments │ ├── images │ │ ├── fig2.2 │ │ ├── fig2-2.png │ │ └── fig2-3.png │ ├── Exercise 2.4.ipynb │ └── AI in 2030_REPORT-summary.ipynb ├── 1-Introduction │ ├── Summary-of-Turing-original-paper-on-AI.md │ └── introduction.ipynb ├── agents.py └── 2-Intelligent-agents │ └── intelligent-agents.ipynb ├── papers └── ai_100_report_0901fnlc_single (1)(1).pdf ├── ci ├── dl_env.py └── install_python.ps1 ├── environments ├── dl_env_mac.yml ├── dl_env_linux_gpu.yml ├── dl_env_windows.yml ├── dl_env_linux.yml ├── README.md ├── dl_env_linux-v2.yml └── dl_env_linux_gpu-v2.yml ├── LICENSE ├── appveyor.yml ├── .travis.yml ├── .gitignore ├── README.md └── 02-Problem-Solving └── 03-Search └── search.ipynb /projects/TSP/GA/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /projects/TSP/GA/test/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /01-Artificial-Intelligence/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /01-Artificial-Intelligence/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /01-Artificial-Intelligence/assignments/images/fig2.2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /01-Artificial-Intelligence/tests/pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | filterwarnings = 3 | ignore::ResourceWarning -------------------------------------------------------------------------------- /projects/seminar/assets/cv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/cv.png -------------------------------------------------------------------------------- /projects/seminar/assets/rcnn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/rcnn.png -------------------------------------------------------------------------------- /projects/seminar/assets/roi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/roi.png -------------------------------------------------------------------------------- /projects/seminar/assets/ross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/ross.png -------------------------------------------------------------------------------- /projects/seminar/assets/tasks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/tasks.png -------------------------------------------------------------------------------- /projects/seminar/assets/rcnn-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/rcnn-2.png -------------------------------------------------------------------------------- /projects/seminar/assets/ImageNet-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/ImageNet-1.png -------------------------------------------------------------------------------- /projects/seminar/assets/fast-rcnn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/fast-rcnn.png -------------------------------------------------------------------------------- /projects/seminar/assets/mask-rcnn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/mask-rcnn.png -------------------------------------------------------------------------------- /projects/seminar/assets/rcnn-conv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/rcnn-conv.png -------------------------------------------------------------------------------- /projects/seminar/assets/rcnn-prob.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/rcnn-prob.png -------------------------------------------------------------------------------- /projects/sudoku/images/fiinished.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/sudoku/images/fiinished.png -------------------------------------------------------------------------------- /projects/seminar/assets/deeplearning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/deeplearning.png -------------------------------------------------------------------------------- /projects/seminar/assets/fast-rcnn-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/fast-rcnn-1.png -------------------------------------------------------------------------------- /projects/seminar/assets/faster-rcnn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/faster-rcnn.png -------------------------------------------------------------------------------- /projects/seminar/assets/mask-rcnn-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/mask-rcnn-1.png -------------------------------------------------------------------------------- /projects/seminar/assets/mask-rcnn-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/mask-rcnn-2.png -------------------------------------------------------------------------------- /projects/seminar/assets/classification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/classification.png -------------------------------------------------------------------------------- /projects/seminar/assets/understanding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/seminar/assets/understanding.png -------------------------------------------------------------------------------- /projects/sudoku/images/sudoku-board-bare.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/sudoku/images/sudoku-board-bare.jpg -------------------------------------------------------------------------------- /papers/ai_100_report_0901fnlc_single (1)(1).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/papers/ai_100_report_0901fnlc_single (1)(1).pdf -------------------------------------------------------------------------------- /projects/sudoku/images/Screenshot_20170831_204744.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/sudoku/images/Screenshot_20170831_204744.png -------------------------------------------------------------------------------- /projects/sudoku/images/Screenshot_20170831_204758.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/projects/sudoku/images/Screenshot_20170831_204758.png -------------------------------------------------------------------------------- /ci/dl_env.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | 3 | a = tf.constant(5) 4 | b = tf.constant(6) 5 | c = tf.add(a, b) 6 | 7 | with tf.Session() as sess: 8 | assert sess.run(c) == 11 9 | -------------------------------------------------------------------------------- /01-Artificial-Intelligence/assignments/images/fig2-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/01-Artificial-Intelligence/assignments/images/fig2-2.png -------------------------------------------------------------------------------- /01-Artificial-Intelligence/assignments/images/fig2-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andersy005/artificial-intelligence/master/01-Artificial-Intelligence/assignments/images/fig2-3.png -------------------------------------------------------------------------------- /projects/sudoku/utils/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Thu Aug 31 20:14:15 2017 5 | 6 | @author: Anderson Banihirwe 7 | """ 8 | 9 | -------------------------------------------------------------------------------- /01-Artificial-Intelligence/tests/test_agents.py: -------------------------------------------------------------------------------- 1 | import random 2 | from agents import Agent 3 | 4 | random.seed("airtificial-seed") 5 | 6 | def test_agent(): 7 | a = Agent() 8 | assert isinstance(a, Agent) 9 | -------------------------------------------------------------------------------- /environments/dl_env_mac.yml: -------------------------------------------------------------------------------- 1 | name: dl 2 | channels: 3 | - menpo 4 | - conda-forge 5 | - defaults 6 | dependencies: 7 | - python=3.6 8 | - numpy 9 | - scipy 10 | - pandas 11 | - jupyter 12 | - pillow 13 | - tensorflow 14 | - nltk 15 | - keras 16 | - scikit-image 17 | - scikit-learn 18 | - seaborn 19 | - bokeh 20 | - opencv3 21 | - flask 22 | - flask-socketio 23 | - cvxopt 24 | -------------------------------------------------------------------------------- /environments/dl_env_linux_gpu.yml: -------------------------------------------------------------------------------- 1 | name: dl-gpu 2 | channels: 3 | - menpo 4 | - conda-forge 5 | - defaults 6 | dependencies: 7 | - python=3.6 8 | - numpy 9 | - scipy 10 | - pandas 11 | - jupyter 12 | - pillow 13 | - tensorflow-gpu 14 | - nltk 15 | - keras 16 | - scikit-image 17 | - scikit-learn 18 | - seaborn 19 | - bokeh 20 | - opencv3 21 | - flask 22 | - flask-socketio 23 | - cvxopt 24 | -------------------------------------------------------------------------------- /environments/dl_env_windows.yml: -------------------------------------------------------------------------------- 1 | name: dl 2 | channels: 3 | - menpo 4 | - conda-forge 5 | - defaults 6 | dependencies: 7 | - python=3.6 8 | - numpy 9 | - scipy 10 | - pandas 11 | - jupyter 12 | - pillow 13 | - tensorflow 14 | - nltk 15 | - keras 16 | - scikit-image 17 | - scikit-learn 18 | - seaborn 19 | - bokeh 20 | - opencv3 21 | - flask 22 | - flask-socketio 23 | - cvxopt 24 | -pip: 25 | - coverage 26 | - coveralls 27 | - codecov 28 | - pytest 29 | -------------------------------------------------------------------------------- /environments/dl_env_linux.yml: -------------------------------------------------------------------------------- 1 | name: dl 2 | channels: 3 | - menpo 4 | - conda-forge 5 | - defaults 6 | dependencies: 7 | - python=3.6 8 | - numpy 9 | - scipy 10 | - pandas 11 | - jupyter 12 | - pillow 13 | - tensorflow 14 | - nltk 15 | - keras 16 | - scikit-image 17 | - scikit-learn 18 | - seaborn 19 | - bokeh 20 | - opencv3 21 | - flask 22 | - flask-socketio 23 | - cvxopt 24 | - pip: 25 | - coverage 26 | - coveralls 27 | - codecov 28 | - pytest 29 | -------------------------------------------------------------------------------- /projects/TSP/GA/test/test_tsp_ga.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../'))) 4 | 5 | from tsp_ga import * 6 | 7 | cities = Cities(5) 8 | tours = alltours(cities) 9 | 10 | def test_cities(): 11 | assert isinstance(cities, frozenset) 12 | 13 | 14 | def test_alltours(): 15 | assert len(tours) == 24 16 | 17 | def test_tour_length(): 18 | assert tour_length(tours) != None 19 | 20 | def test_plot(): 21 | pass 22 | -------------------------------------------------------------------------------- /projects/sudoku/utils/assets.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Thu Aug 31 20:15:04 2017 5 | 6 | @author: Anderson Banihirwe 7 | """ 8 | 9 | import os 10 | import pygame 11 | 12 | def load_image(name): 13 | fullpath = os.path.join("images", name) 14 | try: 15 | image = pygame.image.load(fullpath) 16 | if image.get_alpha() == None: 17 | image = image.convert() 18 | 19 | else: 20 | image = image.convert_alpha() 21 | 22 | 23 | except pygame.error: 24 | print("Oops! Could not load image:", fullpath) 25 | 26 | return image, image.get_rect() 27 | -------------------------------------------------------------------------------- /projects/sudoku/README.md: -------------------------------------------------------------------------------- 1 | # Diagonal Sudoku Solver 2 | 3 | ![](https://i.imgur.com/SJVEeg8.png) 4 | 5 | ![](https://i.imgur.com/PnCj7Pu.png) 6 | 7 | The function (naked_twins) first looks for all boxes with only two values inside. The function then iterates over these boxes, finds all units the current box is a member of. Now having a box and a unit, the function looks for identical boxes. I a match is found, the boxes are called naked twins, and the values of this naked twins can be removed from all other boxes in the current unit. 8 | 9 | One important note to make is that it is tempting to detect pairs in all boxes, and flag them as candidates, and process through them one at the time. It is important to chech if the box previously flagged as pair, can have been pruned down to a single value in an earlier naked twin detection. A last check if the box is still a pair is important. 10 | 11 | -------------------------------------------------------------------------------- /projects/sudoku/visualizer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Thu Aug 31 20:32:37 2017 5 | 6 | @author: Anderson Banihirwe 7 | """ 8 | 9 | 10 | from PySudoku import play 11 | 12 | def visualize_assignments(assignments): 13 | """ Visualizes the set of assignments created by the Sudoku AI""" 14 | last_assignment = None 15 | filtered_assignments = [] 16 | 17 | for i in range(len(assignments)): 18 | if last_assignment: 19 | last_assignment_items = [item for item in last_assignment.items() if len(item[1]) == 1] 20 | current_assignment_items = [item for item in assignments[i].items() if len(item[1]) == 1] 21 | shared_items = set(last_assignment_items) & set(current_assignment_items) 22 | if len(shared_items) < len(current_assignment_items): 23 | filtered_assignments.append(assignments[i]) 24 | last_assignment = assignments[i] 25 | 26 | play(filtered_assignments) -------------------------------------------------------------------------------- /01-Artificial-Intelligence/1-Introduction/Summary-of-Turing-original-paper-on-AI.md: -------------------------------------------------------------------------------- 1 | # [COMPUTING MACHINERY AND INTELLIGENCE](http://www.loebner.net/Prizef/TuringArticle.html) 2 |
By A. M. Turing
3 | 4 | ## The Imitation Game 5 | >"Can machines think?" 6 | 7 | - To define the meaning of the terms **machine** and **think**, Turing proposes a new form of the problem that can be described in terms of an imitation game. 8 | 9 | - The game is played with three people: 10 | - A man (A) 11 | - A woman (B) 12 | - An interrogator (C) 13 | - The interrogator stays in a room apart from the other two. 14 | 15 | - The object of the game for the interrogator is to determine which of the other two is the man and which is the woman. 16 | 17 | - He knows them by labels X and Y, and at the end of the game he says either **X is A and Y is B** or **X is B and Y is A**. 18 | 19 | - The answers should be written, or better still, typewritten. 20 | 21 | >What will happen when a machine takes the part of A in this game? -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Anderson Banihirwe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # CI on Windows via appveyor 2 | # Adapted (minorly) from xarray's appveyor.yml, which itself 3 | # was based on Olivier Grisel's python-appveyor-demo 4 | 5 | environment: 6 | 7 | matrix: 8 | - PYTHON: "C:\\Python36-conda64" 9 | PYTHON_VERSION: "3.6" 10 | PYTHON_ARCH: "64" 11 | CONDA_ENV: "py36" 12 | 13 | install: 14 | # Install miniconda Python 15 | - "powershell ./ci/install_python.ps1" 16 | 17 | # Prepend newly installed Python to the PATH of this build (this cannot be 18 | # done from inside the powershell script as it would require to restart 19 | # the parent CMD process). 20 | - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" 21 | 22 | # Check that we have the expected version and architecture for Python 23 | - "python --version" 24 | - "python -c \"import struct; print(struct.calcsize('P') * 8)\"" 25 | 26 | # install xarray and depenencies 27 | - "conda --version" 28 | - "conda list" 29 | - "conda env create -f environments\\dl_windows.yml" 30 | - "activate dl" 31 | - "conda list" 32 | 33 | test_script: 34 | - "coverage run -m pytest" 35 | - "coverage report -m" 36 | 37 | on_success: 38 | - "coveralls" 39 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | notifications: 2 | email: false 3 | 4 | sudo: required 5 | 6 | dist: trusty 7 | 8 | language: python 9 | python: 10 | - "3.6" 11 | 12 | install: 13 | - sudo apt-get update 14 | # We do this conditionally because it saves us some downloading if the 15 | # version is the same. 16 | - if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then 17 | wget https://repo.continuum.io/miniconda/Miniconda2-latest-Linux-x86_64.sh -O miniconda.sh; 18 | else 19 | wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; 20 | fi 21 | - bash miniconda.sh -b -p $HOME/miniconda 22 | - export PATH="$HOME/miniconda/bin:$PATH" 23 | - hash -r 24 | - conda config --set always_yes yes --set changeps1 no 25 | - conda update -q conda 26 | # Useful for debugging any issues with conda 27 | - conda info -a 28 | 29 | # Create dl environment with packages from dl_env_linux.yml file 30 | #- conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION --file ./ci/requirements.txt 31 | - conda env create -f ./environments/dl_env_linux.yml 32 | 33 | before_script: 34 | - source activate dl 35 | - conda list 36 | 37 | script: 38 | - coverage run -m pytest 39 | - coverage report -m 40 | 41 | 42 | 43 | after_success: 44 | - bash <(curl -s https://codecov.io/bash) 45 | - codecov 46 | - coveralls 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints 2 | *.ppt 3 | *.zip 4 | AI-ML 5 | .idea/workspace.xml 6 | .idea/vcs.xml 7 | .idea/modules.xml 8 | .idea/artificial-intelligence.iml 9 | .idea/misc.xml 10 | *.pyc 11 | 12 | 13 | 14 | # Byte-compiled / optimized / DLL files 15 | __pycache__/ 16 | *.py[cod] 17 | *$py.class 18 | 19 | # C extensions 20 | *.so 21 | 22 | # Distribution / packaging 23 | .Python 24 | env/ 25 | build/ 26 | develop-eggs/ 27 | dist/ 28 | downloads/ 29 | eggs/ 30 | .eggs/ 31 | lib/ 32 | lib64/ 33 | parts/ 34 | sdist/ 35 | var/ 36 | wheels/ 37 | *.egg-info/ 38 | .installed.cfg 39 | *.egg 40 | 41 | # PyInstaller 42 | # Usually these files are written by a python script from a template 43 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 44 | *.manifest 45 | *.spec 46 | 47 | # Installer logs 48 | pip-log.txt 49 | pip-delete-this-directory.txt 50 | 51 | # Unit test / coverage reports 52 | htmlcov/ 53 | .tox/ 54 | .coverage 55 | .coverage.* 56 | .cache 57 | nosetests.xml 58 | coverage.xml 59 | *.cover 60 | .hypothesis/ 61 | 62 | # Translations 63 | *.mo 64 | *.pot 65 | 66 | # Django stuff: 67 | *.log 68 | local_settings.py 69 | 70 | # Flask stuff: 71 | instance/ 72 | .webassets-cache 73 | 74 | # Scrapy stuff: 75 | .scrapy 76 | 77 | # Sphinx documentation 78 | docs/_build/ 79 | 80 | # PyBuilder 81 | target/ 82 | 83 | # Jupyter Notebook 84 | .ipynb_checkpoints 85 | 86 | # pyenv 87 | .python-version 88 | 89 | # celery beat schedule file 90 | celerybeat-schedule 91 | 92 | # SageMath parsed files 93 | *.sage.py 94 | 95 | # dotenv 96 | .env 97 | 98 | # virtualenv 99 | .venv 100 | venv/ 101 | ENV/ 102 | 103 | # Spyder project settings 104 | .spyderproject 105 | .spyproject 106 | 107 | # Rope project settings 108 | .ropeproject 109 | 110 | # mkdocs documentation 111 | /site 112 | 113 | # mypy 114 | .mypy_cache/ 115 | -------------------------------------------------------------------------------- /projects/sudoku/PySudoku.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Thu Aug 31 19:28:33 2017 5 | 6 | @author: Anderson Banihirwe 7 | """ 8 | 9 | import sys 10 | import os 11 | import random 12 | import pygame 13 | sys.path.append(os.path.join("utils")) 14 | import SudokuSquare 15 | from assets import * 16 | 17 | digits = '123456789' 18 | rows = 'ABCDEFGHI' 19 | 20 | def play(values_list): 21 | pygame.init() 22 | 23 | 24 | size = width, height = 700, 700 25 | screen = pygame.display.set_mode(size) 26 | 27 | background_image = pygame.image.load("./images/sudoku-board-bare.jpg").convert() 28 | 29 | clock = pygame.time.Clock() 30 | 31 | # The puzzleNumber sets a seed so either generate 32 | # a random number to fill in here or accept user 33 | # input for a duplicatable puzzle. 34 | 35 | for values in values_list: 36 | pygame.event.pump() 37 | theSquares = [] 38 | initXLoc = 0 39 | initYLoc = 0 40 | startX, startY, editable, number = 0, 0, "N", 0 41 | for y in range(9): 42 | for x in range(9): 43 | if x in (0, 1, 2): startX = (x * 57) + 38 44 | if x in (3, 4, 5): startX = (x * 57) + 99 45 | if x in (6, 7, 8): startX = (x * 57) + 159 46 | 47 | if y in (0, 1, 2): startY = (y * 57) + 35 48 | if y in (3, 4, 5): startY = (y * 57) + 100 49 | if y in (6, 7, 8): startY = (y * 57) + 165 50 | col = digits[y] 51 | row = rows[x] 52 | string_number = values[row + col] 53 | if len(string_number) > 1 or string_number == '' or string_number == '.': 54 | number = None 55 | else: 56 | number = int(string_number) 57 | theSquares.append(SudokuSquare.SudokuSquare(number, startX, startY, editable, x, y)) 58 | 59 | screen.blit(background_image, (0, 0)) 60 | for num in theSquares: 61 | num.draw() 62 | 63 | pygame.display.flip() 64 | pygame.display.update() 65 | clock.tick(5) 66 | 67 | 68 | if __name__ == "__main__": 69 | main() 70 | sys.exit() 71 | -------------------------------------------------------------------------------- /environments/README.md: -------------------------------------------------------------------------------- 1 | 2 | # How to Setup a Python Environment for Machine Learning and Deep Learning with Anaconda 3 | 4 | ## 1. Download the Anaconda Python package for your platform 5 | 6 | 1. Visit the [Anaconda homepage](https://www.continuum.io/). 7 | 2. Click “Anaconda” from the menu and click “Download” to go to the [download page](https://www.continuum.io/downloads). 8 | ![](http://3qeqpr26caki16dnhd19sv6by6v.wpengine.netdna-cdn.com/wp-content/uploads/2017/02/Click-Anaconda-and-Download.png) 9 | 10 | 3. Choose the download suitable for your platform (Windows, OSX, or Linux): 11 | - Choose Python 3.6 12 | - Choose the Graphical Installer(Windows, OSX) 13 | 14 | ![](https://i.imgur.com/4zkN7XG.png) 15 | 16 | This will download the Anaconda Python package to your workstation. 17 | 18 | ## 2. Detailed Anaconda installation information 19 | This step assumes you have sufficient administrative privileges to install software on your system. 20 | For installation instructions, see the following: 21 | 22 | - **Installing on Windows** (https://docs.continuum.io/anaconda/install/windows) 23 | - **Installing on macOS** (https://docs.continuum.io/anaconda/install/mac-os) 24 | - **Installing on Linux** (https://docs.continuum.io/anaconda/install/linux) 25 | 26 | ## 3. Creating an environment from an environment.yml file 27 | 28 | In this step, we will install Python libraries used for deep learning, specifically: Theano, TensorFlow, and Keras, nltk. 29 | Most of machine learning and deep learning libraries needed are provided in the ```yaml (.yml)``` files. 30 | 31 | 1. Create the environment from the ```environment.yml``` file 32 | - **Linux CPU only** 33 | ```sh 34 | $ conda env create -f dl_env_linux.yml 35 | ``` 36 | - **Linux With GPU support** 37 | ```sh 38 | $ conda env create -f dl_env_linux_gpu.yml 39 | ``` 40 | 41 | - **Windows CPU only** 42 | ```sh 43 | $ conda env create -f dl_env_windows.yml 44 | ``` 45 | 46 | - **macOS CPU only** 47 | ```sh 48 | $ conda env create -f dl_env_mac.yml 49 | ``` 50 | 51 | 2. Activate the new environment: 52 | 53 | - Windows: ```activate myenv``` 54 | - macOS and Linux: ```source activate myenv``` 55 | 56 | NOTE: Replace myenv with the name of the environment. 57 | 58 | 3. Verify that the new environment was installed correctly: 59 | 60 | ```sh 61 | $ conda list 62 | ``` 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | | **Linux/OSX** | [![Build Status](https://travis-ci.org/andersy005/artificial-intelligence.svg?branch=master)](https://travis-ci.org/andersy005/artificial-intelligence) | 2 | |---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 3 | | **Windows** | [![Build status](https://ci.appveyor.com/api/projects/status/u8k0ijc6qc2s17at/branch/master?svg=true)](https://ci.appveyor.com/project/andersy005/artificial-intelligence/branch/master) | 4 | 5 | 6 | [![Coverage Status](https://coveralls.io/repos/github/andersy005/artificial-intelligence/badge.svg?branch=master)](https://coveralls.io/github/andersy005/artificial-intelligence?branch=master) 7 | 8 | ![](http://aima.cs.berkeley.edu/cover2.jpg) 9 | # Artificial Intelligence - CPSC 4383 10 | 11 | Instructor: [ Mariofanna Milanova](http://ualr.edu/mgmilanova/index.html) 12 | 13 | This repo contains all my work: code base, notes, exercises and solutions to accompany Russell And Norvig's "Artificial Intelligence - A Modern Approach" and CPSC 4383/5383 Course. 14 | 15 | The screenshots and images are taken from, unless specified, [Artificial Intelligence: A Modern Approach](http://aima.cs.berkeley.edu/). 16 | 17 | 18 | >AI is defined as the study of agents that receive percepts from the environment and perform actions. Each such agent implements a function that maps percept sequences to actions. 19 | 20 | 21 | Implementations in Java, C++, and Python of many of the algorithms discussed in the textbook are available in the authors' [online code repository](http://aima.cs.berkeley.edu/code.html) 22 | 23 | 24 | ## Table of Contents 25 | 26 | - [ ] [Artificial Intelligence](https://github.com/andersy005/artificial-intelligence/tree/master/01-Artificial-Intelligence) 27 | - [ ] [Introduction](https://github.com/andersy005/artificial-intelligence/tree/master/01-Artificial-Intelligence/1-Introduction) 28 | - [ ] [Intelligent Agents](https://github.com/andersy005/artificial-intelligence/tree/master/01-Artificial-Intelligence/2-Intelligent-agents) 29 | 30 | - [ ] [Problem-solving]() 31 | - [ ] [Solving Problems by Searching]() 32 | - [ ] [Beyond Classical Search]() 33 | - [ ] [Adversarial Search]() 34 | - [ ] [Constraint Satisfaction]() 35 | -------------------------------------------------------------------------------- /projects/TSP/GA/tsp_ga.py: -------------------------------------------------------------------------------- 1 | import random 2 | import time 3 | import statistics 4 | import itertools 5 | import functools 6 | import matplotlib.pyplot as plt 7 | import matplotlib 8 | matplotlib.style.use('seaborn') 9 | import numpy as np 10 | 11 | 12 | 13 | 14 | #------------------- Representing Cities--------------------------# 15 | class Point(complex): 16 | """Cities are represented as Points, 17 | which are a subclass of complex numbers.""" 18 | 19 | 20 | x = property(lambda p: p.real) 21 | y = property(lambda p: p.imag) 22 | 23 | City = Point 24 | 25 | 26 | def Cities(n, width=900, height=600, seed=1234): 27 | "Make a set of n cities, each with random coordinates within a (width x height) rectangle." 28 | random.seed(seed * n) 29 | return frozenset((City(random.randrange(width), random.randrange(height)) 30 | for c in range(n))) 31 | 32 | 33 | #-------------------Distance Between two cities ------------------# 34 | def distance(A, B): 35 | """Function to calculate the distance between two points""" 36 | return abs(A - B) 37 | 38 | 39 | #------------------------ Tours----------------------------------# 40 | def alltours(cities): 41 | """Return a list of tours, each a permutation of cities, but 42 | each one starting with the same city. 43 | 44 | So let's arbitrarily say that all tours must start with the first city in 45 | the set of cities. We'll just pull the first city out, and then tack 46 | it back on to all the permutations of the rest of the cities. 47 | This helps us keep all non-redundant tours only. 48 | """ 49 | start = first(cities) 50 | return [[start] + Tour(rest) 51 | for rest in itertools.permutations(cities - {start})] 52 | 53 | def first(collection): 54 | """Start iterating over collection, and return the first element 55 | """ 56 | return next(iter(collection)) 57 | 58 | Tour = list # Tours are implemented as lists of cities. 59 | 60 | 61 | def tour_length(tours): 62 | "The total of distances between each pair of consecutive cities in the tour." 63 | dist_air = [] 64 | for i in range(len(tours)): 65 | dist_air.append(sum([distance(tours[i][j], tours[i][j-1]) for j in range(len(tours[i]))])) 66 | 67 | return dist_air 68 | 69 | 70 | 71 | #---------------------- Plotting------------------------------------# 72 | def plot_tour(tour): 73 | "Plot the cities as circles and the tour as lines between them." 74 | plot_lines(list(tour) + [tour[0]]) 75 | 76 | def plot_lines(points, style='bo-'): 77 | "Plot lines to connect a series of points." 78 | plt.plot([p.x for p in points], [p.y for p in points], style) 79 | plt.axis('scaled'); plt.axis('off') 80 | plt.show() 81 | 82 | 83 | 84 | if __name__ == "__main__": 85 | cities = Cities(5) 86 | #print(cities) 87 | #print(alltours(cities)) 88 | tour_length(alltours(cities)) 89 | for i in alltours(cities): 90 | plot_tour(i) 91 | -------------------------------------------------------------------------------- /ci/install_python.ps1: -------------------------------------------------------------------------------- 1 | # Sample script to install Python and pip under Windows 2 | # Authors: Olivier Grisel, Jonathan Helmus and Kyle Kastner 3 | # License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ 4 | 5 | $MINICONDA_URL = "http://repo.continuum.io/miniconda/" 6 | $BASE_URL = "https://www.python.org/ftp/python/" 7 | 8 | 9 | function DownloadMiniconda ($python_version, $platform_suffix) { 10 | $webclient = New-Object System.Net.WebClient 11 | if ($python_version -match "3.6") { 12 | $filename = "Miniconda3-latest-Windows-" + $platform_suffix + ".exe" 13 | } else { 14 | $filename = "Miniconda2-latest-Windows-" + $platform_suffix + ".exe" 15 | } 16 | $url = $MINICONDA_URL + $filename 17 | 18 | $basedir = $pwd.Path + "\" 19 | $filepath = $basedir + $filename 20 | if (Test-Path $filename) { 21 | Write-Host "Reusing" $filepath 22 | return $filepath 23 | } 24 | 25 | # Download and retry up to 3 times in case of network transient errors. 26 | Write-Host "Downloading" $filename "from" $url 27 | $retry_attempts = 2 28 | for($i=0; $i -lt $retry_attempts; $i++){ 29 | try { 30 | $webclient.DownloadFile($url, $filepath) 31 | break 32 | } 33 | Catch [Exception]{ 34 | Start-Sleep 1 35 | } 36 | } 37 | if (Test-Path $filepath) { 38 | Write-Host "File saved at" $filepath 39 | } else { 40 | # Retry once to get the error message if any at the last try 41 | $webclient.DownloadFile($url, $filepath) 42 | } 43 | return $filepath 44 | } 45 | 46 | 47 | function InstallMiniconda ($python_version, $architecture, $python_home) { 48 | Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home 49 | if (Test-Path $python_home) { 50 | Write-Host $python_home "already exists, skipping." 51 | return $false 52 | } 53 | if ($architecture -match "32") { 54 | $platform_suffix = "x86" 55 | } else { 56 | $platform_suffix = "x86_64" 57 | } 58 | 59 | $filepath = DownloadMiniconda $python_version $platform_suffix 60 | Write-Host "Installing" $filepath "to" $python_home 61 | $install_log = $python_home + ".log" 62 | $args = "/S /D=$python_home" 63 | Write-Host $filepath $args 64 | Start-Process -FilePath $filepath -ArgumentList $args -Wait -Passthru 65 | if (Test-Path $python_home) { 66 | Write-Host "Python $python_version ($architecture) installation complete" 67 | } else { 68 | Write-Host "Failed to install Python in $python_home" 69 | Get-Content -Path $install_log 70 | Exit 1 71 | } 72 | } 73 | 74 | 75 | function InstallCondaPackages ($python_home, $spec) { 76 | $conda_path = $python_home + "\Scripts\conda.exe" 77 | $args = "install --yes " + $spec 78 | Write-Host ("conda " + $args) 79 | Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru 80 | } 81 | 82 | function UpdateConda ($python_home) { 83 | $conda_path = $python_home + "\Scripts\conda.exe" 84 | Write-Host "Updating conda..." 85 | $args = "update --yes conda" 86 | Write-Host $conda_path $args 87 | Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru 88 | } 89 | 90 | 91 | function main () { 92 | InstallMiniconda $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON 93 | UpdateConda $env:PYTHON 94 | InstallCondaPackages $env:PYTHON "conda-build jinja2 anaconda-client" 95 | } 96 | 97 | main 98 | -------------------------------------------------------------------------------- /01-Artificial-Intelligence/assignments/Exercise 2.4.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "**Anderson Banihirwe**\n", 8 | "\n", 9 | "**August 21, 2017**\n", 10 | "\n", 11 | "**CPSC 4383**" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "# Task 1: Exercise 2.4" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "Let us examine the rationality of various vacuum-cleaner agent functions ( Figure 2.2 ):\n", 26 | "![](images/fig2-2.png)\n", 27 | "\n", 28 | "![](images/fig2-3.png)\n", 29 | "A) Show that the simple vacuum-cleaner agent function described in Figure 2.3 is indeed rational under the assumptions listed on page 38\n", 30 | "\n", 31 | ">Page 38 describes an environment which is partially observable, deterministic and static; as such, the tabular agent in Fig. 2.3 can expect to maximize its utility in no more than four actions (the worst case is A: dirty, B: dirty; which results in either suck, right, suck, left, ... or suck, left, suck, right, ...).\n", 32 | "There is no time to e.g. build a model of dirt, since the dirt doesn't replentish itself.\n", 33 | "\n" 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "B) Describe a rational agent function for the modified performance measure that deducts one point for each movement. Does the corresponding agent program require internal state?" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | ">The agent does require internal state: it should know, for instance, whether it has cleaned every square; and, if so, should stop." 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "C) Discuss possible agent designs for the cases in which clean squares can become dirty and the geography of the environment is unknown. Does it make sense for the agent to learn from its experience in these cases? If so, what should it learn ." 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | ">It should learn the geography of its environment to avoid wasting time trying to move off of it; it could maintain, furthermore, a dirt-distribution across the grid and favor those squares that tend to get dirty." 62 | ] 63 | } 64 | ], 65 | "metadata": { 66 | "kernelspec": { 67 | "display_name": "Python 3", 68 | "language": "python", 69 | "name": "python3" 70 | }, 71 | "language_info": { 72 | "codemirror_mode": { 73 | "name": "ipython", 74 | "version": 3 75 | }, 76 | "file_extension": ".py", 77 | "mimetype": "text/x-python", 78 | "name": "python", 79 | "nbconvert_exporter": "python", 80 | "pygments_lexer": "ipython3", 81 | "version": "3.6.2" 82 | }, 83 | "toc": { 84 | "colors": { 85 | "hover_highlight": "#DAA520", 86 | "navigate_num": "#000000", 87 | "navigate_text": "#333333", 88 | "running_highlight": "#FF0000", 89 | "selected_highlight": "#FFD700", 90 | "sidebar_border": "#EEEEEE", 91 | "wrapper_background": "#FFFFFF" 92 | }, 93 | "moveMenuLeft": true, 94 | "nav_menu": { 95 | "height": "30px", 96 | "width": "252px" 97 | }, 98 | "navigate_menu": true, 99 | "number_sections": false, 100 | "sideBar": true, 101 | "threshold": 4, 102 | "toc_cell": false, 103 | "toc_section_display": "block", 104 | "toc_window_display": true, 105 | "widenNotebook": false 106 | } 107 | }, 108 | "nbformat": 4, 109 | "nbformat_minor": 2 110 | } 111 | -------------------------------------------------------------------------------- /01-Artificial-Intelligence/agents.py: -------------------------------------------------------------------------------- 1 | """Implement Agents and Environments (Chapters 1-2). 2 | The class hierarchies are as follows: 3 | Thing ## A physical object that can exist in an environment 4 | Agent 5 | Wumpus 6 | Dirt 7 | Wall 8 | ... 9 | Environment ## An environment holds objects, runs simulations 10 | XYEnvironment 11 | VacuumEnvironment 12 | WumpusEnvironment 13 | An agent program is a callable instance, taking percepts and choosing actions 14 | SimpleReflexAgentProgram 15 | ... 16 | EnvGUI ## A window with a graphical representation of the Environment 17 | EnvToolbar ## contains buttons for controlling EnvGUI 18 | EnvCanvas ## Canvas to display the environment of an EnvGUI 19 | """ 20 | 21 | import numpy as np 22 | import collections 23 | import copy 24 | 25 | 26 | class Thing: 27 | """This represents any physical object that can appear in an Environment. 28 | You subclass Thing to get the things you want. Each thing can have a 29 | .__name__ slot (used for output only).""" 30 | def __repr__(self): 31 | return '<{}>'.format(getattr(self, '__name__', self.__class__.__name__)) 32 | 33 | def is_alive(self): 34 | """Things that are 'alive' should return true.""" 35 | return hasattr(self, 'alive') and self.alive 36 | 37 | def show_state(self): 38 | """Display the agent's internal state. Subclasses should override.""" 39 | print("I don't know how to show_state.") 40 | 41 | def display(self, canvas, x, y, width, height): 42 | """Display an image of this Thing on the canvas.""" 43 | # Do we need this? 44 | pass 45 | 46 | 47 | class Agent(Thing): 48 | """An Agent is a subclass of Thing with one required slot, 49 | .program, which should hold a function that takes one argument, the 50 | percept, and returns an action. (What counts as a percept or action 51 | will depend on the specific environment in which the agent exists.) 52 | Note that 'program' is a slot, not a method. If it were a method, 53 | then the program could 'cheat' and look at aspects of the agent. 54 | It's not supposed to do that: the program can only look at the 55 | percepts. An agent program that needs a model of the world (and of 56 | the agent itself) will have to build and maintain its own model. 57 | There is an optional slot, .performance, which is a number giving 58 | the performance measure of the agent in its environment.""" 59 | 60 | def __init__(self, program=None): 61 | self.alive = True 62 | self.bump = False 63 | self.holding = [] 64 | self.performance = 0 65 | if program is None or not isinstance(program, collections.Callable): 66 | print("Can't find a valid program for {}, falling back to default.".format( 67 | self.__class__.__name__)) 68 | 69 | def program(percept): 70 | return eval(input('Percept={}; action? '.format(percept))) 71 | 72 | self.program = program 73 | 74 | def can_grab(self, thing): 75 | """Returns True if this agent can grab this thing. 76 | Override for appropriate subclasses of Agent and Thing.""" 77 | return False 78 | 79 | def TraceAgent(agent): 80 | """Wrap the agent's program to print its input and output. This will let 81 | you see what the agent is doing in the environment.""" 82 | old_program = agent.program 83 | 84 | def new_program(percept): 85 | action = old_program(percept) 86 | print('{} perceives {} and does {}'.format(agent, percept, action)) 87 | return action 88 | 89 | agent.program = new_program 90 | return agent 91 | 92 | 93 | 94 | __doc__ += """ 95 | >>> a = Thing() 96 | >>> b = Agent() 97 | >>> b.alive 98 | """ 99 | 100 | 101 | -------------------------------------------------------------------------------- /projects/sudoku/utils/SudokuSquare.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Thu Aug 31 19:48:21 2017 5 | 6 | @author: Anderson Banihirwe 7 | """ 8 | 9 | import pygame 10 | from pygame import * 11 | 12 | 13 | def AAfilledRoundedRect(surface, rect, color, radius=0.4): 14 | """ 15 | Arguments: 16 | - surface : destination 17 | - rect : rectangle 18 | - color : rgb or rgba 19 | - radius : 0 <= radius <= 1 20 | """ 21 | 22 | rect = Rect(rect) 23 | color = Color(*color) 24 | alpha = color.a 25 | color.a = 0 26 | pos = rect.topleft 27 | rect.topleft = 0,0 28 | rectangle = Surface(rect.size, SRCALPHA) 29 | 30 | circle = Surface([min(rect.size)*3]*2, SRCALPHA) 31 | draw.ellipse(circle, (0, 0, 0), circle.get_rect(), 0) 32 | circle = transform.smoothscale(circle, [int(min(rect.size) * radius)] * 2) 33 | 34 | radius = rectangle.blit(circle, (0, 0)) 35 | radius.bottomright = rect.bottomright 36 | rectangle.blit(circle, radius) 37 | radius.topright = rect.topright 38 | rectangle.blit(circle, radius) 39 | radius.bottomleft = rect.bottomleft 40 | rectangle.blit(circle, radius) 41 | 42 | rectangle.fill((0,0,0), rect.inflate(-radius.w, 0)) 43 | rectangle.fill((0,0,0), rect.inflate(0, -radius.h)) 44 | 45 | rectangle.fill(color, special_flags=BLEND_RGBA_MAX) 46 | rectangle.fill((255,255,255, alpha), special_flags=BLEND_RGBA_MIN) 47 | 48 | return surface.blit(rectangle, pos) 49 | 50 | 51 | 52 | class SudokuSquare: 53 | """ A sudoku square class.""" 54 | def __init__(self, number=None, offsetX=0, offsetY=0, edit="Y", xLoc=0, yLoc=0): 55 | if number != None: 56 | number = str(number) 57 | self.color = (2, 204, 186) 58 | 59 | else: 60 | number = "" 61 | self.color = (255, 255, 255) 62 | 63 | self.font = pygame.font.SysFont('opensans', 21) 64 | self.text = self.font.render(number, 1, (255, 255, 255)) 65 | self.textpos = self.text.get_rect() 66 | self.textpos = self.textpos.move(offsetX + 17, offsetY + 4) 67 | 68 | 69 | self.edit = edit 70 | self.xLoc = xLoc 71 | self.yLoc = yLoc 72 | self.offsetX = offsetX 73 | self.offsetY = offsetY 74 | 75 | 76 | def draw(self): 77 | screen = pygame.display.get_surface() 78 | AAfilledRoundedRect(screen, (self.offsetX, self.offsetY, 45, 40), self.color) 79 | 80 | screen.blit(self.text, self.textpos) 81 | 82 | 83 | def checkCollide(self, collision): 84 | if len(collision) == 2: 85 | return self.collideRect.collidepoint(collision) 86 | elif len(collision) == 4: 87 | return self.collideRect.colliderect(collision) 88 | else: 89 | return False 90 | 91 | 92 | def highlight(self): 93 | self.collide.fill((190, 190, 255)) 94 | self.draw() 95 | 96 | 97 | def unhighlight(self): 98 | self.collide.fill((255, 255, 255, 255)) 99 | self.draw() 100 | 101 | 102 | def change(self, number): 103 | if number != None: 104 | number = str(number) 105 | else: 106 | number = "" 107 | 108 | if self.edit == "Y": 109 | self.text = self.font.render(number, 1, (0, 0, 0)) 110 | self.draw() 111 | return 0 112 | else: 113 | return 1 114 | 115 | 116 | def currentLoc(self): 117 | return self.xLoc, self.yLoc 118 | 119 | 120 | 121 | if __name__=="__main__": 122 | pass 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /environments/dl_env_linux-v2.yml: -------------------------------------------------------------------------------- 1 | name: dl 2 | channels: 3 | - menpo 4 | - conda-forge 5 | - defaults 6 | dependencies: 7 | - asn1crypto=0.22.0=py36_0 8 | - backports.weakref=1.0rc1=py36_0 9 | - bkcharts=0.2=py36_0 10 | - blas=1.1=openblas 11 | - bleach=1.5.0=py36_0 12 | - bokeh=0.12.6=py36_0 13 | - bzip2=1.0.6=1 14 | - certifi=2017.7.27.1=py36_0 15 | - cffi=1.10.0=py36_0 16 | - chardet=3.0.4=py36_0 17 | - click=6.7=py36_0 18 | - cloudpickle=0.3.1=py36_0 19 | - cryptography=1.9=py36_0 20 | - cycler=0.10.0=py36_0 21 | - dask=0.15.1=py36_0 22 | - dbus=1.10.22=0 23 | - decorator=4.0.11=py36_0 24 | - distributed=1.18.0=py36_0 25 | - entrypoints=0.2.3=py36_1 26 | - expat=2.2.1=0 27 | - ffmpeg=3.2.4=1 28 | - flask=0.12.2=py36_0 29 | - flask-socketio=2.9.2=py36_0 30 | - fontconfig=2.12.1=4 31 | - freetype=2.7=1 32 | - gettext=0.19.7=1 33 | - glib=2.51.4=0 34 | - gmp=6.1.2=0 35 | - gst-plugins-base=1.8.0=0 36 | - gstreamer=1.8.0=2 37 | - h5py=2.7.0=np113py36_1 38 | - hdf5=1.8.18=0 39 | - heapdict=1.0.0=py36_0 40 | - html5lib=0.9999999=py36_0 41 | - icu=58.1=1 42 | - idna=2.5=py36_0 43 | - imageio=2.1.2=py36_0 44 | - ipykernel=4.6.1=py36_0 45 | - ipython=6.1.0=py36_0 46 | - ipython_genutils=0.2.0=py36_0 47 | - ipywidgets=7.0.0=py36_0 48 | - itsdangerous=0.24=py36_1 49 | - jedi=0.10.2=py36_0 50 | - jinja2=2.9.6=py36_0 51 | - jpeg=9b=0 52 | - jsonschema=2.5.1=py36_0 53 | - jupyter=1.0.0=py36_0 54 | - jupyter_client=5.1.0=py36_0 55 | - jupyter_console=5.1.0=py36_0 56 | - jupyter_core=4.3.0=py36_0 57 | - keras=2.0.6=py36_0 58 | - libffi=3.2.1=3 59 | - libgpuarray=0.6.9=0 60 | - libiconv=1.14=4 61 | - libpng=1.6.28=0 62 | - libsodium=1.0.10=0 63 | - libtiff=4.0.6=7 64 | - libxcb=1.12=1 65 | - libxml2=2.9.4=4 66 | - locket=0.2.0=py36_1 67 | - mako=1.0.7=py36_0 68 | - markupsafe=1.0=py36_0 69 | - matplotlib=2.0.2=py36_2 70 | - mistune=0.7.4=py36_0 71 | - mock=2.0.0=py36_0 72 | - moviepy=0.2.3.2=py36_0 73 | - msgpack-python=0.4.8=py36_0 74 | - nbconvert=5.2.1=py36_1 75 | - nbformat=4.3.0=py36_0 76 | - networkx=1.11=py36_0 77 | - nltk=3.2.4=py36_0 78 | - notebook=5.0.0=py36_0 79 | - numpy=1.13.1=py36_blas_openblas_200 80 | - olefile=0.44=py36_0 81 | - openblas=0.2.19=2 82 | - pandas=0.20.3=py36_1 83 | - pandoc=1.19.2=0 84 | - pandocfilters=1.4.1=py36_0 85 | - partd=0.3.8=py36_0 86 | - patsy=0.4.1=py36_0 87 | - pbr=3.1.1=py36_0 88 | - pcre=8.39=0 89 | - pexpect=4.2.1=py36_0 90 | - pickleshare=0.7.4=py36_0 91 | - pillow=4.2.1=py36_1 92 | - prompt_toolkit=1.0.15=py36_0 93 | - protobuf=3.3.2=py36_0 94 | - psutil=5.2.2=py36_0 95 | - ptyprocess=0.5.2=py36_0 96 | - pycparser=2.18=py36_0 97 | - pygments=2.2.0=py36_0 98 | - pygpu=0.6.9=np113py36_0 99 | - pyopenssl=16.2.0=py36_0 100 | - pyparsing=2.2.0=py36_0 101 | - pyqt=5.6.0=py36_4 102 | - pysocks=1.6.7=py36_0 103 | - python-dateutil=2.6.1=py36_0 104 | - python-engineio=1.7.0=py36_0 105 | - python-socketio=1.8.0=py36_0 106 | - pytz=2017.2=py36_0 107 | - pywavelets=0.5.2=np113py36_0 108 | - pyyaml=3.12=py36_1 109 | - pyzmq=16.0.2=py36_2 110 | - qt=5.6.2=3 111 | - qtconsole=4.3.1=py36_0 112 | - requests=2.18.4=py36_0 113 | - scikit-image=0.13.0=py36_1 114 | - scikit-learn=0.19.0=py36_blas_openblas_201 115 | - scipy=0.19.1=py36_blas_openblas_202 116 | - seaborn=0.8.0=py36_0 117 | - simplegeneric=0.8.1=py36_0 118 | - sip=4.18=py36_1 119 | - six=1.10.0=py36_1 120 | - sortedcontainers=1.5.7=py36_0 121 | - statsmodels=0.8.0=np113py36_0 122 | - tblib=1.3.2=py36_0 123 | - tensorflow=1.2.1=py36_0 124 | - terminado=0.6=py36_0 125 | - testpath=0.3=py36_0 126 | - theano=0.9.0=py36_1 127 | - toolz=0.8.2=py36_0 128 | - tornado=4.5.1=py36_0 129 | - tqdm=4.11.2=py36_0 130 | - traitlets=4.3.2=py36_0 131 | - urllib3=1.21.1=py36_1 132 | - wcwidth=0.1.7=py36_0 133 | - webencodings=0.5=py36_0 134 | - werkzeug=0.12.2=py36_0 135 | - widgetsnbextension=3.0.0=py36_0 136 | - x264=20131217=3 137 | - xorg-libxau=1.0.8=3 138 | - xorg-libxdmcp=1.1.2=3 139 | - yaml=0.1.6=0 140 | - zeromq=4.2.1=1 141 | - zict=0.1.2=py36_0 142 | - zlib=1.2.8=3 143 | - libgfortran=3.0.0=1 144 | - markdown=2.6.8=py36_0 145 | - openssl=1.0.2l=0 146 | - pip=9.0.1=py36_1 147 | - python=3.6.2=0 148 | - readline=6.2=2 149 | - setuptools=27.2.0=py36_0 150 | - sqlite=3.13.0=0 151 | - tk=8.5.18=0 152 | - wheel=0.29.0=py36_0 153 | - xz=5.2.3=0 154 | - opencv3=3.1.0=py36_0 155 | - pip: 156 | - ipython-genutils==0.2.0 157 | - jupyter-client==5.1.0 158 | - jupyter-console==5.1.0 159 | - jupyter-core==4.3.0 160 | - prompt-toolkit==1.0.15 161 | -------------------------------------------------------------------------------- /environments/dl_env_linux_gpu-v2.yml: -------------------------------------------------------------------------------- 1 | name: dl-gpu 2 | channels: 3 | - menpo 4 | - conda-forge 5 | - defaults 6 | dependencies: 7 | - asn1crypto=0.22.0=py36_0 8 | - bkcharts=0.2=py36_0 9 | - blas=1.1=openblas 10 | - bleach=1.5.0=py36_0 11 | - bokeh=0.12.6=py36_0 12 | - certifi=2017.7.27.1=py36_0 13 | - chardet=3.0.4=py36_0 14 | - click=6.7=py36_0 15 | - cloudpickle=0.3.1=py36_0 16 | - cryptography=1.9=py36_0 17 | - cycler=0.10.0=py36_0 18 | - dask=0.15.1=py36_0 19 | - decorator=4.0.11=py36_0 20 | - distributed=1.18.0=py36_0 21 | - entrypoints=0.2.3=py36_1 22 | - flask=0.12.2=py36_0 23 | - flask-socketio=2.9.2=py36_0 24 | - fontconfig=2.12.1=4 25 | - freetype=2.7=1 26 | - gmp=6.1.2=0 27 | - h5py=2.7.0=np113py36_1 28 | - hdf5=1.8.18=1 29 | - heapdict=1.0.0=py36_0 30 | - html5lib=0.9999999=py36_0 31 | - icu=58.1=1 32 | - idna=2.5=py36_0 33 | - imageio=2.1.2=py36_0 34 | - ipykernel=4.6.1=py36_0 35 | - ipython=6.1.0=py36_0 36 | - ipython_genutils=0.2.0=py36_0 37 | - itsdangerous=0.24=py36_1 38 | - jedi=0.10.2=py36_0 39 | - jinja2=2.9.5=py36_0 40 | - jsonschema=2.5.1=py36_0 41 | - jupyter_client=5.1.0=py36_0 42 | - jupyter_contrib_core=0.3.1=py36_0 43 | - jupyter_contrib_nbextensions=0.2.8=py36_1 44 | - jupyter_core=4.3.0=py36_0 45 | - jupyter_highlight_selected_word=0.0.11=py36_0 46 | - jupyter_latex_envs=1.3.8.2=py36_1 47 | - jupyter_nbextensions_configurator=0.2.5=py36_0 48 | - keras=2.0.6=py36_0 49 | - libgpuarray=0.6.9=0 50 | - libpng=1.6.28=1 51 | - libsodium=1.0.10=0 52 | - libtiff=4.0.6=7 53 | - locket=0.2.0=py36_1 54 | - mako=1.0.7=py36_0 55 | - markupsafe=1.0=py36_0 56 | - matplotlib=2.0.2=py36_2 57 | - mistune=0.7.4=py36_0 58 | - moviepy=0.2.3.2=py36_0 59 | - msgpack-python=0.4.8=py36_0 60 | - nbconvert=5.2.1=py36_1 61 | - nbformat=4.3.0=py36_0 62 | - networkx=1.11=py36_0 63 | - nltk=3.2.4=py36_0 64 | - notebook=5.0.0=py36_0 65 | - numpy=1.13.1=py36_blas_openblas_200 66 | - olefile=0.44=py36_0 67 | - openblas=0.2.19=2 68 | - pandas=0.20.3=py36_1 69 | - pandoc=1.19.2=0 70 | - pandocfilters=1.4.1=py36_0 71 | - partd=0.3.8=py36_0 72 | - patsy=0.4.1=py36_0 73 | - pexpect=4.2.1=py36_0 74 | - pickleshare=0.7.3=py36_0 75 | - pillow=4.2.1=py36_1 76 | - prompt_toolkit=1.0.14=py36_0 77 | - psutil=5.2.1=py36_0 78 | - ptyprocess=0.5.2=py36_0 79 | - pygments=2.2.0=py36_0 80 | - pygpu=0.6.9=np113py36_0 81 | - pyopenssl=16.2.0=py36_0 82 | - pyparsing=2.2.0=py36_0 83 | - pysocks=1.6.7=py36_0 84 | - python-dateutil=2.6.1=py36_0 85 | - python-engineio=1.7.0=py36_0 86 | - python-socketio=1.8.0=py36_0 87 | - pytz=2017.2=py36_0 88 | - pywavelets=0.5.2=np113py36_0 89 | - pyyaml=3.12=py36_1 90 | - pyzmq=16.0.2=py36_2 91 | - qt=5.6.2=3 92 | - requests=2.18.4=py36_0 93 | - scikit-image=0.13.0=py36_1 94 | - scikit-learn=0.19.0=py36_blas_openblas_201 95 | - scipy=0.19.1=py36_blas_openblas_202 96 | - seaborn=0.8.0=py36_0 97 | - simplegeneric=0.8.1=py36_0 98 | - sortedcontainers=1.5.7=py36_0 99 | - statsmodels=0.8.0=np113py36_0 100 | - tblib=1.3.2=py36_0 101 | - terminado=0.6=py36_0 102 | - testpath=0.3=py36_0 103 | - theano=0.9.0=py36_1 104 | - toolz=0.8.2=py36_0 105 | - tornado=4.5.1=py36_0 106 | - tqdm=4.11.2=py36_0 107 | - traitlets=4.3.2=py36_0 108 | - urllib3=1.21.1=py36_1 109 | - wcwidth=0.1.7=py36_0 110 | - webencodings=0.5=py36_0 111 | - yaml=0.1.6=0 112 | - zeromq=4.2.1=1 113 | - zict=0.1.2=py36_0 114 | - accelerate_cudalib=2.0=0 115 | - backports=1.0=py36_0 116 | - backports.weakref=1.0rc1=py36_0 117 | - cffi=1.10.0=py36_0 118 | - cudatoolkit=8.0=1 119 | - cudnn=6.0.21=cuda8.0_0 120 | - dbus=1.10.20=0 121 | - expat=2.1.0=0 122 | - glib=2.50.2=1 123 | - gst-plugins-base=1.8.0=0 124 | - gstreamer=1.8.0=0 125 | - ipywidgets=6.0.0=py36_0 126 | - jpeg=9b=0 127 | - jupyter=1.0.0=py36_3 128 | - jupyter_console=5.1.0=py36_0 129 | - libffi=3.2.1=1 130 | - libgcc=5.2.0=0 131 | - libgfortran=3.0.0=1 132 | - libiconv=1.14=0 133 | - libprotobuf=3.2.0=0 134 | - libxcb=1.12=1 135 | - libxml2=2.9.4=0 136 | - llvmlite=0.19.0=py36_0 137 | - markdown=2.6.8=py36_0 138 | - mkl=2017.0.3=0 139 | - mkl-service=1.1.2=py36_3 140 | - nose=1.3.7=py36_1 141 | - numba=0.34.0=np113py36_0 142 | - openssl=1.0.2l=0 143 | - pcre=8.39=1 144 | - pip=9.0.1=py36_1 145 | - protobuf=3.2.0=py36_0 146 | - pycparser=2.17=py36_0 147 | - pyqt=5.6.0=py36_2 148 | - python=3.6.2=0 149 | - qtconsole=4.3.0=py36_0 150 | - readline=6.2=2 151 | - setuptools=27.2.0=py36_0 152 | - sip=4.18=py36_0 153 | - six=1.10.0=py36_0 154 | - snakeviz=0.4.1=py36_0 155 | - sqlite=3.13.0=0 156 | - tensorflow-gpu=1.2.1=py36cuda8.0cudnn6.0_0 157 | - tk=8.5.18=0 158 | - werkzeug=0.12.2=py36_0 159 | - wheel=0.29.0=py36_0 160 | - widgetsnbextension=2.0.0=py36_0 161 | - xz=5.2.2=1 162 | - zlib=1.2.8=3 163 | - ffmpeg=3.1.3=0 164 | - freeimage=3.17.0=0 165 | - opencv3=3.1.0=py36_0 166 | - pip: 167 | - ipython-genutils==0.2.0 168 | - jupyter-client==5.1.0 169 | - jupyter-console==5.1.0 170 | - jupyter-contrib-core==0.3.1 171 | - jupyter-contrib-nbextensions==0.2.8 172 | - jupyter-core==4.3.0 173 | - jupyter-highlight-selected-word==0.0.11 174 | - jupyter-latex-envs==1.3.8.2 175 | - jupyter-nbextensions-configurator==0.2.5 176 | - prompt-toolkit==1.0.14 177 | - tensorflow==1.2.1 178 | 179 | -------------------------------------------------------------------------------- /projects/TSP/pyswarm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sat Sep 2 15:36:28 2017 5 | 6 | @author: Anderson Banihirwe 7 | 8 | Simple Particle Swarm Optimization (PSO) 9 | """ 10 | 11 | import random 12 | import math 13 | import time 14 | import numpy as np 15 | 16 | #---------- COST FUNCTION -----------------------------# 17 | 18 | # function to optimize (minimize) 19 | def cost_func(x): 20 | total = 0.0 21 | for i in range(len(x)): 22 | total += x[i]**2 23 | 24 | return total 25 | 26 | 27 | 28 | #------------MAIN----------------------------------------# 29 | 30 | class Particle: 31 | def __init__(self, x0): 32 | self.position_i = [] # particle position 33 | self.velocity_i = [] # particle velocity 34 | self.pos_best_i = [] # best position individual 35 | self.error_best_i = -1 # best error individual 36 | self.error_i = -1 # error individual 37 | 38 | 39 | for i in range(0, ndims): 40 | self.velocity_i.append(random.uniform(-1,1)) 41 | self.position_i.append(x0[i]) 42 | 43 | # evaluate current fitness 44 | def evaluate_fitness(self, costFunc): 45 | self.error_i = costFunc(self.position_i) 46 | 47 | # Check to see if the current position is an individual best 48 | if self.error_i < self.error_best_i or self.error_best_i == -1: 49 | self.pos_best_i = self.position_i 50 | self.error_best_i = self.error_i 51 | 52 | 53 | # update new particle velocity 54 | def update_velocity(self, pos_best_g): 55 | w = 0.5 # constant inertia weight (how much to weigh the previous velocity) 56 | c1 = 1 # cognitive constant 57 | c2 = 2 # social constant 58 | 59 | for i in range(0, ndims): 60 | r1 = random.random() 61 | r2 = random.random() 62 | 63 | vel_cognitive = c1 * r1 * (self.pos_best_i[i] - self.position_i[i]) 64 | vel_social = c2 * r2 * (pos_best_g[i] - self.position_i[i]) 65 | self.velocity_i[i] = w * self.velocity_i[i] + vel_cognitive + vel_social 66 | 67 | 68 | # update the particle position based off new velocity updates 69 | def update_position(self, bounds): 70 | 71 | for i in range(0, ndims): 72 | self.position_i[i] += self.velocity_i[i] 73 | 74 | # adjust maximum position if necessary 75 | if self.position_i[i] > bounds[i][1]: 76 | self.position_i[i] = bounds[i][1] 77 | 78 | 79 | # adjust minimum position if necessary 80 | if self.position_i[i] < bounds[i][0]: 81 | self.position_i[i] = bounds[i][0] 82 | 83 | 84 | class PSO(): 85 | def __init__(self, costFunc, x0, bounds, nparticles, maxiter): 86 | global ndims 87 | 88 | ndims = len(x0) 89 | error_best_g = -1 # best error for group 90 | pos_best_g = [] # best position for group 91 | 92 | # establish the swarm 93 | swarm = [] 94 | for i in range(0, nparticles): 95 | swarm.append(Particle(x0)) 96 | 97 | # Find the time it takes to find the solution 98 | 99 | t0 = time.clock() 100 | # Begin optimization loop 101 | i = 0 102 | while i < maxiter: 103 | 104 | # cycle through particles in swarm and evaluate fitness 105 | for j in range(0, nparticles): 106 | swarm[j].evaluate_fitness(costFunc) 107 | 108 | # Determine if current particle is globally the best 109 | if swarm[j].error_i < error_best_g or error_best_g == -1: 110 | pos_best_g = list(swarm[j].position_i) 111 | error_best_g = float(swarm[j].error_i) 112 | 113 | 114 | # cycle through swarm and update velocities and positions 115 | for j in range(0, nparticles): 116 | swarm[j].update_velocity(pos_best_g) 117 | swarm[j].update_position(bounds) 118 | 119 | i+= 1 120 | t1 = time.clock() 121 | 122 | # Final Results 123 | print("---Optimal solution found in {:.3f} secs for {} particles\n".format(t1 - t0, nparticles)) 124 | print("Best position : {}".format(pos_best_g)) 125 | print("Best Error : {}".format(error_best_g)) 126 | print("-------------------------------------------------------") 127 | 128 | 129 | if __name__ == "__main__": 130 | 131 | initial = [5, 5] 132 | bounds = [(-10, 10), (-10, 10)] 133 | PSO(cost_func, initial, bounds, nparticles=1000, maxiter=100) 134 | 135 | -------------------------------------------------------------------------------- /projects/sudoku/solver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Thu Aug 31 20:35:18 2017 5 | 6 | @author: Anderson Banihirwe 7 | """ 8 | 9 | from itertools import product, combinations 10 | 11 | assignments = [] 12 | rows = 'ABCDEFGHI' 13 | cols = '123456789' 14 | 15 | 16 | def assign_value(values, box, value): 17 | """ 18 | Please use this function to update your values dictionary! 19 | Assigns a value to a given box. If it updates the board record it. 20 | """ 21 | values[box] = value 22 | if len(value) == 1: 23 | assignments.append(values.copy()) 24 | return values 25 | 26 | 27 | def naked_twins(values): 28 | """Eliminate values using the naked twins strategy. 29 | Args: 30 | values(dict): a dictionary of the form {'box_name': '123456789', ...} 31 | Returns: 32 | the values dictionary with the naked twins eliminated from peers. 33 | """ 34 | twin_values = [box for box in values.keys() if len(values[box]) == 2] 35 | for box in twin_values: 36 | candidate = values[box] 37 | if len(candidate) != 2: 38 | continue 39 | 40 | box_units = units[box] 41 | for u in box_units: 42 | naked_pair_found = False 43 | 44 | # Find all instances of naked twins 45 | for b in u: 46 | if b != box and values[b] == candidate: 47 | naked_pair_found = True 48 | 49 | # Eliminate the naked twins as possibilities for their peers 50 | if naked_pair_found: 51 | for bx in u: 52 | if values[bx] != candidate: 53 | for d in candidate: 54 | values = assign_value(values, bx, values[bx].replace(d, '')) 55 | 56 | return values 57 | 58 | 59 | def cross(A, B): 60 | "Cross product of elements in A and elements in B." 61 | #return [s + t for s in A for t in B] 62 | return ['%s%s' % item for item in product(A, B)] 63 | 64 | 65 | 66 | boxes = cross(rows, cols) 67 | 68 | row_units = [cross(r, cols) for r in rows] 69 | column_units = [cross(rows, c) for c in cols] 70 | square_units = [cross(rs, cs) for rs in ('ABC', 'DEF', 'GHI') for cs in ('123', '456', '789')] 71 | 72 | # To solve the second question 73 | diagonal_units = [['A1', 'B2', 'C3', 'D4', 'E5', 'F6', 'G7', 'H8', 'I9'], ['A9', 'B8', 'C7', 'D6', 'E5', 'F4', 'G3', 'H2', 'I1']] 74 | 75 | unitlist = row_units + column_units + square_units + diagonal_units 76 | units = dict((s, [u for u in unitlist if s in u]) for s in boxes) 77 | peers = dict((s, set(sum(units[s], [])) - set([s])) for s in boxes) 78 | 79 | 80 | def grid_values(grid): 81 | "Convert grid into a dict of {square: char} with '.' for empties." 82 | chars = [] 83 | digits = '123456789' 84 | for c in grid: 85 | if c in digits: 86 | chars.append(c) 87 | if c == '.': 88 | chars.append(digits) 89 | assert len(chars) == 81 90 | return dict(zip(boxes, chars)) 91 | 92 | 93 | def display(values): 94 | "Display these values as a 2-D grid." 95 | width = 1 + max(len(values[s]) for s in boxes) 96 | line = '+'.join(['-' * (width * 3)] * 3) 97 | for r in rows: 98 | print(''.join(values[r + c].center(width) + ('|' if c in '36' else '') 99 | for c in cols)) 100 | if r in 'CF': print(line) 101 | print 102 | 103 | 104 | def eliminate(values): 105 | """ 106 | Go through all the boxes, and whenever there is a box with a value, eliminate this value from the values of all its peers. 107 | Input: A sudoku in dictionary form. 108 | Output: The resulting sudoku in dictionary form. 109 | """ 110 | solved_values = [box for box in values.keys() if len(values[box]) == 1] 111 | for box in solved_values: 112 | digit = values[box] 113 | for peer in peers[box]: 114 | values = assign_value(values, peer, values[peer].replace(digit, '')) 115 | return values 116 | 117 | 118 | def only_choice(values): 119 | """ 120 | Go through all the units, and whenever there is a unit with a value that only fits in one box, assign the value to this box. 121 | Input: A sudoku in dictionary form. 122 | Output: The resulting sudoku in dictionary form. 123 | """ 124 | for unit in unitlist: 125 | for digit in '123456789': 126 | dplaces = [box for box in unit if digit in values[box]] 127 | if len(dplaces) == 1: 128 | values = assign_value(values, dplaces[0], digit) 129 | return values 130 | 131 | 132 | def reduce_puzzle(values): 133 | stalled = False 134 | while not stalled: 135 | solved_values_before = len([box for box in values.keys() if len(values[box]) == 1]) 136 | values = eliminate(values) 137 | values = only_choice(values) 138 | values = naked_twins(values) 139 | solved_values_after = len([box for box in values.keys() if len(values[box]) == 1]) 140 | stalled = solved_values_before == solved_values_after 141 | if len([box for box in values.keys() if len(values[box]) == 0]): 142 | return False 143 | return values 144 | 145 | 146 | def solve(grid): 147 | values = reduce_puzzle(grid_values(grid)) 148 | if values is False: 149 | return False 150 | if solved(values): 151 | return values 152 | n, s = min((len(values[s]), s) for s in boxes if len(values[s]) > 1) 153 | for value in values[s]: 154 | new_sudoku = values.copy() 155 | new_sudoku[s] = value 156 | attempt = solve(new_sudoku) 157 | if attempt: 158 | return attempt 159 | 160 | 161 | def solved(values): 162 | return all(len(values[s]) == 1 for s in boxes) 163 | 164 | 165 | diag_sudoku_grid = '2.............62....1....7...6..8...3...9...7...6..4...4....8....52.............3' 166 | #diag_sudoku_grid = '8..........36......7..9.2...5...7.......457.....1...3...1....68..85...1..9....4..' 167 | #diag_sudoku_grid = '...............9..97.3......1..6.5....47.8..2.....2..6.31..4......8..167.87......' 168 | #diag_sudoku_grid = '..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..' 169 | display(solve(diag_sudoku_grid)) 170 | 171 | try: 172 | from visualizer import visualize_assignments 173 | visualize_assignments(assignments) 174 | except Exception as e: 175 | print(e) 176 | print('We could not visualize your board due to a pygame issue. Not a problem! It is not a requirement.') 177 | -------------------------------------------------------------------------------- /projects/sudoku/solver_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Thu Aug 31 20:41:28 2017 5 | 6 | @author: Anderson Banihirwe 7 | """ 8 | 9 | import solver 10 | import unittest 11 | 12 | 13 | class TestNakedTwins(unittest.TestCase): 14 | before_naked_twins_1 = {'I6': '4', 'H9': '3', 'I2': '6', 'E8': '1', 'H3': '5', 'H7': '8', 'I7': '1', 'I4': '8', 15 | 'H5': '6', 'F9': '7', 'G7': '6', 'G6': '3', 'G5': '2', 'E1': '8', 'G3': '1', 'G2': '8', 16 | 'G1': '7', 'I1': '23', 'C8': '5', 'I3': '23', 'E5': '347', 'I5': '5', 'C9': '1', 'G9': '5', 17 | 'G8': '4', 'A1': '1', 'A3': '4', 'A2': '237', 'A5': '9', 'A4': '2357', 'A7': '27', 18 | 'A6': '257', 'C3': '8', 'C2': '237', 'C1': '23', 'E6': '579', 'C7': '9', 'C6': '6', 19 | 'C5': '37', 'C4': '4', 'I9': '9', 'D8': '8', 'I8': '7', 'E4': '6', 'D9': '6', 'H8': '2', 20 | 'F6': '125', 'A9': '8', 'G4': '9', 'A8': '6', 'E7': '345', 'E3': '379', 'F1': '6', 21 | 'F2': '4', 'F3': '23', 'F4': '1235', 'F5': '8', 'E2': '37', 'F7': '35', 'F8': '9', 22 | 'D2': '1', 'H1': '4', 'H6': '17', 'H2': '9', 'H4': '17', 'D3': '2379', 'B4': '27', 23 | 'B5': '1', 'B6': '8', 'B7': '27', 'E9': '2', 'B1': '9', 'B2': '5', 'B3': '6', 'D6': '279', 24 | 'D7': '34', 'D4': '237', 'D5': '347', 'B8': '3', 'B9': '4', 'D1': '5'} 25 | possible_solutions_1 = [ 26 | {'G7': '6', 'G6': '3', 'G5': '2', 'G4': '9', 'G3': '1', 'G2': '8', 'G1': '7', 'G9': '5', 'G8': '4', 'C9': '1', 27 | 'C8': '5', 'C3': '8', 'C2': '237', 'C1': '23', 'C7': '9', 'C6': '6', 'C5': '37', 'A4': '2357', 'A9': '8', 28 | 'A8': '6', 'F1': '6', 'F2': '4', 'F3': '23', 'F4': '1235', 'F5': '8', 'F6': '125', 'F7': '35', 'F8': '9', 29 | 'F9': '7', 'B4': '27', 'B5': '1', 'B6': '8', 'B7': '27', 'E9': '2', 'B1': '9', 'B2': '5', 'B3': '6', 'C4': '4', 30 | 'B8': '3', 'B9': '4', 'I9': '9', 'I8': '7', 'I1': '23', 'I3': '23', 'I2': '6', 'I5': '5', 'I4': '8', 'I7': '1', 31 | 'I6': '4', 'A1': '1', 'A3': '4', 'A2': '237', 'A5': '9', 'E8': '1', 'A7': '27', 'A6': '257', 'E5': '347', 32 | 'E4': '6', 'E7': '345', 'E6': '579', 'E1': '8', 'E3': '79', 'E2': '37', 'H8': '2', 'H9': '3', 'H2': '9', 33 | 'H3': '5', 'H1': '4', 'H6': '17', 'H7': '8', 'H4': '17', 'H5': '6', 'D8': '8', 'D9': '6', 'D6': '279', 34 | 'D7': '34', 'D4': '237', 'D5': '347', 'D2': '1', 'D3': '79', 'D1': '5'}, 35 | {'I6': '4', 'H9': '3', 'I2': '6', 'E8': '1', 'H3': '5', 'H7': '8', 'I7': '1', 'I4': '8', 'H5': '6', 'F9': '7', 36 | 'G7': '6', 'G6': '3', 'G5': '2', 'E1': '8', 'G3': '1', 'G2': '8', 'G1': '7', 'I1': '23', 'C8': '5', 'I3': '23', 37 | 'E5': '347', 'I5': '5', 'C9': '1', 'G9': '5', 'G8': '4', 'A1': '1', 'A3': '4', 'A2': '237', 'A5': '9', 38 | 'A4': '2357', 'A7': '27', 'A6': '257', 'C3': '8', 'C2': '237', 'C1': '23', 'E6': '579', 'C7': '9', 'C6': '6', 39 | 'C5': '37', 'C4': '4', 'I9': '9', 'D8': '8', 'I8': '7', 'E4': '6', 'D9': '6', 'H8': '2', 'F6': '125', 40 | 'A9': '8', 'G4': '9', 'A8': '6', 'E7': '345', 'E3': '79', 'F1': '6', 'F2': '4', 'F3': '23', 'F4': '1235', 41 | 'F5': '8', 'E2': '3', 'F7': '35', 'F8': '9', 'D2': '1', 'H1': '4', 'H6': '17', 'H2': '9', 'H4': '17', 42 | 'D3': '79', 'B4': '27', 'B5': '1', 'B6': '8', 'B7': '27', 'E9': '2', 'B1': '9', 'B2': '5', 'B3': '6', 43 | 'D6': '279', 'D7': '34', 'D4': '237', 'D5': '347', 'B8': '3', 'B9': '4', 'D1': '5'} 44 | ] 45 | 46 | before_naked_twins_2 = {'A1': '23', 'A2': '4', 'A3': '7', 'A4': '6', 'A5': '8', 'A6': '5', 'A7': '23', 'A8': '9', 47 | 'A9': '1', 'B1': '6', 'B2': '9', 'B3': '8', 'B4': '4', 'B5': '37', 'B6': '1', 'B7': '237', 48 | 'B8': '5', 'B9': '237', 'C1': '23', 'C2': '5', 'C3': '1', 'C4': '23', 'C5': '379', 49 | 'C6': '2379', 'C7': '8', 'C8': '6', 'C9': '4', 'D1': '8', 'D2': '17', 'D3': '9', 50 | 'D4': '1235', 'D5': '6', 'D6': '237', 'D7': '4', 'D8': '27', 'D9': '2357', 'E1': '5', 51 | 'E2': '6', 'E3': '2', 'E4': '8', 'E5': '347', 'E6': '347', 'E7': '37', 'E8': '1', 'E9': '9', 52 | 'F1': '4', 'F2': '17', 'F3': '3', 'F4': '125', 'F5': '579', 'F6': '279', 'F7': '6', 53 | 'F8': '8', 'F9': '257', 'G1': '1', 'G2': '8', 'G3': '6', 'G4': '35', 'G5': '345', 54 | 'G6': '34', 'G7': '9', 'G8': '27', 'G9': '27', 'H1': '7', 'H2': '2', 'H3': '4', 'H4': '9', 55 | 'H5': '1', 'H6': '8', 'H7': '5', 'H8': '3', 'H9': '6', 'I1': '9', 'I2': '3', 'I3': '5', 56 | 'I4': '7', 'I5': '2', 'I6': '6', 'I7': '1', 'I8': '4', 'I9': '8'} 57 | possible_solutions_2 = [ 58 | {'A1': '23', 'A2': '4', 'A3': '7', 'A4': '6', 'A5': '8', 'A6': '5', 'A7': '23', 'A8': '9', 'A9': '1', 'B1': '6', 59 | 'B2': '9', 'B3': '8', 'B4': '4', 'B5': '37', 'B6': '1', 'B7': '237', 'B8': '5', 'B9': '237', 'C1': '23', 60 | 'C2': '5', 'C3': '1', 'C4': '23', 'C5': '79', 'C6': '79', 'C7': '8', 'C8': '6', 'C9': '4', 'D1': '8', 61 | 'D2': '17', 'D3': '9', 'D4': '1235', 'D5': '6', 'D6': '237', 'D7': '4', 'D8': '27', 'D9': '2357', 'E1': '5', 62 | 'E2': '6', 'E3': '2', 'E4': '8', 'E5': '347', 'E6': '347', 'E7': '37', 'E8': '1', 'E9': '9', 'F1': '4', 63 | 'F2': '17', 'F3': '3', 'F4': '125', 'F5': '579', 'F6': '279', 'F7': '6', 'F8': '8', 'F9': '257', 'G1': '1', 64 | 'G2': '8', 'G3': '6', 'G4': '35', 'G5': '345', 'G6': '34', 'G7': '9', 'G8': '27', 'G9': '27', 'H1': '7', 65 | 'H2': '2', 'H3': '4', 'H4': '9', 'H5': '1', 'H6': '8', 'H7': '5', 'H8': '3', 'H9': '6', 'I1': '9', 'I2': '3', 66 | 'I3': '5', 'I4': '7', 'I5': '2', 'I6': '6', 'I7': '1', 'I8': '4', 'I9': '8'}, 67 | {'A1': '23', 'A2': '4', 'A3': '7', 'A4': '6', 'A5': '8', 'A6': '5', 'A7': '23', 'A8': '9', 'A9': '1', 'B1': '6', 68 | 'B2': '9', 'B3': '8', 'B4': '4', 'B5': '3', 'B6': '1', 'B7': '237', 'B8': '5', 'B9': '237', 'C1': '23', 69 | 'C2': '5', 'C3': '1', 'C4': '23', 'C5': '79', 'C6': '79', 'C7': '8', 'C8': '6', 'C9': '4', 'D1': '8', 70 | 'D2': '17', 'D3': '9', 'D4': '1235', 'D5': '6', 'D6': '237', 'D7': '4', 'D8': '27', 'D9': '2357', 'E1': '5', 71 | 'E2': '6', 'E3': '2', 'E4': '8', 'E5': '347', 'E6': '347', 'E7': '37', 'E8': '1', 'E9': '9', 'F1': '4', 72 | 'F2': '17', 'F3': '3', 'F4': '125', 'F5': '579', 'F6': '279', 'F7': '6', 'F8': '8', 'F9': '257', 'G1': '1', 73 | 'G2': '8', 'G3': '6', 'G4': '35', 'G5': '345', 'G6': '34', 'G7': '9', 'G8': '27', 'G9': '27', 'H1': '7', 74 | 'H2': '2', 'H3': '4', 'H4': '9', 'H5': '1', 'H6': '8', 'H7': '5', 'H8': '3', 'H9': '6', 'I1': '9', 'I2': '3', 75 | 'I3': '5', 'I4': '7', 'I5': '2', 'I6': '6', 'I7': '1', 'I8': '4', 'I9': '8'} 76 | ] 77 | 78 | def test_naked_twins(self): 79 | self.assertTrue(solver.naked_twins(self.before_naked_twins_1) in self.possible_solutions_1, 80 | "Your naked_twins function produced an unexpected board.") 81 | 82 | def test_naked_twins2(self): 83 | self.assertTrue(solver.naked_twins(self.before_naked_twins_2) in self.possible_solutions_2, 84 | "Your naked_twins function produced an unexpected board.") 85 | 86 | 87 | 88 | class TestDiagonalSudoku(unittest.TestCase): 89 | diagonal_grid = '2.............62....1....7...6..8...3...9...7...6..4...4....8....52.............3' 90 | solved_diag_sudoku = {'G7': '8', 'G6': '9', 'G5': '7', 'G4': '3', 'G3': '2', 'G2': '4', 'G1': '6', 'G9': '5', 91 | 'G8': '1', 'C9': '6', 'C8': '7', 'C3': '1', 'C2': '9', 'C1': '4', 'C7': '5', 'C6': '3', 92 | 'C5': '2', 'C4': '8', 'E5': '9', 'E4': '1', 'F1': '1', 'F2': '2', 'F3': '9', 'F4': '6', 93 | 'F5': '5', 'F6': '7', 'F7': '4', 'F8': '3', 'F9': '8', 'B4': '7', 'B5': '1', 'B6': '6', 94 | 'B7': '2', 'B1': '8', 'B2': '5', 'B3': '3', 'B8': '4', 'B9': '9', 'I9': '3', 'I8': '2', 95 | 'I1': '7', 'I3': '8', 'I2': '1', 'I5': '6', 'I4': '5', 'I7': '9', 'I6': '4', 'A1': '2', 96 | 'A3': '7', 'A2': '6', 'E9': '7', 'A4': '9', 'A7': '3', 'A6': '5', 'A9': '1', 'A8': '8', 97 | 'E7': '6', 'E6': '2', 'E1': '3', 'E3': '4', 'E2': '8', 'E8': '5', 'A5': '4', 'H8': '6', 98 | 'H9': '4', 'H2': '3', 'H3': '5', 'H1': '9', 'H6': '1', 'H7': '7', 'H4': '2', 'H5': '8', 99 | 'D8': '9', 'D9': '2', 'D6': '8', 'D7': '1', 'D4': '4', 'D5': '3', 'D2': '7', 'D3': '6', 100 | 'D1': '5'} 101 | 102 | def test_solve(self): 103 | self.assertEqual(solver.solve(self.diagonal_grid), self.solved_diag_sudoku) 104 | 105 | if __name__ == '__main__': 106 | unittest.main() -------------------------------------------------------------------------------- /01-Artificial-Intelligence/1-Introduction/introduction.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "toc": "true" 7 | }, 8 | "source": [ 9 | "# Table of Contents\n", 10 | "

1  Introduction
1.1  What is AI?
1.1.1  Acting humamly: The Turing Test approach
1.1.2  Thinking humanly: The cognitive modeling approach
1.1.3  Thinking rationally: The \"laws of thought\" approach
1.1.4  Acting rationally: The rational agent approach
1.2  The Foundations of AI
1.3  The history of AI
" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "# Introduction" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "## What is AI?" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "![](https://i.imgur.com/CsEvilC.png)" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "### Acting humamly: The Turing Test approach" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "- **The Turing Test**, was proposed by Alan Turing (1950)\n", 46 | "- Designed to provide a satisfactory operational definition of intelligence.\n", 47 | "- A computer passes the test if a human interrogator, after posing some written questions, cannot tell whether the written responses come from a person or from a computer.\n", 48 | "- The computer would need to possess the following capabilities:\n", 49 | " - **natural language processing** to enable it to communicate successfully in English.\n", 50 | " - **knowledge representation** to store what it knows or hears.\n", 51 | " - **automated reasoning** to use the stored information to answer questions and to draw new conclusions.\n", 52 | " - **machine learning** to adapt to new circumstances and to detect and extrapolate patterns.\n", 53 | " \n", 54 | "- Turing's test deliberately avoided direct physical interaction between the interrogator and the computer, because physical simulation of a person is unnecessary for intelligence.\n", 55 | "\n", 56 | "- **The Total Turing Test** includes a video signal so that the interrogator can test the subject's perceptual abilities, as well the opportunity for the interrogator to pass physical objects through the hatch.\n", 57 | "- To pass the total turing test, the computer will need:\n", 58 | " - **computer vision** to perceive objects, and\n", 59 | " - **robotics** to manipulate objects and move about." 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "### Thinking humanly: The cognitive modeling approach" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": {}, 72 | "source": [ 73 | "- The interdisciplinary field of **cognitive science** brings together computer models from AI and experimental techniques from psychology to construct precise and testable theories of human mind." 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "metadata": {}, 79 | "source": [ 80 | "### Thinking rationally: The \"laws of thought\" approach" 81 | ] 82 | }, 83 | { 84 | "cell_type": "markdown", 85 | "metadata": {}, 86 | "source": [ 87 | "- Logicians in the 19th century developed a precise notation for statements about all kinds of objects in the world and the relations among them. \n", 88 | "- By 1965, programs existed that could, in principle, solve any solvable problem described in logical notation. (Although if no solution exists, the program might loop forever.) \n", 89 | "- The so-called logicist tradition within artificial intelligence hopes to build on such programs to create intelligent systems." 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": {}, 95 | "source": [ 96 | "**There are two main obstacles to this approach.**\n", 97 | "- First, it is not easy to take informal knowledge and state it in the formal terms required by logical notation, particularly when the knowledge is less than 100% certain. \n", 98 | "- Second, there is a big difference between solving a problem “in principle” and solving it in practice. Even problems with just a few hundred facts can exhaust the computational resources of any computer unless it has some guidance as to which reasoning steps to try first. Although both of these obstacles apply to any attempt to build computational reasoning systems, they appeared first in the logicist tradition.\n" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "### Acting rationally: The rational agent approach" 106 | ] 107 | }, 108 | { 109 | "cell_type": "markdown", 110 | "metadata": {}, 111 | "source": [ 112 | "- An **agent** is just something that acts.\n", 113 | "- A **rational agent** is one that acts so as to achieve the best outcome or, when there is uncertainty, the best expected outcome.\n", 114 | "- The rational-agent approach has two advantages over the other approaches:\n", 115 | " - First, it is more general than the \"laws of thought\" approach because correct inference is just one of several possible mechanisms for achieving rationality.\n", 116 | " - Second, it is more amenable to scientific development than are approaches based on human behavior or human thought." 117 | ] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": {}, 122 | "source": [ 123 | "## The Foundations of AI" 124 | ] 125 | }, 126 | { 127 | "cell_type": "markdown", 128 | "metadata": {}, 129 | "source": [ 130 | "- **Philosophers** (going back to 400 B. C .) made AI conceivable by considering the ideas that the mind is in some ways like a machine, that it operates on knowledge encoded in some internal language, and that thought can be used to choose what actions to take.\n", 131 | "- **Mathematicians** provided the tools to manipulate statements of logical certainty as well as uncertain, probabilistic statements. They also set the groundwork for understanding computation and reasoning about algorithms.\n", 132 | "- **Economists** formalized the problem of making decisions that maximize the expected outcome to the decision maker.\n", 133 | "- **Neuroscientists** discovered some facts about how the brain works and the ways in which it is similar to and different from computers.\n", 134 | "- **Psychologists** adopted the idea that humans and animals can be considered information-processing machines. Linguists showed that language use fits into this model.\n", 135 | "- **Computer engineers** provided the ever-more-powerful machines that make AI applications possible.\n", 136 | "- **Control theory** deals with designing devices that act optimally on the basis of feedback from the environment. Initially, the mathematical tools of control theory were quite different from AI, but the fields are coming closer together.\n" 137 | ] 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "metadata": {}, 142 | "source": [ 143 | "## The history of AI\n", 144 | "- The history of AI has had cycles of success, misplaced optimism, and resulting cutbacks in enthusiasm and funding. There have also been cycles of introducing new creative approaches and systematically refining the best ones.\n", 145 | "- AI has advanced more rapidly in the past decade because of greater use of the scientific method in experimenting with and comparing approaches.\n", 146 | "- Recent progress in understanding the theoretical basis for intelligence has gone hand in hand with improvements in the capabilities of real systems. The subfields of AI have become more integrated, and AI has found common ground with other disciplines.\n" 147 | ] 148 | } 149 | ], 150 | "metadata": { 151 | "kernelspec": { 152 | "display_name": "Python 3", 153 | "language": "python", 154 | "name": "python3" 155 | }, 156 | "language_info": { 157 | "codemirror_mode": { 158 | "name": "ipython", 159 | "version": 3 160 | }, 161 | "file_extension": ".py", 162 | "mimetype": "text/x-python", 163 | "name": "python", 164 | "nbconvert_exporter": "python", 165 | "pygments_lexer": "ipython3", 166 | "version": "3.6.2" 167 | }, 168 | "toc": { 169 | "colors": { 170 | "hover_highlight": "#DAA520", 171 | "navigate_num": "#000000", 172 | "navigate_text": "#333333", 173 | "running_highlight": "#FF0000", 174 | "selected_highlight": "#FFD700", 175 | "sidebar_border": "#EEEEEE", 176 | "wrapper_background": "#FFFFFF" 177 | }, 178 | "moveMenuLeft": true, 179 | "nav_menu": { 180 | "height": "171px", 181 | "width": "252px" 182 | }, 183 | "navigate_menu": true, 184 | "number_sections": true, 185 | "sideBar": true, 186 | "threshold": 4, 187 | "toc_cell": true, 188 | "toc_section_display": "block", 189 | "toc_window_display": true, 190 | "widenNotebook": false 191 | } 192 | }, 193 | "nbformat": 4, 194 | "nbformat_minor": 2 195 | } 196 | -------------------------------------------------------------------------------- /01-Artificial-Intelligence/assignments/ AI in 2030_REPORT-summary.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "toc": "true" 7 | }, 8 | "source": [ 9 | "# Table of Contents\n", 10 | "

1  ARTIFICIAL INTELLIGENCE AND LIFE IN 2030
1.1  Preface
1.2  Executive Summary
1.3  Overview
1.3.1  What is next for AI research?
1.4  What is Artificial Intelligence?
1.5  Section II: AI by Domain
1.5.1  Education
" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "# ARTIFICIAL INTELLIGENCE AND LIFE IN 2030\n" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "## Preface\n", 25 | "\n", 26 | "- The overarching purpose of the One Hundred year study's periodic expert review is to provide a collected and connected set of reflections about AI and its influences as the field advances." 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "## Executive Summary" 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "- AI is a science and a set of computational technologies that are inspired by --but typically operate quite differently from -- the ways people use their nervous systems and bodies to sense, learn, reason and take action.\n", 41 | "\n", 42 | "- While drawing on common research and technologies, AI systems are specialized to accomplish particular tasks. Each application requires years of focused research and a careful, unique construction.\n", 43 | "\n", 44 | "- While the rate of progress in AI has been patchy and unpredictable, there have been significant advances since the field's inception 60 years ago.\n", 45 | "\n", 46 | "- Substantial increases in the future uses of AI applications, including more self-driving cars, healthcare diagnostics and targeted treatment, and physical assistance for elder care can be expected.\n", 47 | "\n", 48 | "- Contrary to the more fantastic predictions for AI in the popular press, the Study Panel found no cause for concern that AI is an imminent threat to humankind. No machines with self-sustaining long-term goals and intent have been developed, nor are they likely to be developed in the near future. Instead, increasingly useful applications of AI, with potentially profound positive impacts on our society and economy are likely to emerge between now and 2030." 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "metadata": {}, 54 | "source": [ 55 | "## Overview" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "Many have already grown\n", 63 | "accustomed to touching\n", 64 | "and talking to their\n", 65 | "smart phones. People’s\n", 66 | "future relationships with\n", 67 | "machines will become ever\n", 68 | "more nuanced, fluid, and\n", 69 | "personalized." 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "Society is now at a crucial\n", 77 | "juncture in determining\n", 78 | "how to deploy AI-based\n", 79 | "technologies in ways that\n", 80 | "promote rather than hinder\n", 81 | "democratic values such\n", 82 | "as freedom, equality, and\n", 83 | "transparency.\n" 84 | ] 85 | }, 86 | { 87 | "cell_type": "markdown", 88 | "metadata": {}, 89 | "source": [ 90 | "Longer term, AI may be\n", 91 | "thought of as a radically\n", 92 | "different mechanism\n", 93 | "for wealth creation in\n", 94 | "which everyone should\n", 95 | "be entitled to a portion of\n", 96 | "the world’s AI-produced\n", 97 | "treasures.\n" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "### What is next for AI research?" 105 | ] 106 | }, 107 | { 108 | "cell_type": "markdown", 109 | "metadata": {}, 110 | "source": [ 111 | "The field of AI is shifting\n", 112 | "toward building intelligent\n", 113 | "systems that can\n", 114 | "collaborate effectively with\n", 115 | "people, including creative\n", 116 | "ways to develop interactive\n", 117 | "and scalable ways for\n", 118 | "people to teach robots.\n" 119 | ] 120 | }, 121 | { 122 | "cell_type": "markdown", 123 | "metadata": {}, 124 | "source": [ 125 | "These trends drive the currently “hot” areas of AI research into both fundamental methods and application areas:\n", 126 | "Large-scale machine learning \n", 127 | "\n", 128 | "- **Large-scale machine learning** concerns the design of learning algorithms, as well as scaling existing algorithms, to work with extremely large data sets. Deep learning, a class of learning procedures, has facilitated object recognition.\n", 129 | "\n", 130 | "Large-scale machine learning\n", 131 | "Many of the basic problems in machine learning (such as supervised and\n", 132 | "unsupervised learning) are well-understood. A major focus of current efforts is to\n", 133 | "scale existing algorithms to work with extremely large data sets. For example, whereas\n", 134 | "traditional methods could afford to make several passes over the data set, modern\n", 135 | "ones are designed to make only a single pass; in some cases, only sublinear methods\n", 136 | "(those that only look at a fraction of the data) can be admitted.\n", 137 | "\n", 138 | "\n", 139 | "- **Deep learning**, a class of learning procedures, has facilitated object recognition in images, video labeling, and activity recognition, and is making significant inroads into other areas of perception, such as audio, speech, and natural language processing.\n", 140 | "\n", 141 | "- **Reinforcement learning** is a framework that shifts the focus of machine learning from pattern recognition to experience-driven sequential decision-making. It promises to carry AI applications forward toward taking actions in the real world. While largely confined to academia over the past several decades, it is now seeing some practical, real-world successes.\n", 142 | "\n", 143 | "Whereas traditional machine learning has mostly focused on pattern mining,\n", 144 | "reinforcement learning shifts the focus to decision making, and is a technology that\n", 145 | "will help AI to advance more deeply into the realm of learning about and executing\n", 146 | "actions in the real world. It has existed for several decades as a framework for\n", 147 | "experience-driven sequential decision-making, but the methods have not found great\n", 148 | "success in practice, mainly owing to issues of representation and scaling. However,\n", 149 | "the advent of deep learning has provided reinforcement learning with a “shot in the\n", 150 | "arm.” The recent success of AlphaGo, a computer program developed by Google\n", 151 | "Deepmind that beat the human Go champion in a five-game match, was due in large\n", 152 | "part to reinforcement learning. AlphaGo was trained by initializing an automated\n", 153 | "agent with a human expert database, but was subsequently refined by playing a large\n", 154 | "number of games against itself and applying reinforcement learning.\n", 155 | "\n", 156 | "- **Robotics** is currently concerned with how to train a robot to interact with the world around it in generalizable and predictable ways, how to facilitate manipulation of objects in interactive environments, and how to interact with people. Advances in robotics will rely on commensurate advances to improve the reliability and generality of computer vision and other forms of machine perception.\n", 157 | "\n", 158 | "- **Computer vision** is currently the most prominent form of machine perception. It has been the sub-area of AI most transformed by the rise of deep learning. For the first time, computers are able to perform some vision tasks better than people. Muchcurrent research is focused on automatic image and video captioning.\n" 159 | ] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "metadata": {}, 164 | "source": [ 165 | "## What is Artificial Intelligence?" 166 | ] 167 | }, 168 | { 169 | "cell_type": "markdown", 170 | "metadata": {}, 171 | "source": [ 172 | "Intelligence lies on a\n", 173 | "multi-dimensional\n", 174 | "spectrum. According to\n", 175 | "this view, the difference\n", 176 | "between an arithmetic\n", 177 | "calculator and a human\n", 178 | "brain is not one of kind,\n", 179 | "but of scale, speed,\n", 180 | "degree of autonomy, and\n", 181 | "generality.\n" 182 | ] 183 | }, 184 | { 185 | "cell_type": "markdown", 186 | "metadata": {}, 187 | "source": [ 188 | "## Section II: AI by Domain" 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "metadata": {}, 194 | "source": [ 195 | "### Education" 196 | ] 197 | }, 198 | { 199 | "cell_type": "markdown", 200 | "metadata": {}, 201 | "source": [ 202 | "Though quality education\n", 203 | "will always require active\n", 204 | "engagement by human\n", 205 | "teachers, AI promises to\n", 206 | "enhance education at\n", 207 | "all levels, especially by\n", 208 | "providing personalization\n", 209 | "at scale.\n" 210 | ] 211 | }, 212 | { 213 | "cell_type": "markdown", 214 | "metadata": {}, 215 | "source": [ 216 | "The current absence of\n", 217 | "sophisticated use of AI\n", 218 | "technologies in schools,\n", 219 | "colleges, and universities\n", 220 | "may be explained by\n", 221 | "the lack of financial\n", 222 | "resources as well as the\n", 223 | "lack of data establishing\n", 224 | "the technologies’\n", 225 | "effectiveness.\n" 226 | ] 227 | } 228 | ], 229 | "metadata": { 230 | "kernelspec": { 231 | "display_name": "Python 3", 232 | "language": "python", 233 | "name": "python3" 234 | }, 235 | "language_info": { 236 | "codemirror_mode": { 237 | "name": "ipython", 238 | "version": 3 239 | }, 240 | "file_extension": ".py", 241 | "mimetype": "text/x-python", 242 | "name": "python", 243 | "nbconvert_exporter": "python", 244 | "pygments_lexer": "ipython3", 245 | "version": "3.6.2" 246 | }, 247 | "toc": { 248 | "colors": { 249 | "hover_highlight": "#DAA520", 250 | "navigate_num": "#000000", 251 | "navigate_text": "#333333", 252 | "running_highlight": "#FF0000", 253 | "selected_highlight": "#FFD700", 254 | "sidebar_border": "#EEEEEE", 255 | "wrapper_background": "#FFFFFF" 256 | }, 257 | "moveMenuLeft": true, 258 | "nav_menu": { 259 | "height": "171px", 260 | "width": "252px" 261 | }, 262 | "navigate_menu": true, 263 | "number_sections": false, 264 | "sideBar": true, 265 | "threshold": 4, 266 | "toc_cell": true, 267 | "toc_section_display": "block", 268 | "toc_window_display": false, 269 | "widenNotebook": false 270 | } 271 | }, 272 | "nbformat": 4, 273 | "nbformat_minor": 2 274 | } 275 | -------------------------------------------------------------------------------- /01-Artificial-Intelligence/2-Intelligent-agents/intelligent-agents.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "toc": "true" 7 | }, 8 | "source": [ 9 | "# Table of Contents\n", 10 | "

1  Intelligent Agents
1.1  Agents and Environments
1.2  Good Behavior: The Concept of Rationality
1.2.1  Rationality
1.2.2  Omniscience, learning, and autonomy
1.3  The Nature of Environments
1.3.1  Specifying the task environment
1.3.2  Properties of task environments
1.4  The Structure of Agents
1.4.1  Agent Programs
1.5  Key Points
" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "# Intelligent Agents" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "## Agents and Environments" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "- An **agent** is anything that can be viewed as perceiving its **environment** through **sensors** and acting upon that environment through **actuators**.\n", 32 | "\n", 33 | "![](https://i.imgur.com/x79uGFG.png)" 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "- A human agent has eyes, ears, and other organs for sensors and hands, legs, vocal tract of actuators.\n", 41 | "- A robotic agent might have cameras and infrared range finders for sensors and various motors for actuators.\n", 42 | "- A software agent receives keystrokes, file contents, and network packets as sensory inputs and acts on environment by displaying on the screen, writing files, etc.\n", 43 | "\n", 44 | "- An agent's **percept sequence** is the complete history of everything that agent has ever perceived.\n", 45 | ">An agent's choice of action at any given instant can depend on the entire percept sequence observed to date, but not on anything it hasn't perceived.\n", 46 | "\n", 47 | "- Mathematically speaking, we say that an agent's behavior is described by the **agent function** that maps any given percept sequence to an action.\n", 48 | "- *Internally,* the agent function for an artificial agent will be implemented by an **agent program**. It is important to keep these two ideas distinct.\n", 49 | ">**The agent function** is an abstract mathematical description, **the agent program** is a concrete implementation, running within some physical system." 50 | ] 51 | }, 52 | { 53 | "cell_type": "markdown", 54 | "metadata": {}, 55 | "source": [ 56 | "## Good Behavior: The Concept of Rationality" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "- A **rational agent** is one that does the right thing—conceptually speaking, every entry in the table for the agent function is filled out correctly. Obviously, doing the right thing is better than doing the wrong thing, but what does it mean to do the right thing?\n", 64 | "\n", 65 | "- When an agent is plunked down in an environment, it generates a sequence of actions according to the percepts it receives. This sequence of actions causes the environment to go through a sequence of states. If the sequence is desirable, then the agent has performed well. This notion of desirability is captured by a **performance measure** that evaluates any given sequence of environment states.\n", 66 | "\n", 67 | ">As a generall rule, it is better to design performance measures according to what one actually wants in the environment, rather than according to how one thinks the agent should behave.\n" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "### Rationality" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "- Rationality at any given time depends on four things:\n", 82 | " - The performance measure that defines the criterion of success.\n", 83 | " - The agent's prior knowledge of the environment.\n", 84 | " - The actions that the agent can perform.\n", 85 | " - The agent's percept sequence to date.\n", 86 | " \n", 87 | "- This leads to a **definition of a rational agent**:\n", 88 | ">For each possible percept sequence, a rational agent should select an action that is ex-\n", 89 | "pected to maximize its performance measure, given the evidence provided by the percept\n", 90 | "sequence and whatever built-in knowledge the agent has.\n" 91 | ] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "metadata": {}, 96 | "source": [ 97 | "### Omniscience, learning, and autonomy" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "- There is a distinction between **rationality** and **omniscience**.\n", 105 | " - An omniscient agent knows the *actual* outcome of its actions and can act accordingly; but omniscience is impossible in reality.\n", 106 | " \n", 107 | "- Rationality maximizes *expected* performance, while perfection maximizes *actual* performance.\n", 108 | "\n", 109 | "- Doing actions *in order to modify future percepts* is called **information gathering** and is an important part of rationality.\n", 110 | "\n", 111 | "- A rational agent should be **autonomous** - it should learn what it can to compensate for partial or incorrect prior knowledge." 112 | ] 113 | }, 114 | { 115 | "cell_type": "markdown", 116 | "metadata": {}, 117 | "source": [ 118 | "## The Nature of Environments" 119 | ] 120 | }, 121 | { 122 | "cell_type": "markdown", 123 | "metadata": {}, 124 | "source": [ 125 | "- **Task environments** are essentially the *problems* to which rational agents are the *solutions*. " 126 | ] 127 | }, 128 | { 129 | "cell_type": "markdown", 130 | "metadata": {}, 131 | "source": [ 132 | "### Specifying the task environment" 133 | ] 134 | }, 135 | { 136 | "cell_type": "markdown", 137 | "metadata": {}, 138 | "source": [ 139 | "The **PEAS** (Performance, Environment, Actuators, Sensors) description. In designing an\n", 140 | "agent, the first step must always be to specify the task environment as fully as possible.\n", 141 | "\n", 142 | "![](https://i.imgur.com/YT0HXef.png)\n" 143 | ] 144 | }, 145 | { 146 | "cell_type": "markdown", 147 | "metadata": {}, 148 | "source": [ 149 | "### Properties of task environments" 150 | ] 151 | }, 152 | { 153 | "cell_type": "markdown", 154 | "metadata": {}, 155 | "source": [ 156 | "- The range of task environments that might rise in AI is obviously vast.\n", 157 | "- We can, however, identify a fairly small number of dimensions along which task environments can be categorized.\n", 158 | "\n", 159 | "![](https://i.imgur.com/w7Gmlwn.png)" 160 | ] 161 | }, 162 | { 163 | "cell_type": "markdown", 164 | "metadata": {}, 165 | "source": [ 166 | "- **Fully observable** vs **Partially observable**\n", 167 | " - **Fully observable**: if an agent's sensors give it access to the complete state of the environment at each point in time, then we say that the task environment is fully observable.\n", 168 | "\n", 169 | " - **Partially observable**: if noisy and inaccurate sensors or parts of the state are simply missing from the sensor data, then we say that the task environment is partially observable.\n", 170 | "\n", 171 | "\n", 172 | "- **Single agent** vs **multiagent**\n", 173 | "\n", 174 | "\n", 175 | "- **Deterministic** vs **Stochastic**\n", 176 | "\n", 177 | " - If the next state of the environment is completely determined by the current state and the action executed by the agent, the we say the environment is **deterministic**; otherwise, it is **stochastic**.\n", 178 | " \n", 179 | " - An environment is **uncertain** if it is not fully observable or not deterministic. \n", 180 | " \n", 181 | " - **NOTE**: the word “stochastic” generally implies that uncertainty about outcomes is quantified in terms of probabilities; a nondeterministic environment is one in which actions are characterized by their possible outcomes, but no probabilities are attached to them. Nondeterministic environment descriptions are usually associated with performance measures that require the agent to succeed for all possible outcomes of its actions.\n", 182 | " \n", 183 | "- **Episodic** vs **Sequential**\n", 184 | " - In an **episodic** task environment, the agent's experience is divided into atomic episodes. In each episode the agent receives a percept and then performs a single action. Crucially, the next episode does not depend on the actions taken in previous episodes. Many classification tasks are episodic. \n", 185 | " \n", 186 | " - In **Sequential** environments, the current decision could affect all future decisions. Chess and Taxi driving are sequential.\n", 187 | " \n", 188 | " - Episodic environments are much simpler than sequential environments because the agent does not need to think ahead.\n", 189 | "\n", 190 | "\n", 191 | "- **Discrete** vs **Continuous**\n", 192 | " \n", 193 | " - The discrete/continuous distinction applies to the **state** of the environment, to the way **time** is handled, and to the **precepts** and **actions** of the agent.\n", 194 | " \n", 195 | "- **Known** vs **unknown**\n", 196 | "\n", 197 | "\n", 198 | "![](https://i.imgur.com/JWitaep.png)" 199 | ] 200 | }, 201 | { 202 | "cell_type": "markdown", 203 | "metadata": {}, 204 | "source": [ 205 | "## The Structure of Agents" 206 | ] 207 | }, 208 | { 209 | "cell_type": "markdown", 210 | "metadata": {}, 211 | "source": [ 212 | "- The job of AI is to design an **agent program** that implements the agent function-the mapping from precepts to actions.\n", 213 | "\n", 214 | "- **agent=architecture+program**" 215 | ] 216 | }, 217 | { 218 | "cell_type": "markdown", 219 | "metadata": {}, 220 | "source": [ 221 | "### Agent Programs" 222 | ] 223 | }, 224 | { 225 | "cell_type": "markdown", 226 | "metadata": {}, 227 | "source": [ 228 | "![](https://i.imgur.com/fKvuN3Z.png)" 229 | ] 230 | }, 231 | { 232 | "cell_type": "markdown", 233 | "metadata": {}, 234 | "source": [ 235 | "## Key Points\n" 236 | ] 237 | }, 238 | { 239 | "cell_type": "markdown", 240 | "metadata": {}, 241 | "source": [ 242 | "- An **agent** is something that perceives and acts in an environment. The agent function for an agent specifies the action taken by the agent in response to any percept sequence.\n", 243 | "- The **performance measure** evaluates the behavior of the agent in an environment. A rational agent acts so as to maximize the expected value of the performance measure, given the percept sequence it has seen so far.\n", 244 | "- A **task environment** specification includes the performance measure, the external environment, the actuators, and the sensors. In designing an agent, the first step must always be to specify the task environment as fully as possible.\n", 245 | "- Task environments vary along several significant dimensions. They can be fully or partially observable, single-agent or multiagent, deterministic or stochastic, episodic or sequential, static or dynamic, discrete or continuous, and known or unknown.\n", 246 | "- The **agent program** implements the agent function. There exists a variety of basic agent-program designs reflecting the kind of information made explicit and used in the decision process. The designs vary in efficiency, compactness, and flexibility. The appropriate design of the agent program depends on the nature of the environment.\n", 247 | "- **Simple reflex agents** respond directly to percepts, whereas **model-based reflex agents** maintain internal state to track aspects of the world that are not evident in the current percept. **Goal-based agents** act to achieve their goals, and **utility-based agents** try to maximize their own expected “happiness.”\n", 248 | "- All agents can improve their performance through **learning**.\n" 249 | ] 250 | } 251 | ], 252 | "metadata": { 253 | "kernelspec": { 254 | "display_name": "Python 3", 255 | "language": "python", 256 | "name": "python3" 257 | }, 258 | "language_info": { 259 | "codemirror_mode": { 260 | "name": "ipython", 261 | "version": 3 262 | }, 263 | "file_extension": ".py", 264 | "mimetype": "text/x-python", 265 | "name": "python", 266 | "nbconvert_exporter": "python", 267 | "pygments_lexer": "ipython3", 268 | "version": "3.6.2" 269 | }, 270 | "toc": { 271 | "colors": { 272 | "hover_highlight": "#DAA520", 273 | "navigate_num": "#000000", 274 | "navigate_text": "#333333", 275 | "running_highlight": "#FF0000", 276 | "selected_highlight": "#FFD700", 277 | "sidebar_border": "#EEEEEE", 278 | "wrapper_background": "#FFFFFF" 279 | }, 280 | "moveMenuLeft": true, 281 | "nav_menu": { 282 | "height": "189px", 283 | "width": "252px" 284 | }, 285 | "navigate_menu": true, 286 | "number_sections": true, 287 | "sideBar": true, 288 | "threshold": 4, 289 | "toc_cell": true, 290 | "toc_section_display": "block", 291 | "toc_window_display": true, 292 | "widenNotebook": false 293 | } 294 | }, 295 | "nbformat": 4, 296 | "nbformat_minor": 2 297 | } 298 | -------------------------------------------------------------------------------- /02-Problem-Solving/03-Search/search.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "toc": "true" 7 | }, 8 | "source": [ 9 | "# Table of Contents\n", 10 | "

1  Solving Problems By Searching
1.1  Question
1.2  Application
1.3  Beyond reflex
1.4  Tree Search
1.5  Backtracking Search
1.6  Depth-first search
1.7  Breadth-first search
1.8  DFS with iterative deepening
1.9  Tree Search Algorithms Summary
" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "# Solving Problems By Searching" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "- **Problem-solving agent** uses **atomic** representations - that is, states of the world are considered as wholes, with no internal structure visible to the problem solving algorithms.\n", 25 | "- **Goal-based agents** aka **Planning agents** use more advanced **factored** or **structured** representations.\n" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "## Question" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "![Imgur](http://i.imgur.com/Y46A2uk.png)" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "- When you solve this problem, try to think about how you did it. You probably simulated the scenario in your head, trying to send the farmer over with the goat, observing the consequences. If nothing got eaten, you might continue with the next action. Otherwise, you undo that move and try something else.\n", 47 | "- How can we get a machine to do this automatically? One of the things we need is a systematic approach that considers all the possibilities. We will see that search problems define the possibilities, and search algorithms explore these possibilities." 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "## Application" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "![](https://i.imgur.com/0KJxDFw.png)" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": {}, 67 | "source": [ 68 | "- Route finding is perhaps the most canonical example of a search problem. We are given as the input a map, a source point and a destination point. The goal is to output a sequence of actions (e.g., go straight, turn left, or turn right) that will take us from the source to the destination.\n", 69 | "- We might evaluate action sequences based on an objective (distance, time, or pleasantness)." 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "![](https://i.imgur.com/rovS6up.png)" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "- In robot motion planning, the goal is get a robot to move from one position/pose to another. The desired output trajectory consists of individual actions, each action corresponding to moving or rotating the joints by a small amount.\n", 84 | "- Again, we might evaluate action sequences based on various resources like time or energy." 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "## Beyond reflex" 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": {}, 97 | "source": [ 98 | "![](https://i.imgur.com/ja8Gx0b.png)" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "- Reflex-based models (e.g., linear predictors and neural networks) output either a $-1$ or $+1$ (for binary classification) or a real number (for regression).\n", 106 | "- While reflex-based models were appropriate for some applications such as sentiment classification or spam filtering, the applications we will look at today, such as solving puzzles, demand more.\n", 107 | "- To tackle these new problems, we will introduce search problems, our first instance of a **state-based model**.\n", 108 | "- In a search problem, in a sense, we are still building a predictor $f$ which takes an input $x$, but $f$ will now return an entire action sequence, not just a single action. Of course you should object: can't I just apply a reflex model iteratively to generate a sequence? While that is true, the search problems that we're trying to solve importantly require reasoning about the consequences of the entire action sequence, and cannot be tackled by myopically predicting one action at a time.\n", 109 | "- Tangent: Of course, saying \"cannot\" is a bit strong, since sometimes a search problem can be solved by a reflex-based model. You could have a massive lookup table that told you what the best action to take for any given situation. (It is interesting to think of this as a time/memory tradeoff where reflex-based models are performing an implicit kind of caching.) Going on a further tangent, one can even imagine compiling a state-based model into a reflex-based model; if you're walking around Stanford for the first time, you might have to really plan things out, but eventually it kind of becomes reflex.\n", 110 | "- There are many real-world examples of this paradigm, which we will describe next. For each example, the key is to decompose the output solution into a sequence of primitive actions. In addition, we need to think about how to evaluate different possible outputs." 111 | ] 112 | }, 113 | { 114 | "cell_type": "markdown", 115 | "metadata": { 116 | "collapsed": true 117 | }, 118 | "source": [ 119 | "## Tree Search" 120 | ] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": {}, 125 | "source": [ 126 | "![](https://i.imgur.com/5wdJ2Cj.png)" 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "![](https://i.imgur.com/99kLDnm.png)" 134 | ] 135 | }, 136 | { 137 | "cell_type": "markdown", 138 | "metadata": {}, 139 | "source": [ 140 | "![](https://i.imgur.com/nDgbubM.png)" 141 | ] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": {}, 146 | "source": [ 147 | "- We will build what we will call a **search tree**. The root of the tree is the start state $S_{start}$, and the leaves are the end states ( $IsEnd(s)$ is true). Each edge leaving a node $s$ corresponds to a possible action $a\\in Actions(s)$ that could be performed in state $s$ . The edge is labeled with the action and its cost, written $a:Cost(s, a)$ . The action leads deterministically to the successor state $Succ(s, a)$, represented by the child node.\n", 148 | "\n", 149 | "- In summary, each root-to-leaf path represents a possible action sequence, and the sum of the costs of the edges is the cost of that path. The goal is to find the root-to-leaf path that has the minimum cost.\n", 150 | "- Note that in code, we usually do not build the search tree as a concrete data structure. The search tree is used merely to visualize the computation of the search algorithms and study the structure of the search problem.\n", 151 | "- For the boat crossing example, we have assumed each action (a safe river crossing) costs 1 unit of time. Invalid actions (ones that result in an eating event) cost $\\infty $ and the successor is marked in red. We disallow actions that return us to an earlier configuration. The green nodes are the end states. From this search tree, we see that there are exactly two solutions, each of which has a total cost of 7 steps." 152 | ] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "metadata": {}, 157 | "source": [ 158 | "![](https://i.imgur.com/Isuy8rO.png)" 159 | ] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "metadata": {}, 164 | "source": [ 165 | "- Let's consider another problem and practice modeling it as a search problem. Recall that this means specifying precisely what the states, actions, goals, costs, and successors are.\n", 166 | "- To avoid the ambiguity of natural language, we will do this directly in code, where we define a **SearchProblem** class and implement the methods: **startState**, **isEnd** and **succAndCost**." 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "metadata": {}, 172 | "source": [ 173 | "## Backtracking Search" 174 | ] 175 | }, 176 | { 177 | "cell_type": "markdown", 178 | "metadata": {}, 179 | "source": [ 180 | "- Now let's put modeling aside and suppose we are handed a search problem. How do we construct an algorithm for finding a minimum cost path (not necessarily unique)?\n", 181 | "- We will start with backtracking search, the simplest algorithm which just tries all paths. The algorithm is called recursively on the current state $s$ and the path path leading up to that state. If we have reached a goal, then we can update the minimum cost path with the current path. Otherwise, we consider all possible actions $a$ from state $s$ , and recursively search each of the possibilities.\n", 182 | "- Graphically, backtracking search performs a depth-first traversal of the search tree. What is the time and memory complexity of this algorithm?\n", 183 | "- To get a simple characterization, assume that the search tree has maximum depth $D$(each path consists of $D$ actions/edges) and that there are $b$ available actions per state (the branching factor is $b$).\n", 184 | "- It is easy to see that backtracking search only requires $O(D)$ memory (to maintain the stack for the recurrence), which is as good as it gets.\n", 185 | "- However, the running time is proportional to the number of nodes in the tree, since the algorithm needs to check each of them. The number of nodes is $1 + b + b^2 + \\cdots + b^D = \\frac{b^{D+1} - 1}{b-1} = O(b^D)$. Note that the total number of nodes in the search tree is on the same order as the number of leaves, so the cost is always dominated by the last level.\n", 186 | "- In general, there might not be a finite upper bound on the depth of a search tree. In this case, there are two options: (i) we can simply cap the maximum depth and give up after a certain point or (ii) we can disallow visits to the same state.\n", 187 | "\n", 188 | "![](https://i.imgur.com/Eeq9Uzr.png)" 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "metadata": {}, 194 | "source": [ 195 | "## Depth-first search\n", 196 | "\n", 197 | "Depth-first search always expands the deepest node in the current frontier of the search tree.\n", 198 | "The progress of the search is illustrated in Figure 3.16. The search proceeds immediately\n", 199 | "to the deepest level of the search tree, where the nodes have no successors. As those nodes\n", 200 | "are expanded, they are dropped from the frontier, so then the search “backs up” to the next\n", 201 | "deepest node that still has unexplored successors.\n" 202 | ] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": {}, 207 | "source": [ 208 | "![](https://i.imgur.com/lddQsV4.png)" 209 | ] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "metadata": {}, 214 | "source": [ 215 | "- Backtracking search will always work (i.e., find a minimum cost path), but there are cases where we can do it faster. But in order to do that, we need some additional assumptions — there is no free lunch.\n", 216 | "- Suppose we make the assumption that all the action costs are zero. In other words, all we care about is finding a valid action sequence that reaches the goal. Any such sequence will have the minimum cost: zero.\n", 217 | "- In this case, we can just modify backtracking search to not keep track of costs and then stop searching as soon as we reach a goal. The resulting algorithm is depth-first search (DFS), which should be familiar to you. The worst time and space complexity are of the same order as backtracking search. In particular, if there is no path to an end state, then we have to search the entire tree.\n", 218 | "- However, if there are many ways to reach the end state, then we can stop much earlier without exhausting the search tree. So DFS is great when there are an abundance of solutions." 219 | ] 220 | }, 221 | { 222 | "cell_type": "markdown", 223 | "metadata": {}, 224 | "source": [ 225 | "## Breadth-first search\n", 226 | "![](https://i.imgur.com/UbcZp2E.png)" 227 | ] 228 | }, 229 | { 230 | "cell_type": "markdown", 231 | "metadata": {}, 232 | "source": [ 233 | "- Breadth-first search is a simple strategy in which the root node is expanded first, then all the successors of the root node are expanded next, then their successors, and so on. In general, all the nodes are expanded at a given depth in the search tree before any nodes at the next level are expanded.\n", 234 | "\n", 235 | "- **Breadth-first search (BFS)**, which should also be familiar, makes a less stringent assumption, that all the action costs are the same non-negative number. This effectively means that all the paths of a given length have the same cost.\n", 236 | "- BFS maintains a queue of states to be explored. It pops a state off the queue, then pushes its successors back on the queue.\n", 237 | "- BFS will search all the paths consisting of one edge, two edges, three edges, etc., until it finds a path that reaches a end state. So if the solution has $d$ actions, then we only need to explore $O(b^d)$ nodes, thus taking that much time.\n", 238 | "- However, a potential show-stopper is that BFS also requires $O(b^d)$ space since the queue must contain all the nodes of a given level of the search tree. Can we do better?" 239 | ] 240 | }, 241 | { 242 | "cell_type": "markdown", 243 | "metadata": {}, 244 | "source": [ 245 | "![](https://i.imgur.com/0NCXt5n.png)" 246 | ] 247 | }, 248 | { 249 | "cell_type": "markdown", 250 | "metadata": {}, 251 | "source": [ 252 | "## DFS with iterative deepening" 253 | ] 254 | }, 255 | { 256 | "cell_type": "markdown", 257 | "metadata": {}, 258 | "source": [ 259 | "![](https://i.imgur.com/lV3MJFS.png)" 260 | ] 261 | }, 262 | { 263 | "cell_type": "markdown", 264 | "metadata": {}, 265 | "source": [ 266 | "- Yes, we can do better with a trick called **iterative deepening**. The idea is to modify DFS to make it stop after reaching a certain depth. Therefore, we can invoke this modified DFS to find whether a valid path exists with at most $d$ edges, which as discussed earlier takes $O(d)$ space and $O(b^d)$ time.\n", 267 | "- Now the trick is simply to invoke this modified DFS with cutoff depths of $1, 2, 3, \\dots$ until we find a solution or give up. This algorithm is called DFS with iterative deepening (DFS-ID). In this manner, we are guaranteed optimality when all action costs are equal (like BFS), but we enjoy the parsimonious space requirements of DFS.\n", 268 | "- One might worry that we are doing a lot of work, searching some nodes many times. However, keep in mind that both the number of leaves and the number of nodes in a search tree is $O(b^d)$ so asymptotically DFS with iterative deepening is the same time complexity as BFS." 269 | ] 270 | }, 271 | { 272 | "cell_type": "markdown", 273 | "metadata": {}, 274 | "source": [ 275 | "## Tree Search Algorithms Summary\n" 276 | ] 277 | }, 278 | { 279 | "cell_type": "markdown", 280 | "metadata": {}, 281 | "source": [ 282 | "![](https://i.imgur.com/tRPZ0FF.png)" 283 | ] 284 | }, 285 | { 286 | "cell_type": "markdown", 287 | "metadata": {}, 288 | "source": [ 289 | "- Here is a summary of all the tree search algorithms, the assumptions on the action costs, and the space and time complexities.\n", 290 | "- The take-away is that we can't avoid the exponential time complexity, but we can certainly have linear space complexity. Space is in some sense the more critical dimension in search problems. Memory cannot magically grow, whereas time \"grows\" just by running an algorithm for a longer period of time, or even by parallelizing it across multiple machines (e.g., where each processor gets its own subtree to search)." 291 | ] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "execution_count": null, 296 | "metadata": { 297 | "collapsed": true 298 | }, 299 | "outputs": [], 300 | "source": [] 301 | } 302 | ], 303 | "metadata": { 304 | "kernelspec": { 305 | "display_name": "Python 3", 306 | "language": "python", 307 | "name": "python3" 308 | }, 309 | "language_info": { 310 | "codemirror_mode": { 311 | "name": "ipython", 312 | "version": 3 313 | }, 314 | "file_extension": ".py", 315 | "mimetype": "text/x-python", 316 | "name": "python", 317 | "nbconvert_exporter": "python", 318 | "pygments_lexer": "ipython3", 319 | "version": "3.6.2" 320 | }, 321 | "toc": { 322 | "colors": { 323 | "hover_highlight": "#DAA520", 324 | "navigate_num": "#000000", 325 | "navigate_text": "#333333", 326 | "running_highlight": "#FF0000", 327 | "selected_highlight": "#FFD700", 328 | "sidebar_border": "#EEEEEE", 329 | "wrapper_background": "#FFFFFF" 330 | }, 331 | "moveMenuLeft": true, 332 | "nav_menu": { 333 | "height": "84px", 334 | "width": "252px" 335 | }, 336 | "navigate_menu": true, 337 | "number_sections": true, 338 | "sideBar": true, 339 | "threshold": 4, 340 | "toc_cell": true, 341 | "toc_section_display": "block", 342 | "toc_window_display": true, 343 | "widenNotebook": false 344 | } 345 | }, 346 | "nbformat": 4, 347 | "nbformat_minor": 2 348 | } 349 | -------------------------------------------------------------------------------- /projects/Naive-Bayes/text-classification-naive-bayes.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "toc": "true" 7 | }, 8 | "source": [ 9 | " # Table of Contents\n", 10 | "
" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "# Document/Text Classification" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "This notebook is based on Scikit-learn example for [Classification of text documents using sparse features](http://scikit-learn.org/stable/auto_examples/text/document_classification_20newsgroups.html#example-text-document-classification-20newsgroups-py)." 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": 1, 30 | "metadata": {}, 31 | "outputs": [], 32 | "source": [ 33 | "import warnings\n", 34 | "warnings.filterwarnings(\"ignore\")\n", 35 | "\n", 36 | "import numpy as np\n", 37 | "import time \n", 38 | "%matplotlib inline\n", 39 | "import matplotlib\n", 40 | "matplotlib.style.use('seaborn')\n", 41 | "import matplotlib.pyplot as plt\n", 42 | "\n", 43 | "from sklearn import metrics" 44 | ] 45 | }, 46 | { 47 | "cell_type": "markdown", 48 | "metadata": {}, 49 | "source": [ 50 | "## Loading the data set" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "The data set used for this example is the **20 Newsgroup** data set. The original data set can be found [here](http://qwone.com/~jason/20Newsgroups/).\n", 58 | "\n", 59 | "\n", 60 | "The 20 Newsgroups data set is a collection of approximately 20,000 newsgroup documents, partitioned (nearly) evenly across 20 different newsgroups. \n", 61 | "\n", 62 | "This data set is in-built in scikit, so we don’t need to download it explicitly." 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 2, 68 | "metadata": { 69 | "collapsed": true 70 | }, 71 | "outputs": [], 72 | "source": [ 73 | "from sklearn.datasets import fetch_20newsgroups" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 3, 79 | "metadata": { 80 | "collapsed": true 81 | }, 82 | "outputs": [], 83 | "source": [ 84 | "data_train = fetch_20newsgroups(subset='train', shuffle=True, random_state=42)\n", 85 | "data_test = fetch_20newsgroups(subset='test', shuffle=True, random_state=42)" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": 4, 91 | "metadata": { 92 | "collapsed": true 93 | }, 94 | "outputs": [], 95 | "source": [ 96 | "y_train, y_test = data_train.target, data_test.target" 97 | ] 98 | }, 99 | { 100 | "cell_type": "markdown", 101 | "metadata": {}, 102 | "source": [ 103 | "- Check the target names (categories) and some data files." 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 5, 109 | "metadata": {}, 110 | "outputs": [ 111 | { 112 | "name": "stdout", 113 | "output_type": "stream", 114 | "text": [ 115 | "['alt.atheism', 'comp.graphics', 'comp.os.ms-windows.misc', 'comp.sys.ibm.pc.hardware', 'comp.sys.mac.hardware', 'comp.windows.x', 'misc.forsale', 'rec.autos', 'rec.motorcycles', 'rec.sport.baseball', 'rec.sport.hockey', 'sci.crypt', 'sci.electronics', 'sci.med', 'sci.space', 'soc.religion.christian', 'talk.politics.guns', 'talk.politics.mideast', 'talk.politics.misc', 'talk.religion.misc']\n" 116 | ] 117 | } 118 | ], 119 | "source": [ 120 | "# print all the categories\n", 121 | "categories = data_train.target_names\n", 122 | "print(categories)" 123 | ] 124 | }, 125 | { 126 | "cell_type": "markdown", 127 | "metadata": {}, 128 | "source": [ 129 | "- Print the first line of the first data file." 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": 6, 135 | "metadata": {}, 136 | "outputs": [ 137 | { 138 | "data": { 139 | "text/plain": [ 140 | "[\"From: lerxst@wam.umd.edu (where's my thing)\",\n", 141 | " 'Subject: WHAT car is this!?',\n", 142 | " 'Nntp-Posting-Host: rac3.wam.umd.edu',\n", 143 | " 'Organization: University of Maryland, College Park',\n", 144 | " 'Lines: 15',\n", 145 | " '',\n", 146 | " ' I was wondering if anyone out there could enlighten me on this car I saw',\n", 147 | " 'the other day. It was a 2-door sports car, looked to be from the late 60s/',\n", 148 | " 'early 70s. It was called a Bricklin. The doors were really small. In addition,',\n", 149 | " 'the front bumper was separate from the rest of the body. This is ',\n", 150 | " 'all I know. If anyone can tellme a model name, engine specs, years',\n", 151 | " 'of production, where this car is made, history, or whatever info you',\n", 152 | " 'have on this funky looking car, please e-mail.',\n", 153 | " '',\n", 154 | " 'Thanks,',\n", 155 | " '- IL',\n", 156 | " ' ---- brought to you by your neighborhood Lerxst ----',\n", 157 | " '',\n", 158 | " '',\n", 159 | " '',\n", 160 | " '',\n", 161 | " '']" 162 | ] 163 | }, 164 | "execution_count": 6, 165 | "metadata": {}, 166 | "output_type": "execute_result" 167 | } 168 | ], 169 | "source": [ 170 | "data_train.data[0].split(\"\\n\")" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": {}, 176 | "source": [ 177 | "## Extracting features from text files." 178 | ] 179 | }, 180 | { 181 | "cell_type": "markdown", 182 | "metadata": {}, 183 | "source": [ 184 | "- Text files are actually series of words (ordered). In order to run machine learning algorithms we need to convert the text files into numerical feature vectors.\n", 185 | "- We will be using [the-bag-of-words model](https://en.wikipedia.org/wiki/Bag-of-words_model) for this case.\n", 186 | "- We segment each text file into words (for English splitting by space), and count the number of times each word occurs in each document and finally assign each word an integer id. Each unique word in our dictionary will correspond to a feature (descriptive feature).\n", 187 | "\n", 188 | "\n", 189 | "- We use **```TfidVectorizer()```** which converts a collection of raw documents to a matrix of TF-IDF features. **Tf means term-frequency while tf-idf means term-frequency times inverse document-frequency**. This is a common term weighting scheme in information retrieval, that has also found good use in document classification. The goal of using tf-idf instead of the raw frequencies of occurrence of a token in a given document is to scale down the impact of tokens that occur very frequently in a given corpus and that are hence empirically less informative than features that occur in a small fraction of the training corpus." 190 | ] 191 | }, 192 | { 193 | "cell_type": "markdown", 194 | "metadata": {}, 195 | "source": [ 196 | "### Extracting features from the training data using a sparse vectorizer" 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": 7, 202 | "metadata": { 203 | "collapsed": true 204 | }, 205 | "outputs": [], 206 | "source": [ 207 | "from sklearn.feature_extraction.text import HashingVectorizer, TfidfVectorizer" 208 | ] 209 | }, 210 | { 211 | "cell_type": "code", 212 | "execution_count": 8, 213 | "metadata": {}, 214 | "outputs": [], 215 | "source": [ 216 | "vectorizer = TfidfVectorizer(sublinear_tf=True, max_df=0.5, stop_words='english')" 217 | ] 218 | }, 219 | { 220 | "cell_type": "code", 221 | "execution_count": 9, 222 | "metadata": {}, 223 | "outputs": [ 224 | { 225 | "name": "stdout", 226 | "output_type": "stream", 227 | "text": [ 228 | "n_samples: 11314, n_features: 129791\n" 229 | ] 230 | } 231 | ], 232 | "source": [ 233 | "X_train = vectorizer.fit_transform(data_train.data)\n", 234 | "print(\"n_samples: %d, n_features: %d\" % X_train.shape)" 235 | ] 236 | }, 237 | { 238 | "cell_type": "markdown", 239 | "metadata": {}, 240 | "source": [ 241 | "### Extracting features from the test data using the same vectorizer" 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": 10, 247 | "metadata": {}, 248 | "outputs": [ 249 | { 250 | "name": "stdout", 251 | "output_type": "stream", 252 | "text": [ 253 | "n_samples: 7532, n_features: 129791\n" 254 | ] 255 | } 256 | ], 257 | "source": [ 258 | "X_test = vectorizer.transform(data_test.data)\n", 259 | "print(\"n_samples: %d, n_features: %d\" % X_test.shape)" 260 | ] 261 | }, 262 | { 263 | "cell_type": "markdown", 264 | "metadata": {}, 265 | "source": [ 266 | "## Training + Testing Naive Bayes algorithm" 267 | ] 268 | }, 269 | { 270 | "cell_type": "code", 271 | "execution_count": 11, 272 | "metadata": { 273 | "collapsed": true 274 | }, 275 | "outputs": [], 276 | "source": [ 277 | "from sklearn.naive_bayes import MultinomialNB, BernoulliNB" 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": 12, 283 | "metadata": { 284 | "collapsed": true 285 | }, 286 | "outputs": [], 287 | "source": [ 288 | "clfs = [\n", 289 | " (\"MultinomialNB\", MultinomialNB(alpha=.01)),\n", 290 | " (\"BernoulliNB\", BernoulliNB(alpha=.01))\n", 291 | "]" 292 | ] 293 | }, 294 | { 295 | "cell_type": "code", 296 | "execution_count": 23, 297 | "metadata": { 298 | "collapsed": true 299 | }, 300 | "outputs": [], 301 | "source": [ 302 | "def print_confusion_matrix(clf, x_test, y_test):\n", 303 | " \n", 304 | " # Get the predicted classifications for the test-set\n", 305 | " cls_pred = clf.predict(x_test)\n", 306 | " \n", 307 | " # Get the confusion matrix using sklearn\n", 308 | " cm = metrics.confusion_matrix(y_true=y_test,\n", 309 | " y_pred=cls_pred)\n", 310 | " \n", 311 | " # Print the confusion matrix as text\n", 312 | " #print(\"\\n\\n\")\n", 313 | " #print(cm)\n", 314 | " \n", 315 | " num_classes = len(categories)\n", 316 | " # Plot the confusion matrix.\n", 317 | " plt.imshow(cm, interpolation='nearest', cmap=plt.cm.jet)\n", 318 | " \n", 319 | " # Make various adjustments to the plot.\n", 320 | " plt.tight_layout()\n", 321 | " plt.colorbar()\n", 322 | " tick_marks = np.arange(num_classes)\n", 323 | " plt.xticks(tick_marks, range(num_classes))\n", 324 | " plt.yticks(tick_marks, range(num_classes))\n", 325 | " plt.xlabel('Predicted')\n", 326 | " plt.ylabel('True')\n", 327 | " plt.show()\n", 328 | "\n" 329 | ] 330 | }, 331 | { 332 | "cell_type": "code", 333 | "execution_count": 24, 334 | "metadata": {}, 335 | "outputs": [], 336 | "source": [ 337 | "def train_and_test():\n", 338 | " \n", 339 | " for name, clf in clfs:\n", 340 | " clf.fit(X_train, y_train)\n", 341 | " predicted = clf.predict(X_test)\n", 342 | " score = clf.score(X_test, y_test)\n", 343 | " print(\"{} 's Accuracy = {} %\".format(name, round(score*100,4)))\n", 344 | " print(\"\\n\\n\\n{} 's Confusion Matrix\".format(name))\n", 345 | " print_confusion_matrix(clf, X_test, y_test)\n", 346 | " " 347 | ] 348 | }, 349 | { 350 | "cell_type": "code", 351 | "execution_count": 25, 352 | "metadata": {}, 353 | "outputs": [ 354 | { 355 | "name": "stdout", 356 | "output_type": "stream", 357 | "text": [ 358 | "MultinomialNB 's Accuracy = 83.7361 %\n", 359 | "\n", 360 | "\n", 361 | "\n", 362 | "MultinomialNB 's Confusion Matrix\n" 363 | ] 364 | }, 365 | { 366 | "data": { 367 | "image/png": "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\nAAAASUVORK5CYII=\n", 368 | "text/plain": [ 369 | "" 370 | ] 371 | }, 372 | "metadata": {}, 373 | "output_type": "display_data" 374 | }, 375 | { 376 | "name": "stdout", 377 | "output_type": "stream", 378 | "text": [ 379 | "BernoulliNB 's Accuracy = 77.111 %\n", 380 | "\n", 381 | "\n", 382 | "\n", 383 | "BernoulliNB 's Confusion Matrix\n" 384 | ] 385 | }, 386 | { 387 | "data": { 388 | "image/png": "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\n", 389 | "text/plain": [ 390 | "" 391 | ] 392 | }, 393 | "metadata": {}, 394 | "output_type": "display_data" 395 | }, 396 | { 397 | "name": "stdout", 398 | "output_type": "stream", 399 | "text": [ 400 | "CPU times: user 2.42 s, sys: 1.52 s, total: 3.93 s\n", 401 | "Wall time: 2.23 s\n" 402 | ] 403 | } 404 | ], 405 | "source": [ 406 | "%%time\n", 407 | "train_and_test()" 408 | ] 409 | }, 410 | { 411 | "cell_type": "code", 412 | "execution_count": 16, 413 | "metadata": {}, 414 | "outputs": [ 415 | { 416 | "data": { 417 | "application/json": { 418 | "Software versions": [ 419 | { 420 | "module": "Python", 421 | "version": "3.6.2 64bit [GCC 4.8.2 20140120 (Red Hat 4.8.2-15)]" 422 | }, 423 | { 424 | "module": "IPython", 425 | "version": "6.1.0" 426 | }, 427 | { 428 | "module": "OS", 429 | "version": "Linux 4.4.0 53 generic x86_64 with debian stretch sid" 430 | }, 431 | { 432 | "module": "numpy", 433 | "version": "1.12.1" 434 | }, 435 | { 436 | "module": "matplotlib", 437 | "version": "2.0.2" 438 | }, 439 | { 440 | "module": "sklearn", 441 | "version": "0.19.0" 442 | } 443 | ] 444 | }, 445 | "text/html": [ 446 | "
SoftwareVersion
Python3.6.2 64bit [GCC 4.8.2 20140120 (Red Hat 4.8.2-15)]
IPython6.1.0
OSLinux 4.4.0 53 generic x86_64 with debian stretch sid
numpy1.12.1
matplotlib2.0.2
sklearn0.19.0
Sun Sep 24 13:57:04 2017 CDT
" 447 | ], 448 | "text/latex": [ 449 | "\\begin{tabular}{|l|l|}\\hline\n", 450 | "{\\bf Software} & {\\bf Version} \\\\ \\hline\\hline\n", 451 | "Python & 3.6.2 64bit [GCC 4.8.2 20140120 (Red Hat 4.8.2-15)] \\\\ \\hline\n", 452 | "IPython & 6.1.0 \\\\ \\hline\n", 453 | "OS & Linux 4.4.0 53 generic x86\\_64 with debian stretch sid \\\\ \\hline\n", 454 | "numpy & 1.12.1 \\\\ \\hline\n", 455 | "matplotlib & 2.0.2 \\\\ \\hline\n", 456 | "sklearn & 0.19.0 \\\\ \\hline\n", 457 | "\\hline \\multicolumn{2}{|l|}{Sun Sep 24 13:57:04 2017 CDT} \\\\ \\hline\n", 458 | "\\end{tabular}\n" 459 | ], 460 | "text/plain": [ 461 | "Software versions\n", 462 | "Python 3.6.2 64bit [GCC 4.8.2 20140120 (Red Hat 4.8.2-15)]\n", 463 | "IPython 6.1.0\n", 464 | "OS Linux 4.4.0 53 generic x86_64 with debian stretch sid\n", 465 | "numpy 1.12.1\n", 466 | "matplotlib 2.0.2\n", 467 | "sklearn 0.19.0\n", 468 | "Sun Sep 24 13:57:04 2017 CDT" 469 | ] 470 | }, 471 | "execution_count": 16, 472 | "metadata": {}, 473 | "output_type": "execute_result" 474 | } 475 | ], 476 | "source": [ 477 | "%load_ext version_information\n", 478 | "%version_information numpy, matplotlib, sklearn" 479 | ] 480 | } 481 | ], 482 | "metadata": { 483 | "kernelspec": { 484 | "display_name": "Python 3", 485 | "language": "python", 486 | "name": "python3" 487 | }, 488 | "language_info": { 489 | "codemirror_mode": { 490 | "name": "ipython", 491 | "version": 3 492 | }, 493 | "file_extension": ".py", 494 | "mimetype": "text/x-python", 495 | "name": "python", 496 | "nbconvert_exporter": "python", 497 | "pygments_lexer": "ipython3", 498 | "version": "3.6.2" 499 | }, 500 | "toc": { 501 | "nav_menu": {}, 502 | "number_sections": true, 503 | "sideBar": true, 504 | "skip_h1_title": false, 505 | "toc_cell": true, 506 | "toc_position": {}, 507 | "toc_section_display": "block", 508 | "toc_window_display": true 509 | } 510 | }, 511 | "nbformat": 4, 512 | "nbformat_minor": 2 513 | } 514 | --------------------------------------------------------------------------------