<jupyter_start><jupyter_text>Machine Learning - SS18* Lecturer: Prof. Dr. <NAME>* Assistant: <NAME>, <NAME>* Tutor: **<NAME> / <EMAIL> / https://github.com/changkun**  Before Start- This tutorial will be held in **English**;- Tutorial only focus on solving assignments;- You can access lecture video online if you don't have time go there: https://videoonline.edu.lmu.de/en/semester;- You can finish the assignment in any programming language you like, but we prefer **Python**;- This course will be super crowded in the beginning of the semester, however it will be almost **empty** when approaching the end of the semester;- The assignments are **strongly relevant** with Exams;- Assignemnt solutions will **not** be uploaded except programming assignment solution;- My personal supplement material will **not** be uploaded;- There is no catch-up exam schedule yet;- Any other questions?  1st Tutorial - 04/12/18 - Python in 90minIn this tutorial, we want to give you a short introduction in Python and some insights in the basic usage of some common libraries in the scope of Data Science. Installing Python* Anaconda distribution (recommended)Visit the website https://www.continuum.io/downloads and download the Anaconda distribution for the Python 3.6 version. Make yourself familiar with the jupyter Python notebook which is included in the anaconda installation. If preferred, install also an IDE/editor of your choice, e.g. PyCharm.The Anaconda distribution comes along with a lot of libraries (numpy, scipy, pandas, ...) which otherwise have to be installed individually. IF you need an additional library which is not initially included in Anaconda, you can install the lib via "conda install PACKAGENAME". (Further information can be looked up in the documentation: https://conda.io/docs/index.html)* W/o distributionVisit https://www.python.org/downloads/ and download your preferred python version. Next, go to https://pip.pypa.io/en/stable/installing/ and install $pip$. With $pip$ being installed one can install each package individually. For Example, to install the packages $numpy, scipy, matplotlib, ipythong, jupyter, pandas$, execute the following command:pip install --user numpy scipy matplotlib ipython jupyter pandasIf you need an additional package during the course, don't forget to install the libraries which might be handy.  First steps Assigning Values to Variables. Create variables and assign **numbers, strings, floating values** to them.<jupyter_code># create a string
course = "Machine Learning"
# create a integer
semester = 2018
# create a floating number
date = 16.04

# print them out
print(course, semester, date)

'''
Block comments
'''<jupyter_output>Machine Learning 2018 16.04<jupyter_text>Variable typesPython has five standard data types −NumbersStringListTupleDictionaryLists. Create a list which contains all **numbers from 0 to 1000**<jupyter_code># use `range` to create a list
natures = list(range(0, 11))
print(natures)<jupyter_output>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]<jupyter_text>Loops and conditionals. Using the created list, print each element of the created list **if its is an odd number**, by using a loop and conditionals. Try using different type of loops.<jupyter_code>natures = list(range(0, 100))
# for loop, `end` parameter of `print`
for element in natures:
    if element % 2 == 1:
        print(element, end=' ')
# while loop
i = 0
while i < len(natures):
    if natures[i] % 2 == 1:
        print(natures[i], end=' ')
    i += 1
# list comprehension
odds = [element for element in natures if element % 2 == 1]
print(odds)<jupyter_output>[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]<jupyter_text>List Comprehensions. Now, **generate** a list which contains all numbers from **0 to $n$** which have been **squared** using list comprehensions.<jupyter_code># two way of doing x to the power of y
squared_natures = [element * element for element in natures]
print (squared_natures)

squared_natures = [element ** 2 for element in natures]
print(squared_natures)<jupyter_output>[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364, 3481, 3600, 3721, 3844, 3969, 4096, 4225, 4356, 4489, 4624, 4761, 4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241, 6400, 6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921, 8100, 8281, 8464, 8649, 8836, 9025, 9216, 9409, 9604, 9801]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364, 3481, 3600, 3721, 3844, 3969, 4096, 4225, 4356, 4489, 4624, 4761, 4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241, 6400, 6561[...]<jupyter_text>Functions.  Write a function which **takes an integer $n$**. The function first **creates a list of numbers from $0$ to $n$**. Then, squares each number of the list. Further each of the squared numbers is tested if it is odd. All odd numbers are then appended to a new list. The function returns the **list of odd (squared) numbers**.<jupyter_code># list comprehension in just one line
def odd_squares(n):
    return [x ** 2 for x in range(0, n + 1) if x % 2 == 0]
    
print(odd_squares(10))<jupyter_output>[0, 4, 16, 36, 64, 100]<jupyter_text>Assignments.  Given a list $a=['I','like','cookies']$ and another list $b=a$. Replace in the list $b$ the word $'cookies'$ with $'apples'$. Finally, print both lists ($a$ and $b$). What do you observe? What leads to the observed behavior?<jupyter_code>a = ['I', 'like', 'cookies']

# assign a to b
b = a
# change the last eleemnt from cookies to apples
b[-1] = 'apples'
print('a:', a)
print('b:', b)<jupyter_output>a: ['I', 'like', 'apples']
b: ['I', 'like', 'apples']<jupyter_text>Shallow Copy I. Given a list $a=['I','like','cookies']$ and another list which takes a shallow copy of $a$, $b=a[:]$. Like in the previous assignment, replace in the list $b$ the word $'cookies'$ with $'apples'$. Finally, print both lists ($a$ and $b$). What do you observe now?<jupyter_code>a = ['I', 'like', 'cookies']

# slice operation for copy
b = a[:]
b[-1] = 'apples'

print('a:', a)
print('b:', b)<jupyter_output>a: ['I', 'like', 'cookies']
b: ['I', 'like', 'apples']<jupyter_text>Shallow Copy II. Now, we are given a list $a = ['I', 'like', ['chocolate', 'cookies']]$. Another list $b = deepcopy(a)$ takes this time a deep copy from $a$. Change now the work $'cookies'$ with $'apples'$ in $b$. Print both lists ($a$ and $b$). What do you observe now?Hint: For deep copy. first type: from copy import deepcopy<jupyter_code>from copy import deepcopy
a = ['I', 'like', ['chocolate', 'cookies']]
b = deepcopy(a)
c = a[:]

b[-1][-1] = 'apples'
c[-1][-1] = 'apples'
print('a:', a)
print('b:', b)
print('c:', c)

print('id of a[-1]', id(a[-1]))
print('id of b[-1]', id(b[-1]))
print('id of c[-1]', id(c[-1]))<jupyter_output>a: ['I', 'like', ['chocolate', 'apples']]
b: ['I', 'like', ['chocolate', 'apples']]
c: ['I', 'like', ['chocolate', 'apples']]
id of a[-1] 140475161531976
id of b[-1] 140475162439752
id of c[-1] 140475161531976<jupyter_text>Dictionaries I. Create a dictionary with $n$ entries, where the  keys are enumerated from $0$ to $n-1$ and the values are their corresponding keys squared. Use list comprehensions. Example for expected result: $n = 7; \{0:0, 1:1, 2:4, 3:9, 4:16, 5:25, 6:36\}$<jupyter_code>natures_dict = {n: n**2 for n in range(0, 7)}
print(natures_dict)<jupyter_output>{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36}<jupyter_text>Dictionaries II. Use the dictionary from the previous assignment. Write a list comprehension to get a list of all the  keys of the  dictionary.<jupyter_code># list comprehension get key
keys = [key for key in natures_dict]
print(keys)
# keys method
keys = natures_dict.keys()
print(keys)
print(list(keys))<jupyter_output>[0, 1, 2, 3, 4, 5, 6]
dict_keys([0, 1, 2, 3, 4, 5, 6])
[0, 1, 2, 3, 4, 5, 6]<jupyter_text>Lambda functions. Write a list comprehension which **takes a number $n$** and **returns a list with even numbers**, using a lambda function.<jupyter_code>sum_op = lambda n: [x for x in range(0, n) if x % 2 == 0] 
print(sum_op(111))<jupyter_output>[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110]<jupyter_text>**map.** First, write a **function** which **takes a length in $inch$** and **returns a length in $cm$**. Given a list $l$ with lengths in $inches$: $inches=[4,4.5,5,5.5,6,7]$. Write a list comprehension which takes $l$ and returns a list with all values converted to $cm$ using $map()$.1 inch == 2.54cm<jupyter_code>def inch_to_cm(inch):
    return inch * 2.54
    
inches = [4, 4.5, 5, 5.5, 6, 7]
cms = list(map(inch_to_cm, inches))
print(cms)<jupyter_output>[10.16, 11.43, 12.7, 13.97, 15.24, 17.78]<jupyter_text>filter.  Write a list comprehension which filters the list $inches$ from the assignment above by **returning only sizes between $4$ and $6$ $inches$**.<jupyter_code>four_to_six = filter(lambda x: 4 < x / 2.54 < 6, cms)
print(list(four_to_six))<jupyter_output>[11.43, 12.7, 13.97]<jupyter_text>reduce.  Write a list comprehension which **reduces the list $inches$ by summing up all lenghts.**Hint: for using the reduce function, you need to import it first by: from functools import reduce<jupyter_code>from functools import reduce
sum = reduce(lambda x, y: x + y, inches)
print(sum)<jupyter_output>32.0<jupyter_text>List reverse. Given the following list $a=[0,1,2,3,4,5]$. Write a function which reverses the list.<jupyter_code>a=[0,1,2,3,4,5]
a.reverse()
print(a)<jupyter_output>[5, 4, 3, 2, 1, 0]<jupyter_text>Zipping of lists. Given the following two lists, wher eone list represents the $x-Coordinate$ and another one the $y-Coordinate$:* $xcoors = [0,1,2,3,4,5]$* $ycoors = [6,7,8,9,10,11]$Write a function which zips the  two lists to a list of coordinate-tuples:* $xycoors = [(0,6),(1,7),(2,8),(3,9),(4,10),(5,11)]$<jupyter_code>xcoors = [0,1,2,3,4,5,6]
ycoors = [6,7,8,9,10,11]

xycoors = [(xcoors[i], ycoors[i]) for i in range(0, min(len(xcoors), len(ycoors)))]
print(xycoors)
# xycoors = [(xcoors[i], ycoors[i]) for i in range(0, len(xcoors))]
# print(xycoors)<jupyter_output>[(0, 6), (1, 7), (2, 8), (3, 9), (4, 10), (5, 11)]<jupyter_text>Unzipping of lists. Now, we are given a list of data points where the first dimension of each data point represents the age of a person and the second dimension the amount of money spent for chocolate per month in euro:* $chocage = [(20,8), (33,18), (27,14),(66,23),(90,100)]$Write a function which takes the  list and separates it into two lists, one containing the ages and another one containing its corresponding amount of money spent for chocolate. The result would be e.g.:* $age = [20,33,27,66,90]$* $money\_spent = [8,18,14,23,100]$<jupyter_code># * operation
print(list(list(zip(*xycoors))[0]))
print(list(list(zip(*xycoors))[1]))<jupyter_output>[0, 1, 2, 3, 4, 5]
[6, 7, 8, 9, 10, 11]<jupyter_text>Object oriented programming I.  We deal now with object oriented programming in Python. For this purpose perform the following steps: * Write a $Point$ class. A $Point$ class takes and $x$ and $y$ coordinate as an argument.* Further this class shall have a setter method $setXY$ which takes and $x$ and $y$ coordinate and sets the attributes to the new provided values.* The class shall also have a getter method $getXY$ which returns the current $x$ and $y$ coordiantes of the point.* Write a method distance which takes another $point$ object and returns the euclidean distance between the provided point and the point itself. Hint: Take import math to use math.sqrt(value) in order to compute the square root.<jupyter_code>import math
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def distence(self, point):
        return math.sqrt((self.x - point.x) ** 2 + (self.y - point.y) ** 2)
    
p = Point(1, 2)
print(p.distence(Point(4,5)))<jupyter_output>4.242640687119285<jupyter_text>Object oriented programming II. In a next step, the task is to create a class $Shape$. For this purpose perform the following steps:* Create a class $Shape$ which takes a name and a color as parameters.* Define a method $area$ which just returns $0.0$.* Define a method $perimeter$ which just return $0.0$.Now, create a **class Rectangle** which inherits from $Shape$ and in which you $implement$ the $area$ and $perimeter$ methods.<jupyter_code>class Shape:
    def __init__(self, name, color):
        self.name = name
        self.color = color
        self.area = 0.0
        self.perimeter = 0.0
    
class Rectangle(Shape):
    def __init__(self, name, color, area, perimeter):
        super().__init__(name, color)
        self.area = area
        self.perimeter = perimeter
    def __str__(self):
        return f'{self.name}, {self.color}, {self.area}, {self.perimeter}\n'

r = Rectangle("rect", "red", 10, 30)
print(r)<jupyter_output>rect, red, 10, 30<jupyter_text>Numpy I - some basic functions. In this block, you will become familiar with the numpy library and some of its basic functionality. Please also consider to consult the documentation  https://docs.scipy.org/doc/numpy-dev/index.html if needed. Solve the following tasks:* Create an numpy array of floats containing the numbers from $0$ to $4$.* Create the following matrix as a numpy matrix: $M = [[1,2,3], [4,5,6]]$.* Get the shape of the matrix $M$.* Check if the value $2$ is in $M$.* Given the array $a = np.array([0,1,2,3,4,5,6,7,8,9], float)$. Reshape it to an $5\times2$ matrix.* Transpose the previously introduced matrix $M$.* Flatten matrix $M$.* Given the array $b = np.array ([0,1,2,3], float)$. Increase the dimensionality of $b$.* Create and $3\times3$ identity matrix.<jupyter_code>import numpy as np

# Create an numpy array of floats containing the numbers from $0$ to $4$
arr = np.array([0, 1, 2, 4], float)
print(arr)

# Create the following matrix as a numpy matrix: $M = [[1,2,3], [4,5,6]]$.
M = np.array([[1, 2, 3], [4, 5, 6]], float)

# print M
print(M)

# print shape of M
print(M.shape)

# element in M?
element = 7
if element in M:
    print(f"Yes, {element} is in M")
else:
    print(f"Nope, {element} is not in M")
    
# reshape an array
a = np.array([0,1,2,3,4,5,6,7,8,9], float)
print(a.shape)
b = a.reshape((5, 2))
print(b)
print(b.shape)

# Transpose
print(b.T)

# Flatten
print(b.flatten())

# increate dimensionality
print(a[:, np.newaxis])

# Create and 3x3 identity matrix.
print(np.identity(3))<jupyter_output>[0. 1. 2. 4.]
[[1. 2. 3.]
 [4. 5. 6.]]
(2, 3)
Nope, 7 is not in M
(10,)
[[0. 1.]
 [2. 3.]
 [4. 5.]
 [6. 7.]
 [8. 9.]]
(5, 2)
[[0. 2. 4. 6. 8.]
 [1. 3. 5. 7. 9.]]
[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
[[0.]
 [1.]
 [2.]
 [3.]
 [4.]
 [5.]
 [6.]
 [7.]
 [8.]
 [9.]]
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]<jupyter_text>Numpy II - linear algebra and statistics.  This assignemtn has its focus on numpy function of the linear algebra and statistics domain. Solve the following tasks using numpy:* Given the following two numpy array: $a=np.array([1,2,3], float)$, $b=([4,5,6],float)$. Compute the dot product of $a$ and $b$* Given the following matrix $M = [[1,2,3], [4,5,6], [7,8,9]]$, compute the determinant of $M$ by using the $linalg$ package of the numpy library.* Compute the eigenvalues and eigenvectors of $M$* Compute the inverse of $M$* Given the numpy array $c=np.array([1,4,3,8,3,2,3], float)$, compute the mean of $c$* using $c$, compute the median.* given the following matrix $C=[[1,1], [3,4]]$, compute the covariance of $C$.<jupyter_code>a=np.array([1,2,3], float)
b=np.array([4,5,6], float)

# matrix dot
print('dot op:', np.dot(a, b))

# compute determinant
M = np.array([[1,2,2], [4,5,6], [7,8,9]], float)
print('det of M:', np.linalg.det(M))

# compute eigen-pairs
eigen_values, eigen_vectors = np.linalg.eig(M)
print('eigen values of M:', eigen_values)
print('eigen vectors of M:', eigen_vectors)

# compute inverse of M
invM = np.linalg.inv(M)
print(invM)

# sum, mean, median of numpy array
c=np.array([1,4,3,8,3,2,3], float)
print('sum of c:', np.sum(c))
print('mean of c:', np.mean(c))
print('median of c:', np.median(c))

# covariance of C
C = np.array([[1,1], [3,4]], float)
print(np.cov(C))<jupyter_output>dot op: 32.0
det of M: 2.9999999999999996
eigen values of M: [15.71224293+0.j         -0.35612146+0.25320232j -0.35612146-0.25320232j]
eigen vectors of M: [[-0.18465082+0.j         -0.36119607+0.34050059j -0.36119607-0.34050059j]
 [-0.53185478+0.j         -0.47212544-0.27660792j -0.47212544+0.27660792j]
 [-0.82645906+0.j          0.67393054+0.j          0.67393054-0.j        ]]
[[-1.         -0.66666667  0.66666667]
 [ 2.         -1.66666667  0.66666667]
 [-1.          2.         -1.        ]]
sum of c: 24.0
mean of c: 3.4285714285714284
median of c: 3.0
[[0.  0. ]
 [0.  0.5]]<jupyter_text>Matplotlib - Plotting figures in Python.  In this assignment we are finally going to become familiar with the plotting library of Python. For this we solve the following tasks below. Please consider to consult the documentation if needed: https://matplotlib.org/contents.html.* Given a list of data points : $dpts=[(3,3),(4,5),(4.5,6),(9,7)]$. Plot the function using $plt.plot(xcoors, ycoors)$* You are given two tiny clusters $c_1 = [(1,2),(3,1),(0,1),(2,2)]$ and $c_2=[(12,9),(8,10),(11,11), (14,13)]$. Plot them in a scatter plot using $plt.scatter(xcoors, ycoors)$, where $c_1$ and $c_2$ have different colors. The $x-axis$ represents the time spent at a parking lot in hours, and the $y-axis$ represents the money spent in euro. Create axis labels for your figure.* Take the two clusters $c_1$ and $c_2$ together and compute their pairwise distances, storing them in a matrix. Plot the resulting matrix as a heatmap using $plt.imshow(my\_matrix, cmap='coolwarm')$.<jupyter_code>from matplotlib import pyplot as plt

# plot dpts
dpts=[(3,3),(4,5),(4.5,6),(9,7)]
xcoors = list(list(zip(*dpts))[0])
ycoors = list(list(zip(*dpts))[1])
plt.figure()
plt.plot(xcoors, ycoors)
plt.xlabel('xcoors')
plt.ylabel('ycoors')
plt.show()

# plot c1 and c2 in different colors
c_1 = [(1,2),(3,1),(0,1),(2,2)]
c_2=[(12,9),(8,10),(11,11), (14,13)]
xcoors = list(list(zip(*c_1))[0])
ycoors = list(list(zip(*c_1))[1])
plt.figure()
plt.scatter(xcoors, ycoors, color='red')

xcoors = list(list(zip(*c_2))[0])
ycoors = list(list(zip(*c_2))[1])
plt.scatter(xcoors, ycoors, color='green')
plt.show()

# pair-wise distence between c1 and c2
distence_matrix = []
for x1 in c_1:
    newrow = []
    for x2 in c_2:
        newrow.append(math.sqrt((x1[0] - x2[0])**2 + (x1[1] - x2[1])**2))
    distence_matrix.append(newrow)

    
random_mat = np.random.rand(1000, 1000)
plt.figure()
plt.imshow(random_mat, cmap='coolwarm', interpolation='nearest')
plt.colorbar()
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15549376995160127, 'fraction_numerical': 0.09437751004016064, 'mean_word_length': 4.462035995500562, 'pattern_counts': {'":': 0, '<': 76, '<?xml version=': 0, '>': 73, 'https://': 8, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 5, 'word_list_counts': {'cursed_substrings.json': 40, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '22', 'dir': 'jupyter-structured-clean-dedup', 'id': '408038', 'license': 'MIT', 'n_tokens_mistral': 8398, 'n_tokens_neox': 7025, 'n_words': 2579, 'path': 'week01/py_intro_solution_by_ou.ipynb', 'repo_name': 'changkun/ss18-machine-learning-tutorial', 'size': '19454'}