Machine Learning Primer




Claudius Gros, WS 2024/25

Institut für theoretische Physik
Goethe-University Frankfurt a.M.

Python - First Steps

code vs. script

print("Running a Python code.")
#!/usr/bin/env python3
print("Executing a Python script.\n\"second line\"")

variables as objects

Copy Copy to clipboad
Downlaod Download
#!/usr/bin/env python3
# id: returns object identification

print("***********")
print("id checking")
print("***********")
x0 = 0                # an integer object is created
x1 = 1                # idem
print(id(x0), x0)
print(id(x1), x1, id(x1)-id(x0), "(difference in bits)\n")

print("*************")
print("type checking")
print("*************")
print("x0, type ::   ", x0, type(x0))
x0 = 'a'              # changing type from integer to string
print("x0, type ::   ", x0, type(x0))

print()   
print("****************")
print("strings as lists")
print("****************")
x0 = "I am a string"  # strings are ordered lists
x1 = " |  "  + x0[2] + x0[3]
print(x0, x1)

indenting

Copy Copy to clipboad
Downlaod Download
#!/usr/bin/env python3
from math import sqrt

print("Finding Triples  a^2 + b^2 == c^2") # ouput - not formatted
n = input("Maximum Number? ")              # input prompt
n = int(n)+1                               # casting to int
for a in range(1,n):                       # loop
  for b in range(a,n):
    ab_square = a**2 + b**2
    c = int(sqrt(ab_square))
    if (ab_square==c**2):                  # a^2 + b^2 == c^2
      print(f'{a:3d} {b:3d} | {c:3d}')     # formatted output

sequential data types

Copy Copy to clipboad
Downlaod Download
#!/usr/bin/env python3

text = "elements of string"
print()
print(text, "  |  ", text[9]+text[10])

print()
print("*********************")
print("iterating over values")
print("*********************")
ABC = ["A", "B", "C"]              # a list
print(ABC)
for strList in ABC:                # iterating over values
  print(strList + "_" + strList)

print()
print("**********************")
print("iterating over indices")
print("**********************")
for iList in range(n:=len(ABC)):   # walrus assignment (of n)
  ABC[iList] = 'new_' + ABC[iList]
print(ABC)
print("length of ABC : ", n)

print()
print("**********************************")
print("iterating over (index,value) pairs")
print("**********************************")
for index, value in enumerate(ABC):  
    print("(", index, "|", value, ")")

print()
print("*************************")
print("using list comprehensions")
print("*************************")
[print(strList) for strList in ABC]
print()

intList = [i for i in range(10)]
print(intList)

oddList = [value*value for value in intList if value%2==1]
print(oddList)

print()
print("********************")
print("tupeles come with ()")
print("********************")
# tuples are constant collections, viz unchangeable.
fruitTuple = ("apple", "banana", "cherry")
print(fruitTuple)

# would be an erorr
# fruitTuple[0] = "changing something constant"

sets / dictionaries

Copy Copy to clipboad
Downlaod Download
#!/usr/bin/env python3

# second apple not stored (automatic duplicate elimination)
fruitSet = {"apple", "banana", "cherry", "apple"}

print("*********************************")
print("no ordering guranteed for sets {}")
print("*********************************")
print(fruitSet)
for fruit in fruitSet:
  if 'y' in fruit:
    fruit += " (which I like)"
  print(fruit)
print(fruitSet)

print()
print("**********************************")
print("dictionaries are associative lists")
print("**********************************")
anticCarDict = {
  "brand": "Ford",
  "model": "Mustang",
  "year": 1964,
  "colors": ["red", "white", "blue"]
               }
for key in anticCarDict:
  print(f'{key:7s} ::', anticCarDict[key])

list operations

append()   add element at the end
clear() remove all elements
copy() returns a copy
count() returns the number of elements with specified value
extend() add elements to the end
index() search for given value, returning the index of the first occurance
insert() adding element at specified position
pop() removes element at given inde
remove() removing item with specified value
reverse() reverses the order
sort() sorting
Copy Copy to clipboad
Downlaod Download
#!/usr/bin/env python3

# [-1] : last entry
myList = [i for i in range(10,17)]
print(myList)
print(len(myList), " | ", myList[-1])

myList.append("not any more a list of interges")
print(myList)

myList.insert(1, "first")
print(myList)
print()

aList = [i for i in range(5)]
bList = [i for i in range(5,8)]
# myList = aList would make them the idential object
myList = aList.copy()            # copy entire list
print("aList  :: ", aList)
print("bList  :: ", bList)
print("myList :: ", myList)
print()

myList.extend(bList)             # extend list
print("aList  :: ", aList)
print("bList  :: ", bList)
print("myList :: ", myList)
myList.sort(reverse = True)      # sorting
print("myList :: ", myList)
print()

functions

function basics

call by value

Copy Copy to clipboad
Downlaod Download
#!/usr/bin/env python3

# pass can be used also in for-loops
def nothingToDo():
  pass

# default argument, call by value
def flower(name='Iris'):
  print("my favorite flower is the ", name)
  name = "Orchid"

# list of arguments of arbitrary length
def allArgs(*args):
  for i in range(n:=len(args)):
    print(i, args[i])
  return n

# when using keys, the oder of calling does not matter
def keyFlowers(f3, f2, f1):
  print(f1, f2, f3)

print("*************")
print("call by value")
print("*************")
nothingToDo()
flower()
flower()
flower("Rose")

print()
myFlower = "Lily"
flower(myFlower)
print(myFlower)

print()
print("****************************")
print("arbirary number of arguments")
print("****************************")
print("argsLength: ", allArgs("Daffodil", "Dahlia", "Daisy"))

print()
print("*******************")
print("arguments with keys")
print("*******************")
# order does not matter with keys
keyFlowers(f2="Lavender", f1="Aster", f3="Poppy")

call by reference

Copy Copy to clipboad
Downlaod Download
#!/usr/bin/env python3

import copy             # deep and schallow copy of objects

def myFunc(inList):
 inList.append(3)
 inList.extend([7,1])
 print("id/list in myFunc     :", id(inList), inList)
 inList.remove(7)
 print("id/list in myFunc     :", id(inList), inList)
 return

def newFunc(inList):
 inList.append(3)
 inList.extend([7,1])
 print("id/list in newFunc    :", id(inList), inList)
 inList = [3, 4, 6]                   # a new id is asigned
 print("id/list in newFunc    :", id(inList), inList)
 return

def valueFunc(inList):                # simulates call by value
 localList = copy.deepcopy(inList)    # deep == recursively
 localList.extend([77,11])
 print("id/list in valueFunc  :", id(localList), localList)
 return


print("******************************")
print("id not changed within function")
print("******************************")
myList = [1, 2]
print("id/list before calling:", id(myList), myList)
myFunc(myList)
print("id/list after calling :", id(myList), myList)

print("**************************")
print("id changed within function")
print("**************************")
myList = [1]                        # a new id is asigned
print("id/list before calling:", id(myList), myList)
newFunc(myList)
print("id/list after  calling:", id(myList), myList)

print("***********************")
print("simulated call by value")
print("***********************")
myList = [11]                        # a new id is asigned
print("id/list before calling:", id(myList), myList)
valueFunc(myList)
print("id/list after  calling:", id(myList), myList)

default updating

Copy Copy to clipboad
Downlaod Download
#!/usr/bin/env python3

# list argument with empty default
# the default is however updated at every call
def spammer(bag = []):
    bag.append("spam")
    return bag

# default is None, viz list does not exists
# None is an immutable object, the empty list [] not
def noProblem(bag = None):
    if bag is None:         # check if list exists
      bag = []
    bag.append("no spam")
    return bag

print("****************")
print("using \"bag = []\"")
print("****************")
print(spammer())
print(spammer())
print(spammer())
myBag = spammer()
myBag.clear()
print(myBag)
myBag = ["no"]
print(myBag)
spammer(myBag)
print(myBag)
spammer(myBag)
print(myBag)

print()
print("******************")
print("using \"bag = None\"")
print("******************")
print(noProblem())
print(noProblem())
print(noProblem())

scopes

Copy Copy to clipboad
Downlaod Download
#!/usr/bin/env python3

globalInt = 111

# the first string in a function body is the docstring
def hello():
    "function hello(): "    # the docstring
    globalInt = 22          # a local variable

    global helloInt         # becomes global
    helloInt = 33    
    return hello.__doc__

print()
print("*************")
print("scope testing")
print("*************")
a = 0
for i in range(4):
  b = i
  a += i
  print("   in loop: ", a, b)

print()
print("after loop: ", a, b)       
print()
print(" globalInt: ", globalInt )  

# helloInt only created if hello called at least once
# print("  helloInt: ",  helloInt )   

print()
print("*********")
print("docstring")
print("*********")
print(hello.__doc__ + "The docstring of the function hello ")
print(hello())

recursion

Copy Copy to clipboad
Downlaod Download
#!/usr/bin/env python3

def sum_recursion(n, k=0, result=0):
  "\sum_{k=0}^n k"
  if (k <= n):
    result = k + sum_recursion(n, k+1, result)
#   print(n, k, result)             # for testing
  return result

def fibonacci(n, k=1, kk=0):
  "sum of previous two numbers"
  print(n, k, kk)                   # for testing
  if (n > 0):
    n, k, kk = fibonacci(n-1, k+kk, k) 
  return n, k, kk                   # return 3 variables
   

print("*********")
print("recursion")
print("*********")
N = 4
print(f"evaluate \"\sum_{{k=0}}^{N:d} k\" via recursion:", sum_recursion(N))

print()
print("*******************")
print("compact asignements")
print("*******************")

_, resFib, _ = fibonacci(nFib:=8)      # with placehoders '_' (and Walrus)
print(f'\nthe {nFib:d}-the Fibonacci number is: ', resFib)