{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Homework 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Survey due 4th September, 2015" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##Submission due 10th September, 2015" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "Welcome to CS109 / STAT121 / AC209 / E-109 (http://cs109.org/). In this class, we will be using a variety of tools that will require some initial configuration. To ensure everything goes smoothly moving forward, we will setup the majority of those tools in this homework. **It is very important that you do this setup as soon as possible**. While some of this will likely be dull, doing it now will enable us to do more exciting work in the weeks that follow without getting bogged down in further software configuration. You will also be filling out a **mandatory class survey and creating a github and AWS account, which are mandatory as well**. \n", "\n", "Please note that the **survey is due on September 4th**. The reason is that we need your github account name to set you up for the homework submission system. If you do not submit the survey on time you might not be able to submit the homework in time.\n", "\n", "This homework will not be graded, however, you **must submit it**. Submission instructions, along with the github flow for homework, are at the end of this notebook. The practice you will get submitting this homework will be essential for the submission of the forthcoming homework notebooks and your project." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Table of Contents\n", "* [Homework 0](#Homework-0)\n", "\t* [Survey due 4th September, 2015](#Survey-due-4th-September,-2015)\n", "\t* [Submission due 10th September, 2015](#Submission-due-10th-September,-2015)\n", "\t* [First Things](#First-Things)\n", "\t\t* [1. Create your github account](#1.-Create-your-github-account)\n", "\t\t* [2. Class Survey](#2.-Class-Survey)\n", "\t\t* [3. Piazza](#3.-Piazza)\n", "\t\t* [4. Programming expectations](#4.-Programming-expectations)\n", "\t\t* [5. If you do not have a .edu email address](#5.-If-you-do-not-have-a-.edu-email-address)\n", "\t* [Getting and installing Python](#Getting-and-installing-Python)\n", "\t\t* [Installing Anaconda](#Installing-Anaconda)\n", "\t\t* [Mac/Linux users](#Mac/Linux-users)\n", "\t\t* [Windows Users](#Windows-Users)\n", "\t\t* [Troubleshooting](#Troubleshooting)\n", "\t* [Setting up your git environment](#Setting-up-your-git-environment)\n", "\t\t* [1. Installing git](#1.-Installing-git)\n", "\t\t\t* [Windows specific notes](#Windows-specific-notes)\n", "\t\t\t* [Mac specific notes](#Mac-specific-notes)\n", "\t\t* [2. Optional: Creating ssh keys on your machine](#2.-Optional:-Creating-ssh-keys-on-your-machine)\n", "\t\t* [3. Optional: Uploading ssh keys and Authentication](#3.--Optional:-Uploading-ssh-keys-and-Authentication)\n", "\t\t* [4. Setting global config for git](#4.-Setting-global-config-for-git)\n", "\t\t* [5. Github tutorial](#5.-Github-tutorial)\n", "\t* [Sign up for AWS](#Sign-up-for-AWS)\n", "\t\t* [1. Get an AWS account](#1.-Get-an-AWS-account)\n", "\t\t* [2. Sign up for AWS educate](#2.-Sign-up-for-AWS-educate)\n", "\t* [Hello, Python](#Hello,-Python)\n", "\t* [Python Libraries](#Python-Libraries)\n", "\t\t* [Installing additional libraries](#Installing-additional-libraries)\n", "\t\t* [Testing latest libraries](#Testing-latest-libraries)\n", "\t* [Kicking the tires](#Kicking-the-tires)\n", "\t\t* [Hello World](#Hello-World)\n", "\t\t* [Hello matplotlib](#Hello-matplotlib)\n", "\t\t* [Hello Numpy](#Hello-Numpy)\n", "\t* [The Monty Hall Problem](#The-Monty-Hall-Problem)\n", "\t* [The workflow for homeworks and labs](#The-workflow-for-homeworks-and-labs)\n", "\t\t* [getting and working on labs](#getting-and-working-on-labs)\n", "\t\t* [getting and submitting homework](#getting-and-submitting-homework)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## First Things" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I cant stress this enough: **Do this setup now!**\n", "\n", "These first things are incredibly important. You must absolutely fill these out to get into the swing of things..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1. Create your github account" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you do not have a github account as yet, create it at:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "https://github.com\n", "\n", "This step is **mandatory**. We will need your github username. We are using github for all aspects of this course, including\n", "\n", "- doing and submitting homework\n", "- collaborating on your project\n", "- creating your web site" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To sign up for an account, just go to [github](https://github.com) and pick a unique username, an email address, and a password. Once you've done that, your github page will be at https://github.com/your-username.\n", "\n", "Github also provides a student [developer package](https://education.github.com/pack). This is something that might be nice to have, but it is not necessary for the course. Github may take some time to approve your application for the package. Please note that this is optional and you do not have to have the package approved to fill out the survey. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###2. Class Survey" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, you **must complete the mandatory** course survey located [here](http://goo.gl/forms/bJwajS8zO8). It should only take a few moments of your time. Once you fill in the survey we will use the github username you provided to sign you up into the `cs109-students` organization on github. (see https://help.github.com/articles/how-do-i-access-my-organization-account/) It is imperative that you fill out the survey on time as we use the provided information to sign you in: your access to the homework depends on being in this organization. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###3. Piazza" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Go to [Piazza](https://piazza.com/harvard/fall2015/cs109/home) and sign up for the class using your Harvard e-mail address. If you do not have a Harvard email address write an email to staff@cs109.org and one of the TFs will sign you up.\n", "\n", "You will use Piazza as a forum for discussion, to find team members, to arrange appointments, and to ask questions. Piazza should be your primary form of communication with the staff. Use the staff e-mail (staff@cs109.org) only for individual requests, e.g., to excuse yourself from mandatory sections. All announcements, homework, and project descriptions will be posted on Piazza first. \n", "\n", "**Introduction**\n", "\n", "Once you are signed up to the Piazza course forum, introduce yourself to your classmates and course staff with a follow-up post in the introduction thread. Include your name/nickname, your affiliation, why you are taking this course, and tell us something interesting about yourself (e.g., an industry job, an unusual hobby, past travels, or a cool project you did, etc.). Also tell us whether you have experience with data science." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###4. Programming expectations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All the assignments and labs for this class will use Python and, for the most part, the browser-based IPython notebook format you are currently viewing. Knowledge of Python is not a prerequisite for this course, **provided you are comfortable learning on your own as needed**. While we have strived to make the programming component of this course straightforward, we will not devote much time to teaching prorgramming or Python syntax. Basically, you should feel comfortable with:\n", "\n", "* How to look up Python syntax on Google and StackOverflow.\n", "* Basic programming concepts like functions, loops, arrays, dictionaries, strings, and if statements.\n", "* How to learn new libraries by reading documentation.\n", "* Asking questions on StackOverflow or Piazza.\n", "\n", "There are many online tutorials to introduce you to scientific python programming. [Here is a course](https://github.com/jrjohansson/scientific-python-lectures) that is very nice. Lectures 1-4 of this course are most relevant to this class. While we will cover some python programming in labs 1 and 2, we expect you to pick it up on the fly. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###5. If you do not have a .edu email address" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Please get one, as you will need it to sign up for AWS educate, and if you want to sign up for the student developer github package you will need it as well. As a DCE student you are eligible for a FAS account and you can sign up [here](http://www.extension.harvard.edu/resources-policies/resources/computer-e-mail-services)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Getting and installing Python" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You will be using Python throughout the course, including many popular 3rd party Python libraries for scientific computing. [Anaconda](http://continuum.io/downloads) is an easy-to-install bundle of Python and most of these libraries. We **strongly** recommend that you use Anaconda for this course. If you insist on using your own Python setup instead of Anaconda, we will not provide any installation support, and are not responsible for you loosing points on homework assignments in case of inconsistencies. \n", "\n", "For this course we are using **Python 2**, not **Python 3**.\n", "\n", "Also see: http://docs.continuum.io/anaconda/install\n", "\n", "The **IPython** or **Jupyter** notebook runs in the browser, and works best in Google Chrome or Safari for me. You probably want to use one of these for assignments in this course." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Installing Anaconda" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The Anaconda Python distribution is an easily-installable bundle of Python and many of the libraries used throughout this class. Unless you have a good reason not to, we recommend that you use Anaconda." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Mac/Linux users" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Download the [appropriate version](http://continuum.io/downloads) of Anaconda\n", "1. Follow the instructions on that page to run the installer\n", "1. Test out the IPython notebook: open a Terminal window, and type `ipython notebook`. Or use the Anaconda Launcher which might have been deposited on your desktop. A new browser window should pop up. \n", "1. Click `New Notebook` to create a new notebook file. **Trick**: give this notebook a unique name, like `my-little-rose`. Use Spotlight (upper right corner of the mac desktop, looks like a maginifier) to search for this name. In this way, you will know which folder your notebook opens in by default." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Windows Users" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Download the [appropriate version](http://continuum.io/downloads) of Anaconda\n", "1. Follow the instructions on that page to run the installer. This will typically create a directory at `C:\\Anaconda`\n", "1. Test it out: start the Anaconda launcher, which you can find in `C:\\Anaconda` or, in the Start menu. Start the IPython notebook. A new browser window should open. \n", "1. Click `New Notebook`, which should open a new page. **Trick**: give this notebook a unique name, like `my-little-rose`. Use Explorer (usually start menu on windows desktops) to search for this name. In this way, you will know which folder your notebook opens in by default.\n", "\n", "If you did not add Anaconda to your path, be sure to use the full path to the python and ipython executables, such as `/anaconda/bin/python`.\n", "\n", "If you already have installed Anaconda at some point in the past, you can easily update to the latest Anaconda version by updating conda, then Anaconda as follows:\n", "\n", "```\n", "conda update conda\n", "conda update anaconda\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Troubleshooting" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You must be careful to make sure you are running the Anaconda version of python, since those operating systems come preinstalled with their own versions of python." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'3.6.1 |Anaconda 4.4.0 (x86_64)| (default, May 11 2017, 13:04:09) \\n[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)]'" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import sys\n", "sys.version" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Problem**\n", "When you start python, you don't see a line like `Python 2.7.5 |Anaconda 1.6.1 (x86_64)|`. You are using a Mac or Linux computer\n", "\n", "**Reason**\n", "You are most likely running a different version of Python, and need to modify your Path (the list of directories your computer looks through to find programs). \n", "\n", "**Solution**\n", "Find a file like `.bash_profile`, `.bashrc`, or `.profile`. Open the file in a text editor, and add a line at this line at the end: `export PATH=\"$HOME/anaconda/bin:$PATH\"`. Close the file, open a new terminal window, type `source ~/.profile` (or whatever file you just edited). Type `which python` -- you should see a path that points to the anaconda directory. If so, running `python` should load the proper version\n", "\n", "If this doesn't work (typing `which python` doesn't point to anaconda), you might be using a different shell. Type `echo $SHELL`. If this isn't `bash`, you need to edit a different startup file (for example, if if `echo $SHELL` gives `$csh`, you need to edit your `.cshrc` file. The syntax for this file is slightly different: `set PATH = ($HOME/anaconda/bin $PATH)`\n", "***\n", "\n", "**Problem**\n", "You are running the right version of python (see above item), but are unable to import numpy. \n", "\n", "**Reason**\n", "You are probably loading a different copy of numpy that is incompatible with Anaconda\n", "\n", "**Solution**\n", "See the above item to find your `.bash_profile`, `.profile`, or `.bashrc` file. Open it, and add the line `unset PYTHONPATH` at the end. Close the file, open a new terminal window, type `source ~/.profile` (or whatever file you just edited), and try again.\n", "***\n", "\n", "**Problem**\n", "Under Windows, you receive an error message similar to the following: \"'pip' is not recognized as an internal or external command, operable program or batch file.\"\n", "\n", "**Reason**\n", "The correct Anaconda paths might not be present in your PATH variable, or Anaconda might not have installed correctly.\n", "\n", "**Solution**\n", "Ensure the Anaconda directories to your path environment variable (\"\\Anaconda\" and \"\\Anaconda\\Scripts\"). See [this page](http://superuser.com/questions/284342/what-are-path-and-other-environment-variables-and-how-can-i-set-or-use-them) for details.\n", "\n", "If this does not correct the problem, reinstall Anaconda.\n", "\n", "\n", "**IF YOU ARE STILL HAVING ISSUES ON THE INSTALL, POST TO PIAZZA. WE'LL HELP YOU THERE. OR ASK IN YOUR SECTION**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setting up your git environment" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###1. Installing git" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will be using the command line version of git.\n", "\n", "On linux, install git using your system package manager (yum, apt-get, etc)\n", "\n", "On the Mac, if you ever installed Xcode, you should have git installed. Or you might have installed it using `homebrew`. Either of these are fine as long as the git version is greater than 2.0\n", "\n", "Otherwise, on Mac and Windows, go to http://git-scm.com. Accept all defaults in the installation process. On Windows, installing git will also install for you a minimal unix environment with a \"bash\" shell and terminal window. Voila, your windows computer is transformed into a unixy form." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "####Windows specific notes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There will be an installer `.exe` file you need to click. Accept all the defaults.\n", "\n", "Here is a screenshot from one of the defaults. It makes sure you will have the \"bash\" tool talked about earlier.\n", "![use git bash](wgi-git-bash.png)\n", "\n", "Choose the default line-encoding conversion:\n", "![default lines](wgi-defaultlines.png)\n", "\n", "Use the terminal emulator they provide, its better than the one shipped with windows.\n", "![use mintty](wgi-usemintty.png)\n", "\n", "Towards the end, you might see a message like this. It looks scary, but all you need to do is click \"Continue\"\n", "![scary message](wgi-scarymessage.png)\n", "\n", "\n", "At this point you will be installed. You can bring up \"git bash\" either from your start menu, or from the right click menu on any folder background. When you do so, a terminal window will open. This terminal is where you will issue further git setup commands, and git commands in general.\n", "\n", "Get familiar with the terminal. It opens in your home folder, and maps `\\\\` paths on windows to more web/unix like paths with '/'. Try issuing the commands `ls`, `pwd`, and `cd folder` where folder is one of the folders you see when you do a ls. You can do a `cd ..` to come back up.\n", "\n", "You can also use the terminal which comes with the ipython notebook. More about that later." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "####Mac specific notes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As mentioned earlier, if you ever installed Xcode or the \"Command Line Developer tools\", you may already have git.\n", "Make sure its version 2.0 or higher. (`git --version`)\n", "\n", "Or if you use **Homebrew**, you can install it from there. The current version on homebrew is 2.4.3\n", " You dont need to do anyting more in this section.\n", "\n", "-----\n", "\n", "First click on the `.mpkg` file that comes when you open the downloaded `.dmg` file.\n", "\n", "When I tried to install git on my mac, I got a warning saying my security preferences wouldnt allow it to be installed. So I opened my system preferences and went to \"Security\".\n", "\n", "![system pref](mac-git-security.png)\n", "\n", "Here you must click \"Open Anyway\", and the installer will run.\n", "\n", "The installer puts git as `/usr/local/git/bin/git`. Thats not a particularly useful spot. Open up `Terminal.app`.Its usually in `/Applications/Utilities`. Once the terminal opens up, issue\n", "\n", "`sudo ln -s /usr/local/git/bin/git /usr/local/bin/git`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Keep the Terminal application handy in your dock. (You could also download and use iTerm.app, which is a nicer terminal, if you are into terminal geekery). We'll be using the terminal extensively for git. You can also use the terminal which comes with the ipython notebook. More about that later.\n", "\n", "Try issuing the commands `ls`, `pwd`, and `cd folder` where folder is one of the folders you see when you do a ls. You can do a `cd ..` to come back up." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###2. Optional: Creating ssh keys on your machine" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This ia an optional step. But it makes things much easier.\n", "\n", "There are two ways git talks to github: https, which is a web based protocol\n", "\n", "![github https](github-https-clone.png)\n", "\n", "or over ssh\n", "\n", "![github ssh](github-ssh-clone.png)\n", "\n", "Which one you use is your choice. I recommend ssh, and the github urls in this homework and in labs will be ssh urls.\n", "Every time you contact your upstream repository (hosted on github), you need to prove you're you. You *can* do this with passwords over HTTPS, but it gets old quickly. By providing an ssh public key to github, your ssh-agent will handle all of that for you, and you wont have to put in any passwords.\n", "\n", "At your terminal, issue the command (skip this if you are a seasoned ssh user and already have keys):\n", "\n", "`ssh-keygen -t rsa`\n", "\n", "It will look like this:\n", "![github ssh keygen](sshkeygen.png)\n", "\n", "Accept the defaults. When it asks for a passphrase for your keys, put in none. (you can put in one if you know how to set up a ssh-agent).\n", "\n", "This will create two files for you, in your home folder if you accepted the defaults." ] }, { "cell_type": "raw", "metadata": {}, "source": [ "➜ ~ ls .ssh/id_rsa*\n", ".ssh/id_rsa .ssh/id_rsa.pub" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`id_rsa` is your PRIVATE key. NEVER NEVER NEVER give that to anyone. `id_rsa.pub` is your public key. You must supply this to github." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "----" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###3. Optional: Uploading ssh keys and Authentication" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To upload an ssh key, log in to github and click on the gear icon in the top right corner (settings). Once you're there, click on \"SSH keys\" on the left. This page will contain all your ssh keys once you upload any.\n", "\n", "Click on \"add ssh key\" in the top right. You should see this box:\n", "\n", "\"github\n", "\n", "The title field should be the name of your computer or some other way to identify this particular ssh key.\n", "\n", "In the key field, you'll need to copy and paste your *public* key. **Do not paste your private ssh key here.**\n", "\n", "When you hit \"Add key\", you should see the key name and some hexadecimal characters show up in the list. You're set.\n", "\n", "Now, whenever you clone a repository using this form:\n", "\n", "`$ git clone git@github.com:rdadolf/ac297r-git-demo.git`,\n", "\n", "you'll be connecting over ssh, and will not be asked for your github password\n", "\n", "You will need to repeat steps 2 and 3 of the setup for each computer you wish to use with github." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###4. Setting global config for git" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Again, from the terminal, issue the command\n", "\n", "`git config --global user.name \"YOUR NAME\"`\n", "\n", "This sets up a name for you. Then do\n", "\n", "`git config --global user.email \"YOUR EMAIL ADDRESS\"`\n", "\n", "Use the **SAME** email address you used in setting up your github account.\n", "\n", "These commands set up your global configuration. On my Mac, these are stored in the text file `.gitconfig` in my home folder." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###5. Github tutorial" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Read our git and github tutorial from [Lab 1](https://github.com/cs109/2015lab1/blob/master/Lab1-git.ipynb). Then come back here.\n", "\n", "If you have any issues or questions: Ask us! On Piazza or in Sections!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Sign up for AWS" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For the course you need to sign up for Amazon Web Services (AWS). \n", "\n", "- The sign up process has two steps:\n", " 1. Get an AWS account\n", " 2. Sign up for AWS educate\n", "\n", "The AWS account will enable you to access Amazon's webservices. The AWS educate sign up will provide you with $100 worth of free credits." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1. Get an AWS account" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note: You can skip this step if you already have an account. \n", "\n", "- Go to [this webpage](https://aws.amazon.com/education/awseducate/apply/)\n", "- Click on the yellow box in the upper right corner saying \"Create an AWS account\"\n", "- Follow the normal instructions and fill in all necessary information to create your account.\n", "\n", "Once you have an account you need your account ID. The account ID is a 12 digit number. \n", "Please follow [this description](http://docs.aws.amazon.com/IAM/latest/UserGuide/console_account-alias.html) to find your ID in the Support menu of your AWS console." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2. Sign up for AWS educate" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note: You will need your 12 digit AWS account ID for this step.\n", "\n", "- Go to [this webpage](https://aws.amazon.com/education/awseducate/apply/)\n", "- Click on the right on the button saying \"Apply for AWS Educate for Students\"\n", "- Confirm that you are a student\n", "- Fill out the form\n", "- **Note that that you provide should come from your institution, which means it should end in .edu** \n", "- It might take a few days for your request to be approved. \n", "\n", "Once again, ping us if you need help!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Hello, Python" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The IPython/Jupyter notebook is an application to build interactive computational notebooks. You'll be using them to complete labs and homework. Once you've set up Python, please download this page, and open it with IPython by typing\n", "\n", "```\n", "ipython notebook \n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also open the notebook in any folder by `cd`ing to the folder in the terminal, and typing\n", "\n", "```\n", "ipython notebook .\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "in that folder.\n", "\n", "The anaconda install also probably dropped a launcher on your desktop. You can use the launcher, and select \"ipython notebbok\" or \"jupyter notebook\" from there. In this case you will need to find out which folder you are running in.\n", "\n", "It loolks like this for me:\n", "\n", "![jupyter](jupyter.png)\n", "\n", "Notice that you can use the user interface to create new folders and text files, and even open new terminals, all of which might come useful to you. To create a new notebook, you can use \"Python 2\" under notebooks. You may not have the other choices available (I have julia for example, which is another language that uses the same notebook interface)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For the rest of the assignment, use your local copy of this page, running on IPython.\n", "\n", "Notebooks are composed of many \"cells\", which can contain text (like this one), or code (like the one below). Double click on the cell below, and evaluate it by clicking the \"play\" button above, for by hitting shift + enter" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Item is 10\n", "Item is 20\n", "Item is 30\n", "Item is 40\n", "Item is 50\n" ] } ], "source": [ "x = [10, 20, 30, 40, 50]\n", "for item in x:\n", " print(\"Item is \", item)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Python Libraries" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Installing additional libraries" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Anaconda includes most of the libraries we will use in this course, but you will need to install a few extra ones for the beginning of this course:\n", "\n", "1. [BeautifulSoup](http://www.crummy.com/software/BeautifulSoup/)\n", "1. [Seaborn](http://web.stanford.edu/~mwaskom/software/seaborn/)\n", "1. [PyQuery](https://pythonhosted.org/pyquery/)\n", "\n", "The recommended way to install these packages is to run \n", "\n", "`!pip install BeautifulSoup seaborn pyquery` \n", "\n", "in a code cell in the ipython notebook you just created. On windows, you might want to run `pip install BeautifulSoup seaborn pyquery` on the `git-bash.exe` terminal (note, the exclamation goes away).\n", "\n", "If this doesn't work, you can download the source code, and run `python setup.py install` from the source code directory. On Unix machines(Mac or Linux), either of these commands may require `sudo` (i.e. `sudo pip install...` or `sudo python`)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you've successfully completed the above install, all of the following statements should run." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Testing latest libraries" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "IPython version: 5.3.0 (need at least 3.0.0)\n", "Numpy version: 1.13.0 (need at least 1.9.1)\n", "SciPy version: 0.19.0 (need at least 0.15.1)\n", "Pandas version: 0.20.1 (need at least 0.16.2)\n", "Mapltolib version: 2.0.2 (need at least 1.4.1)\n", "Scikit-Learn version: 0.18.1 (need at least 0.16.1)\n", "requests version: 2.17.3 (need at least 2.0.0)\n", "BeautifulSoup version: 4.6.0 (need at least 4.4)\n", "Loaded PyQuery\n" ] } ], "source": [ "#IPython is what you are using now to run the notebook\n", "import IPython\n", "print(\"IPython version: %6.6s (need at least 3.0.0)\" % IPython.__version__)\n", "\n", "# Numpy is a library for working with Arrays\n", "import numpy as np\n", "print(\"Numpy version: %6.6s (need at least 1.9.1)\" % np.__version__)\n", "\n", "# SciPy implements many different numerical algorithms\n", "import scipy as sp\n", "print(\"SciPy version: %6.6s (need at least 0.15.1)\" % sp.__version__)\n", "\n", "# Pandas makes working with data tables easier\n", "import pandas as pd\n", "print(\"Pandas version: %6.6s (need at least 0.16.2)\" % pd.__version__)\n", "\n", "# Module for plotting\n", "import matplotlib\n", "print(\"Mapltolib version: %6.6s (need at least 1.4.1)\" % matplotlib.__version__)\n", "\n", "# SciKit Learn implements several Machine Learning algorithms\n", "import sklearn\n", "print(\"Scikit-Learn version: %6.6s (need at least 0.16.1)\" % sklearn.__version__)\n", "\n", "# Requests is a library for getting data from the Web\n", "import requests\n", "print(\"requests version: %6.6s (need at least 2.0.0)\" % requests.__version__)\n", "\n", "#BeautifulSoup is a library to parse HTML and XML documents\n", "import bs4\n", "print(\"BeautifulSoup version:%6.6s (need at least 4.4)\" % bs4.__version__)\n", "\n", "import pyquery\n", "print(\"Loaded PyQuery\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If any of these libraries are missing or out of date, you will need to install them and restart IPython." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Kicking the tires" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lets try some things, starting from very simple, to more complex." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Hello World" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following is the incantation we like to put at the beginning of every notebook. It loads most of the stuff we will regularly use." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# The %... is an iPython thing, and is not part of the Python language.\n", "# In this case we're just telling the plotting library to draw things on\n", "# the notebook, instead of on a separate window.\n", "%matplotlib inline \n", "#this line above prepares IPython notebook for working with matplotlib\n", "\n", "# See all the \"as ...\" contructs? They're just aliasing the package names.\n", "# That way we can call methods like plt.plot() instead of matplotlib.pyplot.plot().\n", "\n", "import numpy as np # imports a fast numerical programming library\n", "import scipy as sp #imports stats functions, amongst other things\n", "import matplotlib as mpl # this actually imports matplotlib\n", "import matplotlib.cm as cm #allows us easy access to colormaps\n", "import matplotlib.pyplot as plt #sets up plotting under plt\n", "import pandas as pd #lets us handle data as dataframes\n", "#sets up pandas table display\n", "pd.set_option('display.width', 500)\n", "pd.set_option('display.max_columns', 100)\n", "pd.set_option('display.notebook_repr_html', True)\n", "import seaborn as sns #sets up styles and gives us more plotting options" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Hello matplotlib" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The notebook integrates nicely with Matplotlib, the primary plotting package for python. This should embed a figure of a sine wave:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\nROqlsJa/AAAAAElFTkSuQmCC\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "x = np.linspace(0, 10, 30) #array of 30 points from 0 to 10\n", "y = np.sin(x)\n", "z = y + np.random.normal(size=30) * .2\n", "plt.plot(x, y, 'o-', label='A sine wave')\n", "plt.plot(x, z, '-', label='Noisy sine')\n", "plt.legend(loc = 'lower right')\n", "plt.xlabel(\"X axis\")\n", "plt.ylabel(\"Y axis\") " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If that last cell complained about the `%matplotlib` line, you need to update IPython to v1.0, and restart the notebook. See the [installation page](https://github.com/cs109/content/wiki/Installing-Python)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Hello Numpy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The Numpy array processing library is the basis of nearly all numerical computing in Python. Here's a 30 second crash course. For more details, consult Chapter 4 of Python for Data Analysis, or the [Numpy User's Guide](http://docs.scipy.org/doc/numpy-dev/user/index.html)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Make a 3 row x 4 column array of random numbers\n", "[[ 0.40043511 0.28267003 0.68523828 0.33320828]\n", " [ 0.48903726 0.78322251 0.90891609 0.13816465]\n", " [ 0.72015645 0.70562952 0.71160807 0.5374529 ]]\n", "\n", "Add 1 to every element\n", "[[ 1.40043511 1.28267003 1.68523828 1.33320828]\n", " [ 1.48903726 1.78322251 1.90891609 1.13816465]\n", " [ 1.72015645 1.70562952 1.71160807 1.5374529 ]]\n", "\n", "Get the element at row 1, column 2\n", "1.90891609026\n", "\n", "Get the first row\n", "[ 1.40043511 1.28267003 1.68523828 1.33320828]\n", "Get every 2nd column of the first row\n", "[ 1.40043511 1.68523828]\n", "\n" ] } ], "source": [ "print(\"Make a 3 row x 4 column array of random numbers\")\n", "x = np.random.random((3, 4))\n", "print(x)\n", "print()\n", "\n", "print(\"Add 1 to every element\")\n", "x = x + 1\n", "print(x)\n", "print()\n", "\n", "print(\"Get the element at row 1, column 2\")\n", "print(x[1, 2])\n", "print()\n", "\n", "# The colon syntax is called \"slicing\" the array. \n", "print(\"Get the first row\")\n", "print(x[0, :])\n", "print\n", "\n", "print(\"Get every 2nd column of the first row\")\n", "print(x[0, ::2])\n", "print()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Print the maximum, minimum, and mean of the array. This does **not** require writing a loop. In the code cell below, type `x.m`, to find built-in operations for common array statistics like this" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('Max is ',\n", " 1.920388409413768,\n", " 'Min is ',\n", " 1.1155738760120451,\n", " 'Mean is ',\n", " 1.6064923479087432)" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "\"Max is \", x.max(), \"Min is \", x.min(), \"Mean is \", x.mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Call the `x.max` function again, but use the `axis` keyword to print the maximum of each row in x." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 1.85878336, 1.90943398, 1.92038841])" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x.max(axis=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here's a way to quickly simulate 500 coin \"fair\" coin tosses (where the probabily of getting Heads is 50%, or 0.5)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'number of heads: 244'" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = np.random.binomial(500, .5)\n", "f\"number of heads: {x}\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Repeat this simulation 500 times, and use the [plt.hist() function](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.hist) to plot a histogram of the number of Heads (1s) in each simulation" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "image/png": "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\ndGR0KAAAvOyKf+YLAMgt1a2HJ3wbu+sWpmESjBVnuAIAwBjxBQDAGPEFAMAY8QUAwBhPuAKALEvH\nE6YwuXDkCwCAMeILAIAx4gsAgDHiCwCAMeILAIAx4gsAgDHiCwCAMeILAIAxTrLhY0se+nm2RwAA\nX+LIFwAAY8QXAABjxBcAAGPEFwAAYzzhKkv4KyYAcslEvyftrluYpkn8gSNfAACMEV8AAIwRXwAA\njBFfAACMEV8AAIwRXwAAjBFfAACMEV8AAIwRXwAAjHGGq3HiDFUAkD5+O8MWR74AABgjvgAAGCO+\nAAAYI74AABibtE+44glPAJA7+J58ZTjyBQDAGPEFAMAY8QUAwBjxBQDA2KR9whUAABel4wlflmfJ\n4sgXAABj4zryvXDhgjZv3qy//OUvKigoUEtLi2bPnp3u2QAA8KRxHfn++te/1rlz53TgwAE99NBD\nam1tTfdcAAB41rji+4c//EF33nmnJOm2227T0aNH0zoUAABeNq6HnYeHh1VUVDT6cn5+vt5//30F\ng4lvLhwuHt90SRzceU/abxMAAAvjOvItKipSPB4fffnChQuXDS8AAPigccX305/+tLq7uyVJr776\nqm688ca0DgUAgJcFnHPuSq908dnOf/3rX+Wc09atW3XDDTdkYj4AADxnXPEFAADjx0k2AAAwRnwB\nADDm+acoj4yMqL6+Xv39/Tp37pxqamp0/fXXq7m5Wfn5+SooKND27dt17bXXqrOzU08//bSCwaBq\namp09913Z3v8CUm0++zZs7Vp0yY55zRnzhy1tLQoGAx6avdEe3/+85+XJB08eFAdHR06cOCAJHlq\nbynx7tddd51Wr16tOXPmSJKqqqr05S9/2VO7J9r7tttuU0NDg06fPq3z58/rBz/4gWbNmuX5vX/5\ny1/qnXfekST19/frk5/8pB555BFP7S1d/nt7U1OT8vPzNWfOHG3ZskV5eXm5ubvzuGeeeca1tLQ4\n55yLxWLurrvucitWrHCvv/66c865/fv3u61bt7p///vfbvHixe7s2bPu9OnTo/+ezBLtXlNT4373\nu98555yrra11hw4d8tzuifZ2zrm+vj63atUqd//99zvnnOf2di7x7p2dne6JJ574wNt5bfdEe9fW\n1rrnn3/eOefckSNH3EsvveSLvS86deqU+8pXvuIGBgY8t7dziXf/9re/7V5++WXnnHMbNmxwXV1d\nObu75x92XrRokdavXy9Jcs4pPz9fbW1tuvnmmyVJ58+f15QpU/SnP/1Jn/rUp1RQUKDi4mLNmjVL\nb7zxRjZHn7BEu7e3t+v222/XuXPnNDg4qKKiIs/tnmjvWCymtrY21dfXj76d1/aWEu9+9OhRvfzy\ny1qxYoXq6+s1PDzsud0T7f3KK69oYGBADz74oA4ePKiysjJf7H1Re3u7vvGNb2jGjBme21tKvPvN\nN9+sU6dOyTmneDyuYDCYs7t7Pr6FhYUqKirS8PCw1q1bp2g0qhkzZkiSXnnlFXV0dOjBBx/U8PCw\niouLP3C94eHhbI2dFol2z8/PV39/vxYvXqxYLKabbrrJc7t/eO/169fre9/7njZu3KjCwsLRt/Pa\n3lLij/knPvEJPfzww9q7d68+9rGP6Uc/+pHndk+0d39/v0KhkJ588kldd9112rVrly/2lqSTJ0/q\nyJEj+upXvyrJP5/rFx9q/tKXvqSTJ0+qvLw8Z3f3fHwl6a233tKqVat0zz33aMmSJZKkF154QU1N\nTXr88cd1zTXXXHLWrng8/oEP2GSVaPePfvSjOnTokKqqqtTa2urJ3f937zlz5ujYsWPavHmzNmzY\noL///e/asmWLJ/eWLv2YV1ZW6tZbb5UkVVZW6vXXX/fk7h/ee/r06Vq48L9/n3XhwoU6evSoL/aW\npBdffFGLFy8ePRL24t7Spbtv2bJFe/fu1Ysvvqh77703t7+/Ze8RbxuDg4Nu0aJFrqenZ/Sy5557\nzlVVVblYLDZ62cWfC7z33nvu9OnTLhKJuPfeey8bI6dNot1Xr17t3nzzTeecc88//7yrq6vz3O6J\n9r7oX//61yU/8/XK3s4l3n3p0qXutddec84599RTT7nt27d7bvdEe3/nO99xP/vZz5xzzj355JOu\ntbXVF3s759zatWvd0aNHR1/22t7OJd49Eom4EydOOOecO3TokNuwYUPO7u75k2y0tLToV7/6lUpL\nSyX992e8f/vb33T99dcrFApJkm6//XatW7dOnZ2dOnDggJxzWr16tSKRSDZHn7AP7y5J0WhUO3bs\n0FVXXaWrr75aLS0tmjFjhqd2T7T3rl27NHXqVB0/flwbNmxQZ2enJHlqbyn1x/zaa69Vc3OzioqK\nPLV7or1bW1vV0NCgM2fOqKioSDt37tRHPvIRz++9a9cufe1rX9P+/ftHv8dJ/vhcX79+vX74wx8q\nGAzqqquuUnNzs2bOnJmTu3s+vgAA5Bpf/MwXAIBcQnwBADBGfAEAMEZ8AQAwRnwBADBGfAEAMEZ8\nAQAwRnwBADD2fw2BJ6Wsdd+kAAAAAElFTkSuQmCC\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# \"list comprehension\"\n", "heads = [np.random.binomial(500, .5) for i in range(500)]\n", "\n", "# pure numpy\n", "heads = np.random.binomial(500, .5, size=500)\n", "\n", "histogram = plt.hist(heads, bins=25)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The Monty Hall Problem" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here's a fun and perhaps surprising statistical riddle, and a good way to get some practice writing python functions\n", "\n", "In a gameshow, contestants try to guess which of 3 closed doors contain a cash prize (goats are behind the other two doors). Of course, the odds of choosing the correct door are 1 in 3. As a twist, the host of the show occasionally opens a door after a contestant makes his or her choice. This door is always one of the two the contestant did not pick, and is also always one of the goat doors (note that it is always possible to do this, since there are two goat doors). At this point, the contestant has the option of keeping his or her original choice, or swtiching to the other unopened door. The question is: is there any benefit to switching doors? The answer surprises many people who haven't heard the question before.\n", "\n", "We can answer the problem by running simulations in Python. We'll do it in several parts.\n", "\n", "First, write a function called `simulate_prizedoor`. This function will simulate the location of the prize in many games -- see the detailed specification below:" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1, 1, 1, 2, 2, 1, 1, 1, 1, 0, 2, 0, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 1,\n", " 1, 1, 2, 0, 2, 1, 1, 1, 2, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0,\n", " 2, 1, 2, 2, 0, 1, 2, 0, 2, 2, 1, 0, 2, 0, 1, 2, 2, 1, 2, 0, 0, 1, 2,\n", " 0, 1, 2, 1, 1, 2, 1, 2, 1, 0, 0, 2, 0, 0, 0, 1, 1, 0, 0, 0, 1, 2, 0,\n", " 2, 0, 1, 0, 0, 2, 0, 2])" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "\"\"\"\n", "Function\n", "--------\n", "simulate_prizedoor\n", "\n", "Generate a random array of 0s, 1s, and 2s, representing\n", "hiding a prize between door 0, door 1, and door 2\n", "\n", "Parameters\n", "----------\n", "nsim : int\n", " The number of simulations to run\n", "\n", "Returns\n", "-------\n", "sims : array\n", " Random array of 0s, 1s, and 2s\n", "\n", "Example\n", "-------\n", ">>> print simulate_prizedoor(3)\n", "array([0, 0, 2])\n", "\"\"\"\n", "\n", "\n", "def simulate_prizedoor(nsim):\n", " \"\"\"returns an array of length nsim, with each entry being a random 0,1 or 2\"\"\"\n", " return np.random.randint(0, 3, nsim)\n", "\n", "simulate_prizedoor(100)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, write a function that simulates the contestant's guesses for `nsim` simulations. Call this function `simulate_guess`. The specs:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([0, 1, 0, 0, 1, 0, 1, 0, 1, 0])" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "\"\"\"\n", "Function\n", "--------\n", "simulate_guess\n", "\n", "Return any strategy for guessing which door a prize is behind. This\n", "could be a random strategy, one that always guesses 2, whatever.\n", "\n", "Parameters\n", "----------\n", "nsim : int\n", " The number of simulations to generate guesses for\n", "\n", "Returns\n", "-------\n", "guesses : array\n", " An array of guesses. Each guess is a 0, 1, or 2\n", "\n", "Example\n", "-------\n", ">>> print simulate_guess(5)\n", "array([0, 0, 0, 0, 0])\n", "\"\"\"\n", "\n", "def simulate_guess(nsim):\n", " \"\"\"returns an arrary of length nsim, with each entry a random 0,1 or 2\"\"\"\n", " return np.random.randint(0, 3, nsim)\n", " #return np.random.randint(0, 3, nsim)\n", "\n", "simulate_guess(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, write a function, `goat_door`, to simulate randomly revealing one of the goat doors that a contestant didn't pick." ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([2, 2, 0])" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "\"\"\"\n", "Function\n", "--------\n", "goat_door\n", "\n", "Simulate the opening of a \"goat door\" that doesn't contain the prize,\n", "and is different from the contestants guess\n", "\n", "Parameters\n", "----------\n", "prizedoors : array\n", " The door that the prize is behind in each simulation\n", "guesses : array\n", " THe door that the contestant guessed in each simulation\n", "\n", "Returns\n", "-------\n", "goats : array\n", " The goat door that is opened for each simulation. Each item is 0, 1, or 2, and is different\n", " from both prizedoors and guesses\n", "\n", "Examples\n", "--------\n", ">>> print goat_door(np.array([0, 1, 2]), np.array([1, 1, 1]))\n", ">>> array([2, 2, 0])\n", "\"\"\"\n", "\n", "def goat_door(prizedoors, guesses):\n", " \n", " #strategy: generate random answers, and\n", " #keep updating until they satisfy the rule\n", " #that they aren't a prizedoor or a guess\n", " result = np.random.randint(0, 3, prizedoors.size)\n", " while True:\n", " bad = (result == prizedoors) | (result == guesses)\n", " if not bad.any():\n", " return result\n", " result[bad] = np.random.randint(0, 3, bad.sum())\n", "\n", "goat_door(np.array([0, 1, 2]), np.array([1, 1, 1])) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I rewrote the function as it makes more sense to me this way:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[2, 0, 0]" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import random\n", "\n", "def goat_door(prizedoors, guesses):\n", " goats = []\n", " for prize, guess in zip(prizedoors, guesses):\n", " goat = random.randint(0,2)\n", " while goat == prize or goat == guess:\n", " goat = random.randint(0,2)\n", " goats.append(goat)\n", " \n", " return goats\n", " \n", "goat_door(np.array([0, 1, 2]), np.array([1, 1, 1]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Write a function, `switch_guess`, that represents the strategy of always switching a guess after the goat door is opened." ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 2., 1., 0.])" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "\"\"\"\n", "Function\n", "--------\n", "switch_guess\n", "\n", "The strategy that always switches a guess after the goat door is opened\n", "\n", "Parameters\n", "----------\n", "guesses : array\n", " Array of original guesses, for each simulation\n", "goatdoors : array\n", " Array of revealed goat doors for each simulation\n", "\n", "Returns\n", "-------\n", "The new door after switching. Should be different from both guesses and goatdoors\n", "\n", "Examples\n", "--------\n", ">>> print switch_guess(np.array([0, 1, 2]), np.array([1, 2, 1]))\n", ">>> array([2, 0, 0])\n", "\"\"\"\n", "\n", "def switch_guess(guesses, goatdoors):\n", " result = np.zeros(guesses.size)\n", " switch = {(0, 1): 2, (0, 2): 1, (1, 0): 2, (1, 2): 1, (2, 0): 1, (2, 1): 0}\n", " for i in [0, 1, 2]:\n", " for j in [0, 1, 2]:\n", " mask = (guesses == i) & (goatdoors == j)\n", " if not mask.any():\n", " continue\n", " result = np.where(mask, np.ones_like(result) * switch[(i, j)], result)\n", " return result\n", "\n", "switch_guess(np.array([0, 1, 2]), np.array([1, 2, 1]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A simpler version of the switch guess func:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[2, 1, 0]" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def switch_guess(guesses, goatdoors):\n", " \"\"\"takes in an array of guesses and revealed goatdoors and returns array of new door after switching\"\"\"\n", " s= []\n", " switch = {(0, 1): 2, (0, 2): 1, (1, 0): 2, (1, 2): 1, (2, 0): 1, (2, 1): 0}\n", " for guess, goat in zip(guesses, goatdoors):\n", " s.append(switch[guess, goat])\n", " return s\n", "\n", "switch_guess(np.array([0, 1, 2]), np.array([1, 2, 1]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Last function: write a `win_percentage` function that takes an array of `guesses` and `prizedoors`, and returns the percent of correct guesses" ] }, { "cell_type": "code", "execution_count": 81, "metadata": { "collapsed": true }, "outputs": [], "source": [ "\"\"\"\n", "Function\n", "--------\n", "win_percentage\n", "\n", "Calculate the percent of times that a simulation of guesses is correct\n", "\n", "Parameters\n", "-----------\n", "guesses : array\n", " Guesses for each simulation\n", "prizedoors : array\n", " Location of prize for each simulation\n", "\n", "Returns\n", "--------\n", "percentage : number between 0 and 100\n", " The win percentage\n", "\n", "Examples\n", "---------\n", ">>> print win_percentage(np.array([0, 1, 2]), np.array([0, 0, 0]))\n", "33.333\n", "\"\"\"\n", "\n", "def win_percentage(guesses, prizedoors):\n", " return 100 * (guesses == prizedoors).mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, put it together. Simulate 10000 games where contestant keeps his original guess, and 10000 games where the contestant switches his door after a goat door is revealed. Compute the percentage of time the contestant wins under either strategy. Is one strategy better than the other?" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Win percentage when keeping original door\n", "32.68\n", "Win percentage when switching doors\n", "66.8\n" ] } ], "source": [ "nsim = 10000\n", "\n", "#keep guesses\n", "print(\"Win percentage when keeping original door\")\n", "print(win_percentage(simulate_prizedoor(nsim), simulate_guess(nsim)))\n", "\n", "#switch\n", "pd = simulate_prizedoor(nsim)\n", "guess = simulate_guess(nsim)\n", "goats = goat_door(pd, guess)\n", "guess = switch_guess(guess, goats)\n", "print(\"Win percentage when switching doors\")\n", "print(win_percentage(pd, guess).mean())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Many people find this answer counter-intuitive (famously, PhD mathematicians have incorrectly claimed the result must be wrong. Clearly, none of them knew Python). \n", "\n", "One of the best ways to build intuition about why opening a Goat door affects the odds is to re-run the experiment with 100 doors and one prize. If the game show host opens 98 goat doors after you make your initial selection, would you want to keep your first pick or switch? Can you generalize your simulation code to handle the case of `n` doors?" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "## The workflow for homeworks and labs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### getting and working on labs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lets talk a bit about how labs and sections work in this course:\n", "\n", "1. Lab Notebooks are made available every Thursday evening.\n", "2. Lab Videos (which may not cover everything in the notebooks) are made available every Friday as well\n", "3. In sections starting Monday morning, and running upto the next Friday, your TA will present part of the lab to you. You ought to have looked at and perhaps tried the lab over the previous weekend, and your section might reach a consensus on what you'd like your TF to focus on: please communicate this.\n", "\n", "(Sections are 2 hours long. The first hour will be spent going over the lab, while the second if an office hour, where you can ask your TA questions about the homework, the lectures, the subject matter, and even the lab).\n", "\n", "The labs will be made available on public github repositories, with naming schemes like `cs109/2015lab1`.\n", "\n", "This is how you ought to work with them (our github tutorial has an example of this process on the `cs109/testing` repository):\n", "\n", "1. First fork the lab from the github web interface. For example, the first lab is at: https://github.com/cs109/2015lab1 . The fork button is at the upper right corner of the page. Press it.\n", "2. When it asks you where to fork the lab, choose your own github userid. The web interface will then take you to the web page for your fork. Mine is at: https://github.com/rahuldave/2015lab1 .\n", "3. Now look for the clone url at the bottom right of the page. If you set up your ssh keys, use the ssh url, else use the https url. Mine are `git@github.com:rahuldave/2015lab1.git` and `https://github.com/rahuldave/2015lab1.git` respectively. \n", "4. Clone your fork down to your machine by obtaining a terminal (`/Applications/Utilities/Terminal.app` or equivalent on mac and `git-bash.exe` on windows). Change (`cd`) into an appropriate folder and clone by doing `git clone url` where the `url` is the one in step 3.\n", "5. Add a remote for the original repository that you forked from. We'll call this remote `course`. The command for this, for example, for the first lab is: `git remote add course git@github.com:cs109/2015lab1.git` or `git remote add course https://github.com/cs109/2015lab1.git`\n", "6. Now you have a local repository. Start the ipython notebook in the repository and run the labs. DO NOT run the notebooks ending in `_original.ipynb`. These are simply copies of the labs. We made these copies so that you can update them from our `course` remote in case we make any changes.\n", "\n", "For Lab 1 I'd start with pythonpandas, followed by babypython, and finally git. The git notebook can be run under the ipython notebook. But the git commands can also be run directly on a terminal, which is probably the best place to do them...you can keep the notebook on the side to read as you follow along). So after once having read the tutorial, as described earlier, you now get to work through it.\n", "\n", "When you follow along, you can add in your own notes, and try your own variations. As you are doing this, dont forget to continue doing the \"add/commit/push\" cycle, so that you save and version your changes, and push them to your fork. This typically looks like:\n", " - git add .\n", " - git commit -a\n", " - git push\n", " \n", "In case we make changes, you can incorporate them into your repo by doing: `git fetch course; git checkout course/master -- labname_original.ipynb` where `labname.ipynb` is the lab in question. An \"add/commit/push\" cycle will make sure these changes go into your fork as well. If you intend to work on the changed file, simply copy the file to another one and work on it. Or you could make a new branch. Remember that this fork is YOUR repository, and you can do to it what you like. \n", "\n", "The diagram below should help elucidate the above and serve as a command cheat-sheet." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![homework](cs109gitflow3.png)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### getting and submitting homework" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To make `hw0.ipynb` easily accessible, we added it to the public lab repo, so that you can read it even without having a github account. (Otherwise we would have a chicken and egg problem.). This is because our homework repository is private, and we have set it up so that your repositories are private as well.\n", "\n", "Nevertheless, we want you to get acquainted with the workflow you must execute in order to obtain and submit homeworks. \n", "\n", "Let me first describe the steps by which you gain access to the homework.\n", "\n", "1. At the beginning of this document you were asked to obtain a github id and enter it in the mandatory survey. We will use this github id to construct a homework repository for you with read-write access, and give you access to our read-only homework repository. You will be added to a github organization `cs109-students`.\n", "2. Our read-only repository is `cs109-students/2015hw`. All students have read-only access to this repository. It will serve the job of the `course` remote, like above. Any changes after the homework has gone out will be made here.\n", "3. You will have your own read-write repository under the `cs109-students` organization, which will be of the form `cs109-students/userid-2015hw`. Only you and the cs109 staff have access to this repository, thus ensuring the privacy of your homework.\n", "4. When each homework is released, we will create a **branch** on your remote repository, `cs109-students/userid-2015hw`. The branches are, unimaginatively named: `hw0`, `hw1`,...,`hw5`. (For the curious, the way this works is by us creating one remote per student for a local clone of our `cs109-students/2015hw` repository, and pushing the new branch to it. We only push to a new branch each time as we dont want to be messing with a branch you have already worked on.). There is `master` branch too, which will have some instructions, but nothing very exciting. You will never work on this branch.\n", "\n", "So now, how to you obtain and submit the homework? You wont be forking here.\n", "\n", "1. You first make a clone of your repository. From the terminal, you issue the command: `git clone git@github.com:cs109-students/userid-2015hw.git` (for ssh users) or `git clone https://github.com/cs109-students/userid-2015hw.git` (for https users). Substitute your own userid for `userid`.\n", "2. Next you add a remote `course` to track the read-only \"guru\" repository. The command for this is: `git remote add course git@github.com:cs109-students/2015hw.git` or `git remote add course https://github.com/cs109-students/2015hw.git`. This well help to incorporate any changes, just like above.\n", "3. Your clone will come with a `master` branch, and perhaps a `hw0` branch. In either case you should first do `git fetch origin hw0`, which fetches from *your* remote repository on github the `hw0` branch. Then you issue `git checkout -b hw0 origin/hw0`. This command makes a new local branch `hw0` on your machine which tracks the `hw0` branch on your remote.\n", "4. You are now in the `hw0` branch. This is where you will work on homework 0. Start the ipython notebook in the repository and run the homework. The file you will use is `hw0.ipynb`. DO NOT run the notebook ending in `_original.ipynb`. These are simply copies of the homework. We made these copies so that you can update them from our `course` remote in case we make any changes. You will now engage in the \"add/commit/push\" cycle as described above. (The `push` will only push to the remote `hw0` branch.)\n", "5. We'll grade the last commit you make before the homework deadline. We will be looking for the file `hw0.ipynb`. (In actuality we wont grade homework 0 but check that you submitted it. But we will be using this mechanism to grade the homeworks from homework 1 onwards.)\n", "6. When we are ready to send out homework 1 to you, we will create a new branch on your remote repository `git@github.com:cs109-students/userid-2015hw.git` on github with the name `hw1`. You will now repeat the process from step 3 onwards: `git fetch origin hw1` followed by `git checkout -b hw1 origin/hw1`. Then you work on the `hw1` branch, and engage in the \"add/commit/push\" cycle by running `hw1.ipynb`. And so on...\n", "\n", "Once again, in case we make changes, you can incorporate them into your repo by doing: `git fetch course; git checkout course/hw0 -- hw0_original.ipynb`. An \"add/commit/push\" cycle will make sure these changes go into your fork as well. If you intend to work on the changed file `hw0_original.ipynb`, simply copy the file to `hw0.ipynb` and work on it. \n", "\n", "Remember that we will be looking for files `hw0.ipynb`, `hw1.ipynb`,...,`hw5.ipynb` as the semester goes on.\n", "\n", "This process is summarized in the diagram below." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![homework](cs109gitflow2.png)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.1" } }, "nbformat": 4, "nbformat_minor": 1 }