Guess a penguin's species from its measurements with if rules, then score the rules on 342 real penguins.
Scientists on Antarctica measured 342 penguins. Can a few lines of Python tell the three species apart from their bills and flippers?
This course uses real data: 342 penguins of three species (Adelie, Chinstrap and Gentoo) measured by scientists at Palmer Station, Antarctica. It is in your Files tab as penguins.csv. The program reads each row into a dictionary of numbers, and penguins.append(...) adds it to the end of the list. A model is anything that takes measurements and gives an answer. The simplest model is a set of if rules you write yourself; its accuracy is how often it is right.
Make your prediction first. Help opens once you've locked it in.
def guess(bill, flipper):
if flipper > 206:
return "Gentoo"
if bill > 44:
return "Chinstrap"
return "Adelie"
print(guess(39.1, 181))
print(guess(50.0, 196))
print(guess(46.1, 211))
Each return ends the function, so the rules are tried in order. Follow guess(50.0, 196) through them.
Run it: the rules are checked against every penguin. Then change 206 to 200 and run again. Better or worse?
import csv
penguins = []
with open("penguins.csv") as f:
for row in csv.DictReader(f):
penguins.append({"species": row["species"], "bill": float(row["bill_length_mm"]), "flipper": float(row["flipper_length_mm"])})
def guess(bill, flipper):
if flipper > 206:
return "Gentoo"
if bill > 44:
return "Chinstrap"
return "Adelie"
correct = 0
for p in penguins:
if guess(p["bill"], p["flipper"]) == p["species"]:
correct = correct + 1
print(str(correct) + " of " + str(len(penguins)) + " right: " + str(round(100 * correct / len(penguins))) + "%")
import csv
penguins = []
with open("penguins.csv") as f:
for row in csv.DictReader(f):
penguins.append({"species": row["species"], "bill": float(row["bill_length_mm"]), "flipper": float(row["flipper_length_mm"])})
def guess(bill, flipper):
if flipper > 206:
return "Gentoo"
if bill > 44:
return "Chinstrap"
return "Adelie"
correct = 0
for p in penguins:
if guess(p["bill"], p["flipper"]) == p["species"]:
correct = correct + 1
print(str(correct) + " of " + str(len(penguins)) + " right: " + str(round(100 * correct / len(penguins))) + "%")
Right out of all.
Where the rule's numbers came from.
Measurements that are still text.
This stops with TypeError: '>' not supported between instances of 'str' and 'int'. Click the line that is wrong.
Print every penguin the rules get wrong. Which species is guessed wrong most, and why?
Loop over the penguins again; when guess(...) != p["species"], print the real species, the guess and the measurements.
Change the numbers (206 and 44) one at a time and run again. What is the best accuracy you can get?
Print every penguin the rules get wrong: its real species, the guess and its measurements.
Run your program. This ticks when your code does all of the above.
Add bill_depth_mm to each penguin when it is read, write rules that use it (Gentoos have shallow bills), and print the accuracy. Is it better or worse than the Run step's 95%?
Add bill depth to each penguin, write rules that use it, and print their accuracy.
Run your program. This ticks when your code does all of the above.
Data: Palmer Penguins (Gorman, Williams and Fraser 2014; Palmer Station Antarctica LTER), CC0.
Students meet the Palmer Penguins data, guess species with hand-written if rules, measure accuracy on 342 penguins, look at the mistakes, tune the rules, and write rules of their own with a third measurement. About 45 minutes.
Open the teacher guide: answers, solutions, slides and a worksheet.
Read the unit primer first. This course runs in the Python playground (real Python in the browser, Pyodide); later lessons load scikit-learn, which takes several seconds the first time, so open the site's Check your school page once on a student device at school. penguins.csv is the Palmer Penguins data (CC0): 342 penguins of three species with bill length and depth, flipper length, body mass, sex, island and year (2 penguins with no measurements are left out). The loader is the same csv.DictReader pattern as Data detective, with float() (the bug task forgets it). The rules reach 95% accuracy; the mistakes are mostly Adelies with long bills guessed as Chinstrap. The second Investigate question sets up the course: a person chose 206, and machine learning finds such things from data.
Using the mistakes to improve the rules. Ask students what the wrong guesses have in common before they change a number.
Stretch: Print a table of guesses against real species (a confusion matrix) with a dictionary of dictionaries.
Support: Give students the loop that prints mistakes, and ask them only to write the if.
Next lesson builds a model that learns from the examples themselves: nearest neighbour.