I am working on the file "04.String_me_along.ipynb".
The first task is:
Indexing Strings
This is a very important topic!

Indexing and slicing form the basis of a lot of data manipulation techniques, so make sure you spend a lot of time practicing this.
Example 1: Indexing always begins at 0. Do you see why the answer here is "k"?

Example 2: Indexing can have a lower bound, and an upper bound. The lower bound is always inclusive, and the upper bound is always exclusive.

Example 3: Similarly, -1 would imply the very last character. -2 would imply the 2nd last character, and so on.

Example 4: Again, the upper bound is exclusive. Always!

 Example 5: You can skip strings too. The format? [Lower Bound : Upper Bound : Character-to-Skip]

 Example 6 : You can also index all character.

 Example 7 : Index all character, and then skip every 2 (or 3 or 4 as you wish).

 Example 8 : Reversing strings

Can you write Python code for it?

show = 'Monty Python'

show[0]

show[-1]

show[0:4]

show[0:5]

show[-7:]

show[-3:]

show[1:]


I am working on the file "04.String_me_along.ipynb".
The first task is:
More Splits
Can you write Python code for it?

ice_cream = "chocolate vanilla banana caramel"
ice_cream = ice_cream.split(" ")
print(ice_cream)

ice_cream[0]

ice_cream[-1]

ice_cream[1]

len(ice_cream)


I am working on the file "04.String_me_along.ipynb".
The first task is:
Now remember how we converted an int to a float, and vice versa?
Can you write Python code for it?

children = 5

type(children)

new_children = float(children)
type(new_children)


I am working on the file "04.String_me_along.ipynb".
The first task is:
String Operations

+ : concatenate two (or more) strings
len(string): find the number of characters ina string
string.upper(): returns an uppercase version of a string
string.lower(): returns a lowercase version of a string
haystack.find(needle): searches haystack for needle, prints the position of the first occurrence, indexed from 0. Returns -1 if not found
string_1.count(string_2): counts the number of occurrences of one string in another.
haystack.startswith(needle): does a the haystack string start with the needle string?
haystack.endswith(needle): does a the haystack string end with the needle string?
string_1.split(string_2): split the first string at every occurrence of the second string. Outputs a list (see below).
==: are the two operand strings the same?
string.strip(): remove any whitespace from the left or right of the string, including newlines.

Read more about string operations here: https://docs.python.org/3/library/string.html
Can you write Python code for it?

sherlocked = "To Sherlock Holmes she is always the woman."
print(sherlocked)

print(len(sherlocked))

print(sherlocked.upper())

print(sherlocked.lower())

sherlocked.find("she")


I am working on the file "04.String_me_along.ipynb".
The first task is:
String Substitution
Can you write Python code for it?

age = 42
print("I am {} years old.".format(age))

print("I am {} years old".format(age))
print("Hello World!")


I am working on the file "04.String_me_along.ipynb".
The first task is:
Switching between Single, Double and Triple Quotes
Text = The name's Bond, James Bond.
Can you write Python code for it?

text01 = "The name's Bond, James Bond."

print(text01)

text02 = """The name's Bond, James Bond."""
text03 = """Text here"""
text04 = """Here we go!"""

print(text02)
print(text03)
print(text04)

text05 = 'The name's Bond, James Bond.'
print(text05)


I am working on the file "04.String_me_along.ipynb".
The first task is:
You can convert them to strings too!
Can you write Python code for it?

stringy_kids = str(children)
type(stringy_kids)


I am working on the file "04/形態素解析.ipynb".
The first task is:
31. 動詞
動詞の表層形をすべて抽出せよ．
Can you write Python code for it?

import pickle
def extract_verb_surface(morph):
    verb_list = []
    for i in morph:
        for j in i:
            if j['pos']=='動詞' :
                verb_list.append(j['surface'])
    return verb_list
with open('morph_neko.pickle', 'rb') as f:
    neko_sample = pickle.load(f, encoding='utf-8', fix_imports=False)
verbs = extract_verb(neko_sample)


I am working on the file "04/形態素解析.ipynb".
The first task is:
32. 動詞の原形
動詞の原形をすべて抽出せよ
Can you write Python code for it?

import pickle
def extract_verb_base(morph):
    base_form_lists = [j['base']  for i in morph for j in i if j['pos'] == '動詞']
    return base_form_lists
with open('morph_neko.pickle', 'rb') as f:
    neko_sample = pickle.load(f, encoding='utf-8', fix_imports=False)
base_forms = extract_verb_base(neko_sample)


I am working on the file "04/形態素解析.ipynb".
The first task is:
33. サ変名詞
サ変接続の名詞をすべて抽出せよ
Can you write Python code for it?

with open('morph_neko.pickle', 'rb') as f:
    neko_sample = pickle.load(f, encoding='utf-8', fix_imports=False)
noun_shen = [j['base']  for i in neko_sample for j in i if j['pos1'] in ('サ変接続') and j['base'] not in ['*\n']]


I am working on the file "04/形態素解析.ipynb".
The first task is:
34. 「AのB」
2つの名詞が「の」で連結されている名詞句を抽出せよ．
Can you write Python code for it?

import pickle
with open('morph_neko.pickle', 'rb') as f:
    neko_samples = pickle.load(f)

noun_phrase = [i[j-1]['surface'] + i[j]['base'] + i[j+1]['surface'] \
               for i in neko_samples for j in range(len(i)) \
               if i[j]['base'] in ('の') and i[j+1]['pos'] in ('名詞') and i[j-1]['pos'] in ('名詞')]
noun_phrase


I am working on the file "04/形態素解析.ipynb".
The first task is:
36. 単語の出現頻度
文章中に出現する単語とその出現頻度を求め，出現頻度の高い順に並べよ．
Can you write Python code for it?

import pickle
from operator import itemgetter
from collections import defaultdict
with open('morph_neko.pickle', 'rb') as f:
    neko_samples = pickle.load(f, encoding='utf-8', fix_imports=False)

words = [word['base'] for sentence in neko_samples for word in sentence ]
word_count = defaultdict(int)
for i in words:
    if i not in (['。', '、']) :
        word_count[i] += 1
word_count = sorted(word_count.items(), key=itemgetter(1), reverse=True)

with open('count_list.pickle', 'wb') as f:
    pickle.dump(word_count, f)


I am working on the file "04/形態素解析.ipynb".
The first task is:
38. ヒストグラム
単語の出現頻度のヒストグラム（横軸に出現頻度，縦軸に出現頻度をとる単語の種類数を棒グラフで表したもの）を描け．
Can you write Python code for it?

%matplotlib inline
import prettyplotlib as ppl
import matplotlib.pyplot as plt
import pickle
from collections import defaultdict, Counter
with open('count_list.pickle', 'rb') as f:
    count_list = pickle.load(f)

counts = [i[1] for i in count_list]
counts = (Counter(counts))
kind = [i[0]for i in counts.most_common()]
frequency = [i[1] for i in counts.most_common()]
plt.figure(figsize=(12, 9))
plt.hist(frequency, color='c', bins=239)
print()

%matplotlib inline
import prettyplotlib as ppl
import matplotlib.pyplot as plt
import pickle
from collections import defaultdict, Counter

count_list = [i[1] for i in word_count]
ranking = range(1, len(count_list)+1)
plt.xscale('log')
plt.yscale('log')
ppl.plot(ranking, count_list)


I am working on the file "0420_PytorchIntro_1555587538086.ipynb".
The first task is:
$\frac{\partial{s}}{\partial{x}} = \frac{\partial{s}}{\partial{r}} \cdot \frac{\partial{r}}{\partial{x}}$
For the above code $a$ represents $\frac{\partial{s}}{\partial{r}}$ and then $x.grad$ gives directly $\frac{\partial{s}}{\partial{x}}$
Autodiff example that looks like what we have been doing
Can you write Python code for it?

x = torch.randn([20, 1], requires_grad=True)
y = 3*x - 2

w = torch.tensor([1.], requires_grad=True)
b = torch.tensor([1.], requires_grad=True)

y_hat = w*x + b

loss = torch.sum((y_hat - y)**2)

print(loss)

loss.backward()

print(w.grad, b.grad)


I am working on the file "0420_PytorchIntro_1555587538086.ipynb".
The first task is:
$t = \sum_i z_i, z_i = y_i^2 + 1, y_i = x_i + 5$
$\frac{\partial t}{\partial x_i} = \frac{\partial z_i}{\partial x_i} = \frac{\partial z_i}{\partial y_i} \frac{\partial y_i}{\partial x_i} = 2y_i \times 1$
At x = 1, y = 6, $\frac{\partial t}{\partial x_i} = 12$
Can you write Python code for it?

x = torch.ones([3, 2], requires_grad=True)
y = x + 5
r = 1/(1 + torch.exp(-y))
print(r)
s = torch.sum(r)
s.backward()
print(x.grad)

x = torch.ones([3, 2], requires_grad=True)
y = x + 5
r = 1/(1 + torch.exp(-y))
a = torch.ones([3, 2])
r.backward(a)
print(x.grad)


I am working on the file "0420_PytorchIntro_1555587538086.ipynb".
The first task is:
CUDA support
Can you write Python code for it?

print(torch.cuda.device_count())

print(torch.cuda.device(0))
print(torch.cuda.get_device_name(0))

cuda0 = torch.device('cuda:0')

a = torch.ones(3, 2, device=cuda0)
b = torch.ones(3, 2, device=cuda0)
c = a + b
print(c)

print(a)

%%time
for i in range(10):
  a = np.random.randn(10000,10000)
  b = np.random.randn(10000,10000)
  np.add(b, a)

%%time
for i in range(10):
  a_cpu = torch.randn([10000, 10000])
  b_cpu = torch.randn([10000, 10000])
  b_cpu.add_(a_cpu)

%%time
for i in range(10):
  a = torch.randn([10000, 10000], device=cuda0)
  b = torch.randn([10000, 10000], device=cuda0)
  b.add_(a)

%%time
for i in range(10):
  a = np.random.randn(10000,10000)
  b = np.random.randn(10000,10000)
  np.matmul(b, a)

%%time
for i in range(10):
  a_cpu = torch.randn([10000, 10000])
  b_cpu = torch.randn([10000, 10000])
  torch.matmul(a_cpu, b_cpu)

%%time
for i in range(10):
  a = torch.randn([10000, 10000], device=cuda0)
  b = torch.randn([10000, 10000], device=cuda0)
  torch.matmul(a, b)


I am working on the file "0420_PytorchIntro_1555587538086.ipynb".
The first task is:
Do it in a loop
Can you write Python code for it?

learning_rate = 0.01

w = torch.tensor([1.], requires_grad=True)
b = torch.tensor([1.], requires_grad=True)

print(w.item(), b.item())

for i in range(10):

  x = torch.randn([20, 1])
  y = 3*x - 2

  y_hat = w*x + b
  loss = torch.sum((y_hat - y)**2)

  loss.backward()

  with torch.no_grad():
    w -= learning_rate * w.grad
    b -= learning_rate * b.grad

    w.grad.zero_()
    b.grad.zero_()

  print(w.item(), b.item())


I am working on the file "0420_PytorchIntro_1555587538086.ipynb".
The first task is:
Initialise tensors
Can you write Python code for it?

x = torch.ones(3, 2)
print(x)
x = torch.zeros(3, 2)
print(x)
x = torch.rand(3, 2)
print(x)

x = torch.empty(3, 2)
print(x)
y = torch.zeros_like(x)
print(y)

x = torch.linspace(0, 1, steps=5)
print(x)

x = torch.tensor([[1, 2],
                 [3, 4],
                 [5, 6]])
print(x)


I am working on the file "0420_PytorchIntro_1555587538086.ipynb".
The first task is:
Numpy <> PyTorch
Can you write Python code for it?

x_np = x.numpy()
print(type(x), type(x_np))
print(x_np)

a = np.random.randn(5)
print(a)
a_pt = torch.from_numpy(a)
print(type(a), type(a_pt))
print(a_pt)

np.add(a, 1, out=a)
print(a)
print(a_pt)

%%time
for i in range(100):
  a = np.random.randn(100,100)
  b = np.random.randn(100,100)
  c = np.matmul(a, b)

%%time
for i in range(100):
  a = torch.randn([100, 100])
  b = torch.randn([100, 100])
  c = torch.matmul(a, b)

%%time
for i in range(10):
  a = np.random.randn(10000,10000)
  b = np.random.randn(10000,10000)
  c = a + b

%%time
for i in range(10):
  a = torch.randn([10000, 10000])
  b = torch.randn([10000, 10000])
  c = a + b


I am working on the file "0420_PytorchIntro_1555587538086.ipynb".
The first task is:
Reshaping tensors
Can you write Python code for it?

print(x)
y = x.view(2, 3)
print(y)

y = x.view(6,-1)
print(y)


I am working on the file "0420_PytorchIntro_1555587538086.ipynb".
The first task is:
Simple Tensor Operations
Can you write Python code for it?

x = torch.ones([3, 2])
y = torch.ones([3, 2])
z = x + y
print(z)
z = x - y
print(z)
z = x * y
print(z)

z = y.add(x)
print(z)
print(y)

z = y.add_(x)
print(z)
print(y)


I am working on the file "0420_PytorchIntro_1555587538086.ipynb".
The first task is:
Slicing tensors
Can you write Python code for it?

print(x.size())
print(x[:, 1])
print(x[0, :])

y = x[1, 1]
print(y)
print(y.item())


I am working on the file "04A_MLP_Optimizer_Sandbox_Assignment.ipynb".
The first task is:
Optimizers
Instead of the optimizer being given though, let's try out a few. Here we have optimizers implementing algorithms for Stochastic Gradient Descent (SGD), Stochastic Gradient Descent with Momentum (momentum), and Adaptive Moments (ADAM). Try out different parameter settings (e.g. learning rate) for each of them.
Can you write Python code for it?

# Optimizers: Try out a few different parameters for SGD and SGD momentum
train_step_SGD = tf.train.GradientDescentOptimizer(learning_rate=**PICK_ONE**).minimize(cross_entropy)
train_step_momentum = tf.train.MomentumOptimizer(learning_rate=**PICK_ONE**, momentum=**mass_x_velocity**).minimize(cross_entropy)
train_step_ADAM = tf.train.AdamOptimizer().minimize(cross_entropy)

# Op for initializing all variables
initialize_all = tf.global_variables_initializer()


I am working on the file "04A_MLP_Optimizer_Sandbox_Assignment.ipynb".
The first task is:
Training
Because we'll be repeating training a few times, let's move our training regimen into function. Note that we pass which optimization algorithm we're running as an argument. In addition to printing out the validation accuracy and final test accuracy, we'll also return the lists of accuracies at each validation step and the training losses at each iteration.
Can you write Python code for it?

def train_MLP(train_step_optimizer, iterations=4000):
    with tf.Session() as sess:
        # Initialize (or reset) all variables
        sess.run(initialize_all)

        # Initialize arrays to track losses and validation accuracies
        valid_accs = []
        losses = []

        for i in range(iterations):
            # Validate every 250th batch
            if i % 250 == 0:
                validation_accuracy = 0
                for v in range(10):
                    batch = mnist.validation.next_batch(50)
                    validation_accuracy += (1/10) * accuracy.eval(feed_dict={x: batch[0], y_: batch[1]})
                print('step %d, validation accuracy %g' % (i, validation_accuracy))
                valid_accs.append(validation_accuracy)

            # Train
            batch = mnist.train.next_batch(50)
            loss, _ = sess.run([cross_entropy, train_step_optimizer], feed_dict={x: batch[0], y_: batch[1]})
            losses.append(loss)

        print('test accuracy %g' % accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

    return valid_accs, losses


I am working on the file "04_BFS.ipynb".
The first task is:
BFS in Matrix

Number of Islands

Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
Example 1:
11110
11010
11000
00000
Answer: 1
Example 2:
11000
11000
00100
00011
Answer: 3
https://leetcode.com/problems/number-of-islands/#/description
http://www.lintcode.com/en/problem/number-of-islands/
Can you write Python code for it?

class Solution(object):
    def numIslands(self, grid):
        """
        :type grid: List[List[str]]
        :rtype: int
        """
        if grid is None or len(grid) == 0 or len(grid[0]) == 0:
            return 0

        m, n = len(grid), len(grid[0])
        visited = [[False for i in range(n)] for j in range(m)]
        count = 0

        def bfs(grid, m, n, x, y):
            dx = [0, 0, 1, -1]
            dy = [1, -1, 0, 0]

            queue = [[x, y]]
            visited[x][y] = True
            while queue:
                x, y = queue.pop(0)
                for i in range(4):
                    xx, yy = x + dx[i], y + dy[i]
                    if 0 <= xx < m and 0 <= yy < n:
                        if not visited[xx][yy] and grid[xx][yy] == '1':
                            queue.append([xx, yy])
                        visited[xx][yy] = True

        for x in range(m):
            for y in range(n):
                if not visited[x][y] and grid[x][y] == '1':
                    count += 1
                    bfs(grid, m, n, x, y)

        return count

class Solution:
    # @param {boolean[][]} grid a boolean 2D matrix
    # @return {int} an integer
    def numIslands(self, grid):
        # Write your code here
        if grid is None or len(grid) == 0 or len(grid[0]) == 0:
            return 0

        m, n = len(grid), len(grid[0])
        visited = [[False for y in range(n)] for x in range(m)]
        dx = [0, 0, 1, -1]
        dy = [1, -1, 0, 0]
        count = 0

        def bfs(x, y):
            queue = [[x, y]]
            while queue:
                x, y = queue.pop(0)
                visited[x][y] = True
                for i in range(4):
                    xx, yy = x + dx[i], y + dy[i]
                    if 0 <= xx < m and 0 <= yy < n:
                        if not visited[xx][yy] and grid[xx][yy] == 1:
                            queue.append([xx, yy])
                        visited[xx][yy] = True
    ...


I am working on the file "04_BFS.ipynb".
The first task is:
Clone Graph

http://www.lintcode.com/en/problem/clone-graph/
https://leetcode.com/problems/clone-graph/#/description
Can you write Python code for it?

# Definition for a undirected graph node
# class UndirectedGraphNode:
#     def __init__(self, x):
#         self.label = x
#         self.neighbors = []
class Solution:
    # @param node, a undirected graph node
    # @return a undirected graph node
    def __init__(self):
        self.dict = {}

    def cloneGraph(self, node):
        # write your code here
        if node is None:
            return

        nodeCopy = UndirectedGraphNode(node.label)
        self.dict[node] = nodeCopy

        queue = [node]
        while queue:
            node = queue.pop(0)
            for n in node.neighbors:
                if n not in self.dict:
                    nc = UndirectedGraphNode(n.label)
                    self.dict[n] = nc
                    self.dict[node].neighbors.append(nc)
                    queue.append(n)
                else:
                    self.dict[node].neighbors.append(self.dict[n])

        return nodeCopy


I am working on the file "04_BFS.ipynb".
The first task is:
Knight Shortest Path

http://www.lintcode.com/en/problem/knight-shortest-path/
Can you write Python code for it?

# Definition for a point.
# class Point:
#     def __init__(self, a=0, b=0):
#         self.x = a
#         self.y = b

class Solution:
    # @param {boolean[][]} grid a chessboard included 0 (False) and 1 (True)
    # @param {Point} source a point
    # @param {Point} destination a point
    # @return {int} the shortest path
    def shortestPath(self, grid, source, destination):
        # Write your code here
        if grid is None or len(grid) == 0 or len(grid[0]) == 0:
            return -1

        m, n = len(grid), len(grid[0])
        d = [(1,2), (1,-2), (-1,2), (-1,-2), (2,1), (2,-1), (-2,1), (-2,-1)]

        path, step = [[source.x, source.y]], -1

        while path:
            step += 1
            new_path = []
            for x, y in path:
                if [x, y] == [destination.x, destination.y]:
                    return step
                for dx, dy in d:
                    xx, yy = x + dx, y + dy
                    if 0 <= xx < m and 0 <= yy < n and grid[xx][yy] != 1:
                        new_path.append([xx, yy])
                        grid[xx][yy] = 1
            path = new_path

        return -1


I am working on the file "04_BFS.ipynb".
The first task is:
Search Graph Nodes

Given a undirected graph, a node and a target, return the nearest node to given node which value of it is target, return NULL if you can't find.
There is a mapping store the nodes' values in the given parameters.
Notice
It's guaranteed there is only one available solution
http://www.lintcode.com/en/problem/search-graph-nodes/
Can you write Python code for it?

# Definition for a undirected graph node
# class UndirectedGraphNode:
#     def __init__(self, x):
#         self.label = x
#         self.neighbors = []

class Solution:
    # @param {UndirectedGraphNode[]} graph a list of undirected graph node
    # @param {dict} values a dict, <UndirectedGraphNode, (int)value>
    # @param {UndirectedGraphNode} node an Undirected graph node
    # @param {int} target an integer
    # @return {UndirectedGraphNode} a node
    def searchNode(self, graph, values, node, target):
        # Write your code here
        if not node:
            return None

        if values[node] == target:
            return node

        queue = [node]
        visited = set([node])
        while queue:
            node = queue.pop(0)
            for n in node.neighbors:
                if values[n] == target:
                    return n
                if n not in visited:
                    visited.add(n)
                    queue.append(n)

        return None


I am working on the file "04_BFS.ipynb".
The first task is:
Topological Sorting

Given an directed graph, a topological order of the graph nodes is defined as follow:
For each directed edge A -> B in graph, A must before B in the order list.
The first node in the order can be any node in the graph with no nodes direct to it.
Find any topological order for the given graph.
http://www.lintcode.com/en/problem/topological-sorting/
Can you write Python code for it?

# Definition for a Directed graph node
# class DirectedGraphNode:
#     def __init__(self, x):
#         self.label = x
#         self.neighbors = []

class Solution:
    """
    @param graph: A list of Directed graph node
    @return: A list of graph nodes in topological order.
    """
    def topSort(self, graph):
        # write your code here
        dic = {}
        for node in graph:
            dic[node] = 0

        for node in graph:
            for n in node.neighbors:
                dic[n] += 1

        order = []
        for node in graph:
            if dic[node] == 0:
                order.append(node)

        queue = order[:]   ## right way to copy a list!!!
        while queue:
            node = queue.pop(0)
            for n in node.neighbors:
                dic[n] -= 1
                if dic[n] == 0:
                    order.append(n)
                    queue.append(n)

        return order if len(order) == len(dic) else None


I am working on the file "04_BFS.ipynb".
The first task is:
Zombie in Matrix

Given a 2D grid, each cell is either a wall 2, a zombie 1 or people 0 (the number zero, one, two).Zombies can turn the nearest people(up/down/left/right) into zombies every day, but can not through wall. How long will it take to turn all people into zombies? Return -1 if can not turn all people into zombies.
Example
Given a matrix:
0 1 2 0 0
1 0 0 2 1
0 1 0 0 0
return 2
http://www.lintcode.com/en/problem/zombie-in-matrix/
Can you write Python code for it?

class Solution:
    # @param {int[][]} grid  a 2D integer grid
    # @return {int} an integer
    def zombie(self, grid):
        # Write your code here
        if grid is None or len(grid) == 0 or len(grid[0]) == 0:
            return -1

        m, n = len(grid), len(grid[0])
        day, people, zombies = -1, 0, []
        di = [0, 0, 1, -1]
        dj = [1, -1, 0, 0]

        for i in range(m):
            for j in range(n):
                if grid[i][j] == 0:
                    people += 1
                elif grid[i][j] == 1:
                    zombies.append([i, j])

        while zombies:
            new_zombies = []
            for i, j in zombies:
                for k in range(4):
                    zi, zj = i + di[k], j + dj[k]
                    if 0 <= zi < m and 0 <= zj < n and grid[zi][zj] == 0:
                        new_zombies.append([zi, zj])
                        grid[zi][zj] = 1
                        people -= 1
            day += 1
            zombies = new_zombies
            # print day, zombies

        return -1 if people > 0 else day


I am working on the file "04_Control_Structures_Lecture.ipynb".
The first task is:
Another way to get Boolean values is by checking if the membership of given value is valid or not:
Can you write Python code for it?

'Dr.' in 'Dr. Madison'

10 not in (10, 20, 30)


I am working on the file "04_Control_Structures_Lecture.ipynb".
The first task is:
Apply It!

Write a small program that prints the day of the specific month of a year. The output will look like this:

Test 1:
This program will determine the number of days in a given month

Enter the month (1-12): 14
*Invalid Value Entered -14*

Test 2:
This program will determine the number of days in a given month

Enter the month (1-12): 2
Please enter the year (e.g., 2010): 2000
There are 29 days in the month

Use if and elif statements

Hint1:

The days of the month are fixed regardless of the year, except February.

Check for 2.

Hint2:

If the year is divisible by 4 but is also divisible by 100, then it is not a leap year— unless, it is also divisible by 400, then it is.

Hint3:

(year % 4 == 0) and (not (year % 100 == 0) or (year % 400 == 0))

Iterative Control
An iterative control statement is a control statement providing the repeated execution of a set of instructions.

Because of the repeated execution, iterative control structures are commonly referred to as “loops” and that's how I am going to name them :)
A while statement is an iterative control statement that repeatedly executes a set of statements based on a provided Boolean expression (condition).
Syntax:
while condition:
    statement
Can you write Python code for it?

# Initial variables
total = 0
i = 1
n = int(input('Enter value: '))

while i <= n:
    total += i # total = total + i
    i += 1
print(total)


I am working on the file "04_Control_Structures_Lecture.ipynb".
The first task is:
As long as the condition of a while statement is true, the statements within the loop are (re)executed.
Can you write Python code for it?

import time
n = 10
tot = 0
i = 1
while i <= n:
    tot = tot + i
    i = i + 1
    print(tot)
    time.sleep(2)

n = 100
tot = 0
while True:
    tot = tot + n
    n = n - 1
    if n == 0:
        break
print(tot)


I am working on the file "04_Control_Structures_Lecture.ipynb".
The first task is:
Boolean (logical) operators , denoted by and, or, and not in Python. It is basically logic,
Can you write Python code for it?

p = False
r = True

p and r

p or r

not (r and (not p))


I am working on the file "04_Control_Structures_Lecture.ipynb".
The first task is:
Selection Control
A selection control statement is a control statement providing selective execution of instructions.

An if statement is a selection control statement based on the value of a given Boolean expression.
Syntax:
if condition:
    statements
else:
    statements

You don't have to include else part.
Can you write Python code for it?

if 10 < 0:
    print("Yes")

grade = 66
if grade >= 70:
    print('Passing Grade')
else:
    print('Failing Grade')

grade = 100
if grade == 100:
    print('Perfect Score!')


I am working on the file "04_Control_Structures_Lecture.ipynb".
The first task is:
We know that we can compare number for sure, but Python also let's us compare String values based on their character encoding.
Can you write Python code for it?

10 == 20

print(type('2'))
print('2' < '9')

if "Aliya" > "Alican":
    print("Aliya is the best!")
else:
    print("No, Aliya is not the best!")

'Hello' == "hello"

'Hello' > 'Zebra'


I am working on the file "04_CorrectiveSolutions.ipynb".
The first task is:
Compute L matrix: with 5 nodes we expect 2 dofs, one with symmetric load and one with antisymmetric load
Can you write Python code for it?


I am working on the file "04_CorrectiveSolutions.ipynb".
The first task is:
Compute eigenvalues and eigenvectors as:
$$\left| \mathbf{I} \cdot \beta^2 - \mathbf{\tilde{K}}^{-1} \cdot \mathbf{\tilde{M}} \right| = 0$$
We substitute some numerical values to simplify the expressions
Can you write Python code for it?


I am working on the file "04_CorrectiveSolutions.ipynb".
The first task is:
Eigenvalues correspond to $\beta^2$
Can you write Python code for it?


I am working on the file "04_CorrectiveSolutions.ipynb".
The first task is:
Eigenvectors are orthogonal as expected
Can you write Python code for it?


I am working on the file "04_CorrectiveSolutions.ipynb".
The first task is:
First example: Simple rectangular symmetric section
Define graph describing the section:
1) stringers are nodes with parameters:
- x coordinate
- y coordinate
- Area
2) panels are oriented edges with parameters:
- thickness
- lenght which is automatically calculated
Can you write Python code for it?


I am working on the file "04_CorrectiveSolutions.ipynb".
The first task is:
From $\beta_i^2$ we compute:
$$\lambda_i = \sqrt{\frac{E A_0 l_0}{G t_0} \beta_i^2}$$
substuting numerical values
Can you write Python code for it?

λ = [sympy.N(sympy.sqrt(E*A*h/(G*t)*βi).subs(datav)) for βi in β2]
λ


I am working on the file "04_CorrectiveSolutions.ipynb".
The first task is:
Import Section class, which contains all calculations
Can you write Python code for it?


I am working on the file "04_CorrectiveSolutions.ipynb".
The first task is:
Plot of S1 section in original reference frame
Define a dictionary of coordinates used by Networkx to plot section as a Directed graph.
Note that arrows are actually just thicker stubs
Can you write Python code for it?

start_pos={ii: [float(S1.g.node[ii]['ip'][i].subs(datav)) for i in range(2)] for ii in S1.g.nodes() }

plt.figure(figsize=(12,8),dpi=300)
nx.draw(S1.g,with_labels=True, arrows= True, pos=start_pos)
plt.arrow(0,0,20,0)
plt.arrow(0,0,0,20)
#plt.text(0,0, 'CG', fontsize=24)
plt.axis('equal')
plt.title("Section in starting reference Frame",fontsize=16);


I am working on the file "04_CorrectiveSolutions.ipynb".
The first task is:
We also define numerical values for each symbol in order to plot scaled section and perform calculations
Can you write Python code for it?

values = [(A, 150 * ureg.millimeter**2),(A0, 250  * ureg.millimeter**2),(a, 80 * ureg.millimeter), \
          (b, 20 * ureg.millimeter),(h, 35 * ureg.millimeter),(L, 2000 * ureg.millimeter), \
          (t, 0.8 *ureg.millimeter),(E, 72e3 * ureg.MPa), (G, 27e3 * ureg.MPa)]
datav = [(v[0],v[1].magnitude) for v in values]


I am working on the file "04_Diferenciacion/04_Serie_Taylor.ipynb".
The first task is:
Primera diferencia centrada
Usando tres términos de la serie de Taylor expandida hacia adelante
\begin{equation}
    f(x_{i+1}) \approx f(x_{i}) + f'(x_{i}) h + \frac{1}{2} f''(x_{i}) h^{2} \label{ecuacion6}
\end{equation}
Usando tres términos de la serie de Taylor expandida hacia atrás
\begin{equation}
    f(x_{i-1}) \approx f(x_{i}) - f'(x_{i}) h + \frac{1}{2} f''(x_{i}) h^{2} \label{ecuacion7}
\end{equation}
Restando \eqref{ecuacion7} de \eqref{ecuacion6}
\begin{equation}
    f(x_{i+1}) - f(x_{i-1}) \approx 2 f'(x_{i}) h
\end{equation}
Despejando la primera derivada
\begin{equation}
    f'(x_{i}) = \frac{f(x_{i+1}) - f(x_{i-1})}{2 h}
\end{equation}
También puede escribirse como el promedio de una diferencia hacia adelante y una diferencia hacia atrás
\begin{equation}
    f'(x_{i}) = \frac{\frac{f(x_{i+1}) - f(x_{i})}{h} + \frac{f(x_{i}) - f(x_{i-1})}{h}}{2}
\end{equation}
Can you write Python code for it?

def fx_centrada(f,x,h):
    derivada = (fx_adelante(f,x,h) + fx_atras(f,x,h))/2
    return derivada

print('f\'(0.5) =', fx_centrada(g,0.5,0.25))


I am working on the file "04_Diferenciacion/04_Serie_Taylor.ipynb".
The first task is:
Primera diferencia hacia atrás
Usando dos términos de la serie de Taylor expandida hacia atrás
\begin{equation}
    f(x_{i-1}) \approx f(x_{i}) - f'(x_{i}) h
\end{equation}
Despejando la primera derivada
\begin{equation}
    f'(x_{i}) = \frac{f(x_{i}) - f(x_{i-1})}{h}
\end{equation}
Can you write Python code for it?

def fx_atras(f,x,h):
    derivada = (f(x) - f(x-h))/h
    return derivada

print('f\'(0.5) =', fx_atras(g,0.5,0.25))


I am working on the file "04_Diferenciacion/04_Serie_Taylor.ipynb".
The first task is:
Segunda diferencia centrada
Usando tres términos de la serie de Taylor expandida hacia adelante
\begin{equation}
    f(x_{i+1}) \approx f(x_{i}) + f'(x_{i}) h + \frac{1}{2} f''(x_{i}) h^{2} \label{ecuacion15}
\end{equation}
Usando tres términos de la serie de Taylor expandida hacia atrás
\begin{equation}
    f(x_{i-1}) \approx f(x_{i}) - f'(x_{i}) h + \frac{1}{2} f''(x_{i}) h^{2} \label{ecuacion16}
\end{equation}
Sumando \eqref{ecuacion16} a \eqref{ecuacion15}
\begin{equation}
    f(x_{i+1}) + f(x_{i-1}) \approx 2 f(x_{i}) + f''(x_{i}) h^{2}
\end{equation}
Despejando la segunda derivada
\begin{equation}
    f''(x_{i}) = \frac{f(x_{i+1}) - 2 f(x_{i}) + f(x_{i-1})}{h^{2}}
\end{equation}
También puede escribirse como la diferencia de una diferencia hacia adelante y una diferencia hacia atrás
\begin{equation}
    f''(x_{i}) = \frac{\frac{f(x_{i+1}) - f(x_{i})}{h} - \frac{f(x_{i}) - f(x_{i-1})}{h}}{h}
\end{equation}
Can you write Python code for it?

def fxx_centrada(f,x,h):
    derivada = (fxx_adelante(f,x,h) - fxx_atras(f,x,h))/h
    return derivada

print('f\'\'(0.5) =', fxx_centrada(g,0.5,0.25))


I am working on the file "04_Diferenciacion/04_Serie_Taylor.ipynb".
The first task is:
Segunda diferencia hacia adelante
Usando tres términos de la serie de Taylor expandida hacia adelante una posición
\begin{equation}
    f(x_{i+1}) \approx f(x_{i}) + f'(x_{i}) h + \frac{1}{2} f''(x_{i}) h^{2}
\end{equation}
Multiplicando por dos
\begin{equation}
    2 f(x_{i+1}) \approx 2 f(x_{i}) + 2 f'(x_{i}) h + f''(x_{i}) h^{2} \label{ecuacion9}
\end{equation}
Usando tres términos de la serie de Taylor expandida hacia adelante dos posiciones
\begin{equation}
    f(x_{i+2}) \approx f(x_{i}) + 2 f'(x_{i}) h + 2 f''(x_{i}) h^{2} \label{ecuacion10}
\end{equation}
Restando \eqref{ecuacion10} de \eqref{ecuacion9}
\begin{equation}
    2 f(x_{i+1}) - f(x_{i+2}) \approx f(x_{i}) - f''(x_{i}) h^{2}
\end{equation}
Despejando la segunda derivada
\begin{equation}
    f''(x_{i}) = \frac{f(x_{i+2}) - 2 f(x_{i+1}) + f(x_{i})}{h^{2}}
\end{equation}
Can you write Python code for it?

def fxx_adelante(f,x,h):
    derivada = (f(x+2*h) - 2*f(x+h) + f(x))/h**2
    return derivada

print('f\'\'(0.5) =', fxx_adelante(g,0.5,0.25))


I am working on the file "04_Diferenciacion/04_Serie_Taylor.ipynb".
The first task is:
Segunda diferencia hacia atrás
Usando tres términos de la serie de Taylor expandida hacia atrás una posición
\begin{equation}
    f(x_{i-1}) \approx f(x_{i}) - f'(x_{i}) h + \frac{1}{2} f''(x_{i}) h^{2}
\end{equation}
Multiplicando por dos
\begin{equation}
    2 f(x_{i-1}) \approx 2 f(x_{i}) - 2 f'(x_{i}) h + f''(x_{i}) h^{2} \label{ecuacion12}
\end{equation}
Usando tres términos de la serie de Taylor expandida hacia atrás dos posiciones
\begin{equation}
    f(x_{i-2}) \approx f(x_{i}) - 2 f'(x_{i}) h + 2 f''(x_{i}) h^{2} \label{ecuacion13}
\end{equation}
Restando \eqref{ecuacion13} de \eqref{ecuacion12}
\begin{equation}
    2 f(x_{i-1}) - f(x_{i-2}) \approx f(x_{i}) - f''(x_{i}) h^{2}
\end{equation}
Despejando la segunda derivada
\begin{equation}
    f''(x_{i}) = \frac{f(x_{i}) - 2 f(x_{i-1}) + f(x_{i-2})}{h^{2}}
\end{equation}
Can you write Python code for it?

def fxx_atras(f,x,h):
    derivada = (f(x) - 2*f(x-h) + f(x-2*h))/h**2
    return derivada

print('f\'\'(0.5) =', fxx_atras(g,0.5,0.25))


I am working on the file "04_FD_stability_dispersion/1_fd_stability_dispersion.ipynb".
The first task is:
Comparison of numerical with analytical solution
In the function below we solve the homogeneous 1D acoustic wave equation by the 3-point spatial/temporal difference operator and compare the numerical results with the analytical solution. To play a little bit more with the modelling parameters, I restricted the input parameters to dt and dx. The number of spatial grid points and time steps, as well as the discrete source and receiver positions are estimated within this function.
Can you write Python code for it?

# 1D Wave Propagation (Finite Difference Solution)
# ------------------------------------------------
def FD_1D_acoustic(dt,dx):

    nx = (int)(xmax/dx) # number of grid points in x-direction
    print('nx = ',nx)

    nt = (int)(tmax/dt) # maximum number of time steps
    print('nt = ',nt)

    ir = (int)(xr/dx)      # receiver location in grid in x-direction
    isrc = (int)(xsrc/dx)  # source location in grid in x-direction

    # Source time function (Gaussian)
    # -------------------------------
    src  = np.zeros(nt + 1)
    time = np.linspace(0 * dt, nt * dt, nt)

    # 1st derivative of a Gaussian
    src  = -2. * (time - t0) * (f0 ** 2) * (np.exp(- (f0 ** 2) * (time - t0) ** 2))

    # Analytical solution
    # -------------------
    G    = time * 0.

    # Initialize coordinates
    # ----------------------
    x    = np.arange(nx)
    x    = x * dx       # coordinate in x-direction

    for it in range(nt): # Calculate Green's function (Heaviside function)
        if (time[it] - np.abs(x[ir] - x[isrc]) / vp0) >= 0:
            G[it] = 1. / (2 * vp0)
    Gc   = np.convolve(G, src * dt)
    Gc   = Gc[0:nt]
    lim  = Gc.max() # get limit value from the maximum amplitude

    # Initialize empty pressure arrays
    # --------------------------------
    p    = np.zeros(nx) # p at time n (now)
    pold = np.zeros(nx) # p at time n-1 (past)
    pnew = np.zeros(nx) # p at time n+1 (present)
    d2px = np.zeros(nx) # 2nd space derivative of p

    # Initialize model (assume homogeneous model)
    # -------------------------------------------
    vp    = np.zeros(nx)
    vp    = vp + vp0       # initialize wave velocity in model

    # Initialize empty seismogram
    # ---------------------------
    seis = np.zeros(nt)

    # Calculate Partial Derivatives
    # -----------------------------
    for it in range(nt):

        # FD approximation of spatial derivative by 3 point operator
        for i in range(1, nx - 1):
            d2px[i] = (p[i + 1] -...


I am working on the file "04_FD_stability_dispersion/1_fd_stability_dispersion.ipynb".
The first task is:
Hmm, the accurracy of the FD modelling result compared to the analytical solution is clearly deterioated, when the spatial grid point $dx$ is increased. And why does the P-body wave becomes dispersive? More generally, how do I choose $dx$ and $dt$ without using a trial-and-error approach, which requires a lot of computation time, especially when considering 3D modelling. To understand the underlying problems, we will investigate the stability and numerical dispersion of the FD method in the next two sections.
Stability of 1D acoustic wave equation finite difference approximation
To analyse the stability of the finite difference approximation of the 1D acoustic wave equation:
\begin{equation}
 \frac{p_{j}^{n+1} - 2 p_{j}^n + p_{j}^{n-1}}{\mathrm{d}t^2} \ = \ vp_{j}^2 \frac{p_{j+1}^{n} - 2 p_{j}^n + p_{j-1}^{n}}{\mathrm{d}x^2},
\end{equation}
we use an approach introduced by the famous mathematician and pioneer of computational sciences John von Neumann. For the von Neumann Analysis, we assume harmonic plane wave solutions for the pressure wavefield like:
\begin{equation}
p = exp(i(kx-\omega t)),\nonumber
\end{equation}
with $i^2=-1$, the wavenumber $k$ and circular frequency $\omega$. Using the discrete
spatial coordinates:
$x_j = j dx,$
and times
$t_n = n dt.$
We can calculate discrete plane wave solutions at the discrete locations and times in eq. (1), for example at grid point j and time n:
\begin{equation}
p_j^n = exp(i(kjdx-\omega n dt)),\nonumber
\end{equation}
or at grid point j and time n+1:
\begin{align}
p_j^{n+1} &= exp(i(kjdx-\omega (n+1) dt))\nonumber\
&= exp(-i\omega dt)\; exp(i(kjdx-\omega n dt))\nonumber\
&= exp(-i\omega dt)\; p_j^n,\nonumber\
\end{align}
or at the grid point j and time n-1:
\begin{align}
p_j^{n-1} &= exp(i(kjdx-\omega (n-1) dt))\nonumber\
&= exp(i\omega dt)\; exp(i(kjdx-\omega n dt))\nonumber\
&= exp(i\omega dt)\; p_j^n.\nonumber\
\end{align}
Similar approximations can be estimated for time n at the spatial grid points j+1:
\begin{align}
p_{j+1}^{n} &= exp(i(k(j+1)dx-\omega...
Can you write Python code for it?

Nwave = np.arange(2,12,0.25) # numbers per wavelength
vp0 = 333.0 # P-wave velocity (m/s)

def dispersion_1D(eps):

    vp_phase = (vp0*Nwave/(np.pi*eps)) * np.arcsin(eps*np.sin(np.pi/Nwave))

    return vp_phase

vp_eps_1 = dispersion_1D(1.0)
vp_eps_2 = dispersion_1D(0.9)
vp_eps_3 = dispersion_1D(0.8)
vp_eps_4 = dispersion_1D(0.7)

plt.plot(Nwave, vp_eps_1, 'b-',lw=3,label=r"$\epsilon=1$")
plt.plot(Nwave, vp_eps_2, 'r-',lw=3,label=r"$\epsilon=0.9$")
plt.plot(Nwave, vp_eps_3, 'g-',lw=3,label=r"$\epsilon=0.8$")
plt.plot(Nwave, vp_eps_4, 'k-',lw=3,label=r"$\epsilon=0.7$")
plt.title('Grid dispersion')
plt.xlabel('Number of grid points per wavelength')
plt.ylabel('Phase velocity $v_{phase}$, m/s')
plt.legend()
plt.grid()
plt.show()


I am working on the file "04_FD_stability_dispersion/1_fd_stability_dispersion.ipynb".
The first task is:
Notice, that no grid dispersion occurs in the case of $\epsilon=1$. Keep in mind though that this only true for the homogeneous medium. Realistic modelling problems have a variable P-wave velocity, so we have not a constant $\epsilon$ within the model.
For all values $\epsilon<1$, numerical dispersion can occur, if the sampling of the spatial model is too small, especially when using only the Nyquist criterion $N_\lambda = 2$. For the 1D acoustic wave equation, the dispersion is minimized for $N_\lambda$ values between 8-12.
More generally, we can define the grid dispersion criterion for the spatial gridpoint distance
\begin{equation}
dx \le \frac{\lambda_{min}}{N_\lambda} = \frac{v_{min}}{N_\lambda f_{max}},\nonumber
\end{equation}
where $N_\lambda$ depends on the used FD operator, numerical scheme and also wave type, $v_{min}$ is the minimum P- or S-wave velocity in the model and $f_{max}$ the maximum frequency of the source wavelet.
Finally, let's apply the dispersion and stability criteria to our test problem in order to find optimum dt and dx values ...
Can you write Python code for it?

# calculate dx according to the grid dispersion criterion
Nlam = 12              # number of grid points per wavelength
fmax = 50.0            # fmax = 2 * f0 (Hz)
dx = vp0 / (Nlam*fmax) # spatial gridpoint distance (m)
print('dx = ', dx)

# calculate dt according to the CFL criterion
dt = dx / vp0 # time step (s)

# check CFL criterion
epsilon = vp0 * dt / dx
print('epsilon = ', epsilon)
if(epsilon>1.0):
    print('Warning: CFL condition is violated!')
print('dt = ', dt)

FD_1D_acoustic(dt,dx)


I am working on the file "04_FD_stability_dispersion/1_fd_stability_dispersion.ipynb".
The first task is:
Oops, maybe this idea was not so smart at all, because the modelling becomes unstable. Instead of increasing the time step dt, we could try to increase the spatial discretization dx to save computation time ...
Can you write Python code for it?

# dx   = 0.5 # old grid point distance in x-direction
dx   = 7.0 # new grid point distance in x-direction
dt   = 0.0010  # time step
FD_1D_acoustic(dt,dx)


I am working on the file "04_FD_stability_dispersion/1_fd_stability_dispersion.ipynb".
The first task is:
This is the same result, we achieved in the last lesson. Now, you might get the smart idea to save some computation time by increasing the timestep dt. Let's try it ...
Can you write Python code for it?

dx   = 0.5 # grid point distance in x-direction
#dt   = 0.0010  # old time step
dt   = 0.0015023  # time step
FD_1D_acoustic(dt,dx)


I am working on the file "04_FD_stability_dispersion/lecture_notebooks/1_fd_stability_dispersion.ipynb".
The first task is:
Comparison of numerical with analytical solution
In the function below we solve the homogeneous 1D acoustic wave equation by the 3-point spatial/temporal difference operator and compare the numerical results with the analytical solution. To play a little bit more with the modelling parameters, I restricted the input parameters to dt and dx. The number of spatial grid points and time steps, as well as the discrete source and receiver positions are estimated within this function.
Can you write Python code for it?


I am working on the file "04_FD_stability_dispersion/lecture_notebooks/1_fd_stability_dispersion.ipynb".
The first task is:
This is the same result, we achieved in the last lesson. Now, you might get the smart idea to save some computation time by increasing the timestep dt. Let's try it ...
Can you write Python code for it?


I am working on the file "04_FD_stability_dispersion/lecture_notebooks/4_general_fd_taylor_operators.ipynb".
The first task is:
Generalization of Taylor FD operators
In the last lesson, we learned how to derive a high order FD approximation for the second derivative using Taylor series expansion. In the next step we derive a general equation to compute FD operators, where I use a detailed derivation based on "Derivative Approximation by Finite Differences" by David Eberly
Estimation of arbitrary FD operators by Taylor series expansion
We can approximate the $d-th$ order derivative of a function $f(x)$ with an order of error $p>0$ by a general finite-difference approximation:
\begin{equation}
\frac{h^d}{d!}f^{(d)}(x) = \sum_{i=i_{min}}^{i_{max}} C_i f(x+ih) + \cal{O}(h^{d+p})
\end{equation}
where h is an equidistant grid point distance. By choosing the extreme indices $i_{min}$ and $i_{max}$, you can define forward, backward or central operators. The accuracy of the FD operator is defined by it's length and therefore also the number of
weighting coefficients $C_i$ incorporated in the approximation. $\cal{O}(h^{d+p})$ terms are negelected.
Formally, we can approximate $f(x+ih)$ by a Taylor series expansion:
\begin{equation}
f(x+ih) = \sum_{n=0}^{\infty} i^n \frac{h^n}{n!}f^{(n)}(x)\nonumber
\end{equation}
Inserting into eq.(1) yields
\begin{align}
\frac{h^d}{d!}f^{(d)}(x) &= \sum_{i=i_{min}}^{i_{max}} C_i \sum_{n=0}^{\infty} i^n \frac{h^n}{n!}f^{(n)}(x) + \cal{O}(h^{d+p})\nonumber\
\end{align}
We can move the second sum on the RHS to the front
\begin{align}
\frac{h^d}{d!}f^{(d)}(x) &= \sum_{n=0}^{\infty} \left(\sum_{i=i_{min}}^{i_{max}} i^n C_i\right) \frac{h^n}{n!}f^{(n)}(x) + \cal{O}(h^{d+p})\nonumber\
\end{align}
In the FD approximation we only expand the Taylor series up to the term $n=(d+p)-1$
\begin{align}
\frac{h^d}{d!}f^{(d)}(x) &= \sum_{n=0}^{(d+p)-1} \left(\sum_{i=i_{min}}^{i_{max}} i^n C_i\right) \frac{h^n}{n!}f^{(n)}(x) + \cal{O}(h^{d+p})\nonumber\
\end{align}
and neglect the $\cal{O}(h^{d+p})$ terms
\begin{align}
\frac{h^d}{d!}f^{(d)}(x) &= \sum_{n=0}^{(d+p)-1} \left(\sum_{i=i_{min}}^{i_{max}} i^n C_i\right)...
Can you write Python code for it?

# import SymPy libraries
from sympy import symbols, differentiate_finite, Function

# Define symbols
x, h = symbols('x h')
f = Function('f')


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Ahora graficaremos las 3 especies versus la longitud del sépalo usando la función stripplot de seaborn:
Can you write Python code for it?

sns.stripplot(x="species", y="sepal_length", data=iris, jitter=True)
plt.title('Figure 4.2');


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Ahora vamos a generar una figura que muestra las dos clases (setosa = 0 yversicolor = 1) contra los valores de la longitud del sépalo, y también el límite de decisión como una línea naranja y el intervalo del 94% de HPD como una banda naranja semitransparente.
Can you write Python code for it?

plt.axvline(trace_lda['bd'].mean(), ymax=1, color='C1')
bd_hpd = pm.hpd(trace_lda['bd'])
plt.fill_betweenx([0, 1], bd_hpd[0], bd_hpd[1], color='C1', alpha=0.5)

plt.plot(x_0, np.random.normal(y_0, 0.02), '.', color='k')
plt.ylabel('θ', rotation=0)
plt.xlabel('sepal_length')
plt.title('Figure 4.9');


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Ahora vamos a graficar los datos junto con la curva sigmoide ajustada:
Can you write Python code for it?

theta = trace_0['θ'].mean(axis=0)
idx = np.argsort(x_c)
plt.figure(figsize=(10, 6))
plt.plot(x_c[idx], theta[idx], color='C2', lw=3);
plt.vlines(trace_0['bd'].mean(), 0, 1, color='k')
bd_hpd = az.hpd(trace_0['bd'])
plt.fill_betweenx([0, 1], bd_hpd[0], bd_hpd[1], color='k', alpha=0.5)

plt.scatter(x_c, np.random.normal(y_0, 0.02), marker='.', color=[f'C{x}' for x in y_0])
theta_hpd = az.hpd(trace_0['θ'])[idx]
plt.fill_between(x_c[idx], theta_hpd[:,0], theta_hpd[:,1], color='C2', alpha=0.5)

plt.xlabel(x_n)
plt.ylabel('θ', rotation=0, labelpad=20)
# use original scale for xticks
locs, _ = plt.xticks()
plt.xticks(locs, np.round(locs + x_0.mean(), 1))
plt.title('Figure 4.4');


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Al igual que con otros modelos lineales, centrar los datos puede ayudar con el muestreo. Ahora que tenemos los datos en el formato adecuado, finalmente podemos construir el modelo con PyMC3.
Observe cómo la primera parte del siguiente modelo se asemeja a un modelo de regresión lineal. Este modelo tiene dos variables deterministas: θ ybd. θ es la salida de la función logística aplicada a la variable μ y bd es límite de decisión (el cual explicaremos más adelante).Otro punto que vale la pena mencionar es que en lugar de escribir explícitamente la función logística estamos usando pm.math.sigmoid (esto es un alias para una función de Theano).
Can you write Python code for it?

with pm.Model() as modelo_0:
    α = pm.Normal('α', mu=0, sd=10)
    β = pm.Normal('β', mu=0, sd=10)

    μ = α + pm.math.dot(x_c, β)
    θ = pm.Deterministic('θ', pm.math.sigmoid(μ))
    bd = pm.Deterministic('bd', -α/β)

    yl = pm.Bernoulli('yl', p=θ, observed=y_0)

    trace_0 = pm.sample(1000)

varnames = ['α', 'β', 'bd']
az.plot_trace(trace_0, varnames);


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Aquí tenemos algunas versicolors (1s) con una longitud de sépalo inusualmente corta. Podemos arreglar esto con un modelo de mezcla. Vamos a decir que la variable de salida viene con probabilidad $\pi$ por adivinación aleatoria o con probabilidad $1-\pi$ de un modelo de regresión logística. Matemáticamente, tenemos:
$$p = \pi \ 0.5 + (1 - \pi) \: \text{logistic}(\alpha + X \beta) \tag{4.26} $$
Tenga en cuenta que cuando $\pi = 1$ obtenemos $p = 0.5 $, y para $\pi = 0 $ recuperamos la expresión para regresión logística.
La implementación de este modelo es una modificación directa del primer modelo de este capítulo.
Can you write Python code for it?

with pm.Model() as modelo_rlg:
    α = pm.Normal('α', mu=0, sd=10)
    β = pm.Normal('β', mu=0, sd=10)

    μ = α + x_c *  β
    θ = pm.Deterministic('θ', pm.math.sigmoid(μ))
    bd = pm.Deterministic('bd', -α/β)

    π = pm.Beta('π', 1, 1)
    p = π * 0.5 + (1 - π) * θ

    yl = pm.Bernoulli('yl', p=p, observed=y_0)

    trace_rlg = pm.sample(1000)

az.summary(trace_rlg, varnames)

theta = trace_rlg['θ'].mean(axis=0)
idx = np.argsort(x_c)
plt.plot(x_c[idx], theta[idx], color='C2', lw=3);
plt.vlines(trace_rlg['bd'].mean(), 0, 1, color='k')
bd_hpd = pm.hpd(trace_rlg['bd'])
plt.fill_betweenx([0, 1], bd_hpd[0], bd_hpd[1], color='k', alpha=0.5)

plt.scatter(x_c, np.random.normal(y_0, 0.02), marker='.', color=[f'C{x}' for x in y_0])
theta_hpd = pm.hpd(trace_rlg['θ'])[idx]
plt.fill_between(x_c[idx], theta_hpd[:,0], theta_hpd[:,1], color='C2', alpha=0.5)

plt.xlabel(x_n)
plt.ylabel('θ', rotation=0)
# use original scale for xticks
locs, _ = plt.xticks()
plt.xticks(locs, np.round(locs + x_0.mean(), 1))
plt.title('Figure 4.13');


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Como es habitual, también mostramos el summary del posterior. Más adelante, compararemos el valor que obtengamos para el límite de decisión con un valor calculado utilizando otro método.
Can you write Python code for it?


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Como habrá notado, la figura 4.9 es bastante similar a la figura 4.4. Verifique también los valores de la decisión de límite en el siguiente summary:
Can you write Python code for it?


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Como hicimos para una única variable predictiva, vamos a graficar los datos y el límite de decisión.
Can you write Python code for it?

idx = np.argsort(x_1[:,0])
bd = trace_1['bd'].mean(0)[idx]
plt.scatter(x_1[:,0], x_1[:,1], c=[f'C{x}' for x in y_0])
plt.plot(x_1[:,0][idx], bd, color='k');

bd_hpd = az.hpd(trace_1['bd'])[idx]
plt.fill_between(x_1[:,0][idx], bd_hpd[:,0], bd_hpd[:,1], color='k', alpha=0.5);

plt.xlabel(x_n[0])
plt.ylabel(x_n[1])
plt.title('Figure 4.5');


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
El código de PyMC3 refleja los pocos cambios entre el modelo logístico y el modelo softmax. Presta atención a los valores de shape para los coeficientes $\alpha $ y $\beta$. En el siguiente código usamos la función softmax de Theano. Hemos utilizado la expresión import theano.tensor as tt, que es la convención utilizada por los desarrolladores de PyMC3:
Can you write Python code for it?

with pm.Model() as modelo_s:
    α = pm.Normal('α', mu=0, sd=5, shape=3)
    β = pm.Normal('β', mu=0, sd=5, shape=(4,3))
    μ = pm.Deterministic('μ', α + pm.math.dot(x_s, β))
    θ = tt.nnet.softmax(μ)
    yl = pm.Categorical('yl', p=θ, observed=y_s)
    trace_s = pm.sample(2000)

az.plot_forest(trace_s, var_names=['α', 'β']);


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
El límite de decisión es una línea recta, como ya hemos visto. No se confunda con el aspecto curvo de la banda del 94% de HPD. La curvatura aparente es el resultado de tener múltiples líneas que giran alrededor de una región central (aproximadamente alrededor de la media de x y la media de y).
Interpretación de los coeficientes de una regresión logística
Debemos tener cuidado al interpretar los coeficientes $\beta$ de una regresión logística. La interpretación no es tan sencilla como con los modelos lineales en el capítulo anterior. La función logística introduce una no linearidad, que debemos tener en cuenta. Si $\beta$ es positivo, aumentar $x$ aumentará $p(y = 1)$ en cierta cantidad, pero la cantidad no es una función lineal de $x$, es en cambio una función no-lineal de $x$. Podemos visualizar este hecho en la figura 4.4, en lugar de una línea con una pendiente constante, tenemos una línea en forma de S con una pendiente que cambia en función de $x$. Un poco de álgebra nos puede dar una idea de cuánto cambia $p(y=1)$ con $\beta$:
El modelo logístico básico es:
$$\theta = logistic (\alpha + X \beta) \tag{4.11} $$
El inverso de la logística es la función logit, que es:
$$ logit(z) = log \left (\frac{z}{1-z} \right) \tag{4.12}$$
Por lo tanto, si tomamos la primera ecuación en esta sección y aplicamos la función logit a ambos términos, obtenemos:
$$ logit(\theta) = \alpha + X \beta \tag{4.13}$$
O equivalente:
$$ log \left (\frac{\theta} {1-\theta} \right) = \alpha + X \beta \tag {4.14}$$
Recuerden que $\theta$ en nuestro modelo era la probabilidad de $y = 1 $, por lo tanto:
$$ log \left(\frac {p(y = 1)} {1-p (y = 1)} \right) = \alpha + X \beta \tag {4.15} $$
La cantidad $$\frac{p (y = 1)} {1-p (y = 1)}$$ se conoce como odds. Los odds a favor se definen como la relación entre la probabilidad de éxito y la probabilidad de no éxito. Mientras que la probabilidad de obtener 2 tirando un dado es 1/6, los odds para el mismo evento son $\frac{1/6}{5/6} \simeq 0.2$ o dicho de otra forma 1 evento favorable frente a 5...
Can you write Python code for it?

probability = np.linspace(0.01, 1, 100)
odds = probability / (1 - probability)

_, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.plot(probability, odds, 'C0')
ax2.plot(probability, np.log(odds), 'C1')

ax1.set_xlabel('probability')
ax1.set_ylabel('odds', color='C0')
ax2.set_ylabel('log-odds', color='C1')
ax1.grid(False)
ax2.grid(False)
plt.title('Figure 4.6');


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
El límite de decisión se desplaza hacia la clase menos abundante y la incertidumbre es más grande que antes. Este es el comportamiento típico de un modelo logístico para datos no balanceados. ¡Pero espera un minuto! Bien podrías argumentar que te estoy engañando ya que la mayor incertidumbre es en realidad el producto de tener menos datos y no solo menos setosas que versicolores. Este es un punto totalmente válido, pero si realizas el ejercicio 2 podrás verificar que lo que explica esta gráfica son los datos desequilibrados.
Can you write Python code for it?

idx = np.argsort(x_3[:,0])
bd = trace_3['bd'].mean(0)[idx]
plt.scatter(x_3[:,0], x_3[:,1], c= [f'C{x}' for x in y_3])
plt.plot(x_3[:,0][idx], bd, color='k');

bd_hpd = pm.hpd(trace_3['bd'])[idx]
plt.fill_between(x_3[:,0][idx], bd_hpd[:,0], bd_hpd[:,1], color='k', alpha=0.5);

plt.xlabel(x_n[0])
plt.ylabel(x_n[1]);

plt.title('Figure 4.8')


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
El resultado es que clasificamos correctamente $\approx 98 \%$ de los datos, es decir, clasificamos erroneamente solo tres casos. Ese es realmente un muy buen trabajo. Sin embargo, una verdadera prueba para evaluar el rendimiento de nuestro modelo sería verificarlo con un conjunto de datos no usado para ajustar al modelo. De lo contrario, es posible que estemos sobreestimando la capacidad real del modelo para generalizar a otros datos.
Es posible que hayas notado que las distribuciones marginales de cada parámetro son muy amplias. Este es el mismo problema de no identificabilidad que ya hemos encontrado para los datos correlacionados en otros modelos de regresión o con clases perfectamente separables. En este caso, el ancho posterior se debe a la condición de que todas las probabilidades deben sumar 1. Dada esta condición, estamos usando más parámetros de los que necesitamos para especificar completamente el modelo. En términos simples, si tenés 10 números que suman 1, solo necesitás darme 9 de ellos; el otro puedo calcularlo. Esto es precisamente lo que está pasando con este problema. Una solución es fijar los parámetros extra a algún valor, por ejemplo, cero. El siguiente código muestra cómo lograr esto usando PyMC3:
Can you write Python code for it?

with pm.Model() as modelo_sf:
    α = pm.Normal('α', mu=0, sd=2, shape=2)
    β = pm.Normal('β', mu=0, sd=2, shape=(4,2))
    α_f = tt.concatenate([[0] ,α])
    β_f = tt.concatenate([np.zeros((4,1)) , β], axis=1)
    μ = α_f + pm.math.dot(x_s, β_f)
    θ = tt.nnet.softmax(μ)
    yl = pm.Categorical('yl', p=θ, observed=y_s)
    trace_sf = pm.sample(1000)

az.plot_forest(trace_sf, var_names=['α', 'β']);


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
El segundo paso consiste en usar como likelihood una distribución binomial y no una Gaussiana. De esta forma el modelo queda expresado como:
$$
\theta = logistic(\alpha + x\beta) \
y = \text{Bern}(\theta) \tag{4.3}
$$
Esto modelo se puede motivar de la siguiente forma. Si nuestros datos son binarios $y \in {0, 1}$, como con el ejemplo de la moneda o el diagnóstico, vemos que tiene sentido usar una distribución bernoulli. Esta distribución está parametrizada por un único parámetro en el intervalo [0, 1], el cual puede ser generado desde un modelo lineal siempre y cuando los valores generados por el modelo lineal sean comprimidos al intervalo [0, 1], algo que puede ser obtenido al emplear una función logística.
Usando un diagrama de Kruschke una regresión logística con priors Gaussianos:
<img alt="regresión_logística" src="imagenes/logística.png" width=250>
El conjunto de datos del Iris
Vamos a aplicar una regresión logística al conjunto de datos Iris. Este es un conjunto de datos clásico que contiene información sobre flores de 3 especies estrechamente relacionadas: setosa, virginica y versicolor. Estas serán nuestras variables dependientes, las clases que queremos predecir. Tenemos 50 individuos de cada especie y para cada individuo el conjunto de datos contiene cuatro variables (o features) que vamos a usar como variables independientes. Estas son el largo del pétalo, el ancho del pétalo, el largo del sépalo y el ancho del sépalo. Por si se lo están preguntando, los sépalos son hojas modificadas, cuya función está generalmente relacionada con la protección de las flores en la yema.
Podemos cargar un DataFrame con el conjunto de datos del iris haciendo:
Can you write Python code for it?

iris = pd.read_csv('datos/iris.csv')
iris.head()


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
En el último capítulo, usamos una combinación lineal de variables independientes para predecir la media de una variable dependiente. Asumimos que en general la variable dependiente se distribuía como una Gaussiana y también exploramos que sucedía al relajar esta condición y usar una distribución t de Student. En este capítulo veremos más ejemplos donde es aconsejable usar distribuciones distintas a las gaussianas. Como veremos pronto, hay un motivo general, o patrón, que se puede usar para generalizar el modelo lineal a muchos problemas.
En el presente capítulo veremos:

Regresión logística y funciones inversa de enlace
Regresión logística simple
Regresión logística múltiple
La función de softmax y la regresión logística multinomial
Regresión de Poisson
Regresión de Poisson cero-inflada

Modelos lineales generalizados
La principal idea de este capítulo es bastante simple, en lugar de usar una combinación lineal de variables de entrada para predecir la media de una variable de salida, vamos a aplicar una función a la combinación lineal de variables de entrada para predecir la media de la variable de salida:
$$\mu = f(\alpha + X \beta) \tag{4.1}$$
donde $f$ es lo que se conoce como función inversa de enlace. Hay una gran variedad de funciones inversas de enlace que podemos elegir, probablemente la más simple sea la función identidad. Esta es una función que devuelve el mismo valor utilizado como argumento. Todos los modelos del capítulo anterior usaron la función de identidad, y por simplicidad simplemente la omitimos. La función de identidad puede no ser muy útil en sí misma, pero nos permite pensar en varios modelos diferentes de una manera unificada.
¿Por qué llamamos a $f$ función inversa de enlace en lugar de llamarla simplemente función de enlace? La razón es histórica. Tradicionalmente las personas aplican funciones al otro lado de la ecuación $4.1$, y llaman a esas funciones funciones de enlace, por lo tanto, para evitar confusiones, nos apegaremos al término función de enlace inverso.
Una situación en...
Can you write Python code for it?

z = np.linspace(-6, 6)
logística = 1 / (1 + np.exp(-z))
plt.plot(z, logística)
plt.xlabel('z')
plt.ylabel('logística(z)')
plt.title('Figure 4.1');


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Es importante notar que $\mu$ puede ser un flotante, pero la distribución modela probabilidad de un número discreto de eventos. En la figura 4.10, los puntos representan los valores de la distribución, mientras que las líneas continuas son una ayuda visual que nos ayuda a comprender fácilmente la forma de la distribución. Recuerde, la distribución de Poisson es una distribución discreta.
La distribución de Poisson puede verse como un caso especial de la distribución binomial cuando la cantidad de intentos $n$ es muy grande pero la probabilidad de éxito $p$ es muy baja. Sin entrar en detalles matemáticos, tratemos de aclarar la afirmación anterior. Siguiendo el ejemplo del auto, podemos afirmar que o vemos el auto rojo o no, por lo que podemos usar una distribución binomial. En ese caso tenemos:
$$ x \sim Bin(n, p) \tag{4.18}$$
Entonces, la media de la distribución binomial es:
$$\mathbf{E}[x] = np \tag{4.19} $$
Y la varianza viene dada por:
$$ \mathbf {V}[x] = np (1 - p) \tag{4.20}$$
Pero tenga en cuenta que incluso si se encuentra en una avenida muy transitada, la posibilidad de ver un auto rojo en comparación con el número total de automóviles en una ciudad es muy pequeño y, por lo tanto, tenemos:
$$n >> p \Rightarrow np \simeq np (1-p) \tag{4.21}$$
Entonces, podemos hacer la siguiente aproximación:
$$\mathbf {V}[x] = np \tag{4.22}$$
Ahora la media y la varianza están representadas por el mismo número y podemos
declarar con confianza que nuestra variable se distribuye como una distribución de Poisson:
$$x \sim Poisson(\mu = np) \tag{4.23}$$
El modelo de Poisson inflado de ceros
Al contar cosas, una posibilidad es no contar esas cosas, es decir obtener cero. El número cero puede ocurrir generalmente por muchas razones; obtuvimos un cero porque estábamos contando autos rojos y un auto rojo no pasó por la avenida o porque no logramos verlo (tal vez no vimos pasar un diminuto auto rojo detrás de un gran camión). Entonces, si usamos una distribución de Poisson, notaremos, por ejemplo, cuando realizamos una...
Can you write Python code for it?

#np.random.seed(42)
n = 100
θ_real = 2.5
ψ = 0.1

# Simulate some data
counts = np.array([(np.random.random() > (1-ψ)) * np.random.poisson(θ_real)
                   for i in range(n)])

with pm.Model() as ZIP:
    ψ = pm.Beta('ψ', 1., 1.)
    θ = pm.Gamma('θ', 2., 0.1)
    y = pm.ZeroInflatedPoisson('y', ψ, θ, observed=counts)
    trace = pm.sample(1000)

az.plot_trace(trace)
plt.title('Figure 4.11');

az.summary(trace)


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
La figura 4.4 muestra la longitud del sépalo para las especies (setosa = 0, versicolor = 1). Para mitigar la superposición de los datos, hemos agregado ruido (jitter) a las variables-respuesta binarias. Una línea verde en forma de S representa el valor medio de $\theta$. Esta línea se puede interpretar como la probabilidad que una flor sea versicolor dado el valor de la longitud del sépalo. La banda verde semitransparente es el intervalo del 94% de HPD. De esta forma podemos interpretar a la regresión logística como una forma de combinar variables linealmente a fin de obtener una probabilidad para variables binarias.
Alternativamente podemos usar una regresión logística para clasificar, esto lo podemos hacer discretizando el valor de probabilidad obtenido. El caso más común es asignar la clase 1 si la probabilidad es mayor a 0.5 y asignar la clase 0 en caso contrario. En la figura 4.4 hemos graficado este límite de decisión usando una línea vertical negra junto con su 94% HPD (la banda gris). De acuerdo con el límite de decisión, los valores $x_i$ (longitud del sépalo en este caso) a la izquierda corresponden a la clase 0 (setosa) y los valores a la derecha a la clase 1 (versicolor).
El límite de decisión se define como el valor de $x_i$, para el cual $y = 0.5$. Y resulta ser $- \frac{\alpha}{\beta} $, como podemos comprobar a continuación:
A partir de la definición del modelo tenemos la relación:
$$\theta = logistic(\alpha + x \beta) \tag{4.4}$$
Y a partir de la definición de la función logística tenemos que $\theta = 0.5 $, cuando el argumento de la regresión logística es 0, es decir:
$$0.5 = logística(\alpha + x_i \beta) \Leftrightarrow 0 = \alpha + x_i \beta \tag{4.5}$$
Reordenando 4.5, encontramos que el valor de $x_i$, para el cual, $\theta = 0.5$ corresponde a la expresión:
$$x_i = - \frac{\alpha}{\beta} \tag{4.6}$$
Resumiendo los puntos más importantes hasta el momento:

El valor de $\theta$ es, en términos generales, $p(y= 1 \mid x) $. En este sentido, la regresión logística es en realidad una...
Can you write Python code for it?

df = iris.query("species == ('setosa', 'versicolor')")
y_1 = pd.Categorical(df['species']).codes
x_n = ['sepal_length', 'sepal_width']
#x_n = ['petal_length', 'petal_width']
x_1 = df[x_n].values


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Lo dejo como un ejercicio para que explore el conjunto de datos utilizando gráficos y / o una función de Pandas, como describe(). Por ahora vamos a continuar traduciendo el diagrama de Kruschke anterior a PyMC3:
Can you write Python code for it?

with pm.Model() as ZIP_reg:
    ψ = pm.Beta('ψ', 1, 1)
    α = pm.Normal('α', 0, 10)
    β = pm.Normal('β', 0, 10, shape=2)
    θ = pm.math.exp(α + β[0] * fish_data['child'] + β[1] * fish_data['camper'])
    yl = pm.ZeroInflatedPoisson('yl', ψ, θ, observed=fish_data['count'])
    trace_ZIP_reg = pm.sample(1000)
az.plot_trace(trace_ZIP_reg);


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Observe en la figura 4.2 que en el eje y se representan una variable continua mientras que en el eje x la variable es categórica. La dispersión (o jitter) de los puntos a lo largo del eje x no tiene ningún significado, y es solo un truco para evitar que todos los puntos colapsen en una sola línea (pueden probar pasando el argumento jitter=False). Por lo tanto lo único que importa al leer el eje x es la pertenencia de los puntos a las clases setosa, versicolor o virginica.
Otra forma de inspeccionar los datos es haciendo una matriz de dispersión con la función pairplot. En la figura 4.3 podemos ver una matriz de $4 \times 4$, ya que tenemos 4 variables independientes (o features). La matriz es simétrica con los triángulos superior e inferior conteniendo la misma información. En la diagonal principal en vez de tener una gráfico de dispersión de una variable contra si misma (lo cual no es informativo) tenemos un KDE de cada feature para cada especie (o clase). Cada especie está representada usando un color particular.
Can you write Python code for it?

sns.pairplot(iris, hue='species')
plt.title('Figure 4.3');


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Para generar la figura 4.7, hemos utilizado una máscara que elimina el triángulo superior y los elementos diagonales del heatmap, ya que estos son poco informativos o redundantes. Observe también que hemos graficado el valor absoluto de la correlación, ya que en este momento no nos importa el signo de la correlación entre las variables, solo su fuerza.
Una solución cuando se trabaja con variables (altamente) correlacionadas, es simplemente eliminar una (o más de una) de las variables correlacionadas. Otra opción es poner más información en el a priori, esto se puede lograr con a prioris informativos si es que contamos con información previa útil, o más general utilizando a prioris ligeramente informativos. Andrew Gelman y el equipo de Stan recomiendan usar el siguiente a priori al realizar una regresión logística:
$$ \beta \sim Student t (0, \nu, sd) \tag {4.10}$$
donde sd se elije de forma que informe débilmente sobre los valores esperados para la escala. Se sugiere que el parámetro de normalidad $\nu$ sea alrededor de 3-7. Lo que dice este a priori es que esperamos que el coeficiente sea pequeño, pero ponemos colas pesadas porque esto nos lleva a un modelo más robusto que el uso de una distribución gaussiana.
Tratando con clases desequilibradas
El conjunto de datos del iris está completamente equilibrado; en el sentido de que cada categoría tiene exactamente el mismo número de observaciones. Tenemos 50 setosas, 50 versicolores, y 50 virgininas. Por el contrario, muchos conjuntos de datos constan de datos no balanceados, es decir, hay muchos más datos de una clase que de la otra. Cuando esto sucede, la regresión logística puede generar problemas, es decir, el límite no se puede determinar con la misma precisión que cuando el conjunto de datos está más equilibrado.
Para ver un ejemplo de este comportamiento, vamos a usar el conjunto de datos del iris y vamos a eliminar arbitrariamente algunos puntos de datos de la clase setosa:
Can you write Python code for it?

df = iris.query("species == ('setosa', 'versicolor')")
df = df[45:]
y_3 = pd.Categorical(df['species']).codes
x_n = ['sepal_length', 'sepal_width']
x_3 = df[x_n].values


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Por lo tanto, los valores de los coeficientes proporcionados por summary están en la escala log-odds.
Can you write Python code for it?


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Regresión de Poisson y regresión ZIP
El modelo ZIP puede parecer un poco aburrido, pero a veces necesitamos estimar distribuciones simples como esta u otra como las distribuciones de Poisson o Gaussianas. Además, podemos usar las distribuciones Poisson o ZIP como parte de un modelo lineal. Como vimos con la regresión logística (y softmax) podemos usar una función de enlace inverso para transformar el resultado de un modelo lineal en una variable adecuada para ser utilizada con otra distribución que no sea la normal. En la siguiente figura, vemos una posible implementación de una regresión ZIP. La regresión de Poisson será similar, pero sin la necesidad de incluir $\phi$ ya que no modelaremos un exceso de ceros. Observe que ahora usamos la función exponencial como la función de enlace inverso. Esta elección garantiza que los valores devueltos por el modelo lineal sean positivos.
Para ejemplificar la implementación de un modelo de regresión ZIP, vamos a trabajar con un conjunto de datos tomado del Instituto de Investigación y Educación Digital.
El problema es el siguiente: trabajamos en la administración de un parque y queremos mejorar la experiencia de los visitantes. Por lo tanto, decidimos realizar una breve encuesta a 250 grupos que visitan el parque. Parte de los datos que recopilamos (a nivel de grupo) consiste en:

La cantidad de peces que capturaron (contar)
Cuántos niños había en el grupo (niño)
Ya sea que hayan traído o no una casa-rodante o "caravana" al parque (camper).

Usando estos datos, vamos a construir un modelo que predice el número de peces capturados en función de las variables niño y caravana. Podemos usar Pandas para cargar los datos:
Can you write Python code for it?


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Si ejecutas el código, encontrarás que el aumento en las log-odds es de $\approx 4.7$, que es exactamente el valor de $\beta_0$ (verifique el summary para trace_1). Esto está en línea con nuestro hallazgo anterior que muestra que los coeficientes $\beta$ indican el aumento en unidades log-odds por incremento unitario de la variable $x$. El aumento en la probabilidad es $\approx 0.70$.
Trabajando con variables correlacionadas
Sabemos por el capítulo anterior que trabajar con variables muy correlacionadas puede traernos problemas. Las variables correlacionadas se traducen en combinaciones más amplias de coeficientes que explican los datos o, desde el punto de vista complementario, variables correlacioadas tienen menos poder para restringir los modelos. Un problema similar ocurre cuando las clases se vuelven perfectamente separables, es decir, no hay superposición entre clases dada la combinación lineal de variables en nuestro modelo. Podemos visualizar un ejemplo de esto al usar el conjunto de datos iris con el modelo_1, pero esta vez utilizando las variables ancho de pétalo y largo de pétalo. Encontraras que los coeficientes $\beta$ son más amplios que antes y también el 94% HPD (banda gris en la figura 4.5) es mucho más amplia. La figura 4.7 muestra un heatmap para las variables sepal_length y sepal_width (usadas en el primer ejemplo) la correlación no es tan alta como la correlación entre las variables petal_length y petal_width  (usada en el segundo ejemplo).
Can you write Python code for it?

corr = iris[iris['species'] != 'virginica'].corr()
mask = np.tri(*corr.shape).T
sns.heatmap(corr.abs(), mask=mask, annot=True, cmap='viridis')
plt.title('Figure 4.7');


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Tanto el modelo LDA como la regresión logística proporcionan resultados similares. El modelo discriminante lineal puede extenderse a más de una característica al modelar las clases como Gaussianas multivariadas. Además, es posible relajar el supuesto de que las clases comparten una varianza común (o covarianza). Esto conduce a un modelo conocido como análisis discriminante cuadrático (QDA).
En general, los modelos LDA o QDA funcionarán mejor que una regresión logística cuando las características que estamos usando estén más o menos distribuidas como Gaussianas y la regresión logística funcionará mejor en el caso contrario. Una ventaja de modelos como LDA y QDA (o generalizaciones de esta idea) es que puede ser más fácil o más natural incorporar información previa.
Es importante tener en cuenta que los límites de decisión de LDA y QDA pueden ser calculados analíticamente y, por lo tanto, por lo general se calculan de esa manera. Para usar un LDA para dos clases y una característica, solo necesitamos calcular la media de cada distribución y promediar esos dos valores, y obtenemos la decisión de los límites. En el modelo anterior, lo hicimos, pero con un giro Bayesiano. Estimamos los parámetros de las dos Gaussianas y luego insertamos esas estimaciones en una fórmula predefinida.
Regresión de Poisson
Otro modelo lineal generalizado muy popular es la regresión de Poisson. Este modelo asume que los datos se distribuyen de acuerdo con la distribución de Poisson.
Un escenario en el que la distribución de Poisson es útil es cuando se analizan cosas, como la descomposición de un núcleo radioactivo, el número de hijos por pareja o el número de seguidores de Twitter. Lo que todos estos ejemplos tienen en común es que usualmente los modelamos usando números discretos no negativos {0, 1, 2, 3 ...}. Este tipo de variable recibe el nombre de datos de conteo (count data).
La distribución de Poisson
Imagina que estamos contando la cantidad de autos rojos que pasan por una avenida por hora. Podríamos usar la distribución de...
Can you write Python code for it?

mu_params = [0.5, 1.5, 3, 8]
x = np.arange(0, max(mu_params) * 3)
for mu in mu_params:
    y = stats.poisson(mu).pmf(x)
    plt.plot(x, y, 'o-', label=f'μ = {mu:3.1f}')
plt.legend()
plt.xlabel('x')
plt.ylabel('f(x)')
plt.title('Figure 4.10')
plt.savefig('B11197_04_10.png', dpi=300);


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Una forma muy empírica de entender los modelos es cambiar los parámetros y ver qué sucede. En el siguiente bloque de código, calculamos las log-odds en favor de versicolor como $\text {log_odds_versicolor_i} = \alpha + beta_1 x1 + \beta_2 x2$, y luego la probabilidad de versicolor con la función logística. Luego repetimos el cálculo arreglando $x_2$ y aumentando $x_1$ en 1.
Can you write Python code for it?

x_1 = 4.5  # sepal_length
x_2 = 3   # sepal_width

log_odds_versicolor_i = (df['mean'] * [1, x_1, x_2]).sum()
probability_versicolor_i = logistic(log_odds_versicolor_i)

log_odds_versicolor_f = (df['mean'] * [1, x_1 + 1, x_2]).sum()
probability_versicolor_f = logistic(log_odds_versicolor_f)

(f'{log_odds_versicolor_f - log_odds_versicolor_i:.2f}',
 f'{probability_versicolor_f - probability_versicolor_i:.2f}')


I am working on the file "04_Generalizando_modelos_lineales.ipynb".
The first task is:
Y ahora ejecutamos una regresión logística múltiple, tal cual hicimos antes.
Can you write Python code for it?

with pm.Model() as modelo_3:
    α = pm.Normal('α', mu=0, sd=10)
    β = pm.Normal('β', mu=0, sd=2, shape=len(x_n))

    μ = α + pm.math.dot(x_3, β)
    θ = pm.math.sigmoid(μ)
    bd = pm.Deterministic('bd', -α/β[1] - β[0]/β[1] * x_3[:,0])

    yl = pm.Bernoulli('yl', p=θ, observed=y_3)

    trace_3 = pm.sample(1000)


I am working on the file "04_Introduccion_estadistica/01_Tabla_frecuencias_y_medidas.ipynb".
The first task is:
Construcción de tabla de frencuencias
Una de los primeros pasos del análisis descriptivo consiste en la organización de los datos mediante el uso de tablas o estructuras similares. La organización de los datos es fundamental para facilitar el entendimiento y posterior análisis de los datos.
Es común analizar conjuntos de datos con un gran número de registros y cuyo entendimiento se dificulta debido al volumen de los datos. En nuestro caso, la tabla de rutas aéreas contiene más de 66 mil registros.
La tabla de frecuencias o distribución de frecuencias es una manera de organizar los datos en forma de tabla, asignando a cada categoría o rango de valores su frecuencia correspondiente. Se pueden usar tanto variables cuantitativas como cualitativas.
La primera columna contiene el valor único o el rango de valores de la variable en estudio. En nuestro caso, usaremos la variable País de origen para construir la tabla de frencuencias.
La segunda columna contiene la frecuencia absoluta, la cual es el número de veces que aparece un determinado valor en un conjunto de datos. La suma de las frecuencias absolutas es igual al número total de registros.
La tercera columna contiene la frecuencia relativa, la cual es el cuociente entre la frecuencia absoluta de un determinado valor y el número total de datos. La suma de las frecuencias relativas es igual a 1.
Can you write Python code for it?

rutas_pais=pd.value_counts(rutas['Pais_origen']).reset_index()
rutas_pais.columns=['País', 'Frecuencia absoluta']
rutas_pais['Frencuencia relativa']=rutas_pais['Frecuencia absoluta']/rutas_pais['Frecuencia absoluta'].sum()
rutas_pais


I am working on the file "04_Introduccion_estadistica/01_Tabla_frecuencias_y_medidas.ipynb".
The first task is:
El valor promedio de la distancia reocrrida por los vuelos aéreos es 1.824,65 kilómetros.
Calculemos la mediana usando la función median()
Can you write Python code for it?


I am working on the file "04_Introduccion_estadistica/01_Tabla_frecuencias_y_medidas.ipynb".
The first task is:
Lectura de datos
Para este tutorial usaremos la base de datos de vuelos áreos publicada por el sitio web Openflights. En particular, usaremos la tabla de las rutas de vuelos comerciales (rutas.csv).
Más información en https://github.com/jpatokal/openflights
Can you write Python code for it?

rutas_file='data/rutas.csv'
rutas=pd.read_csv(rutas_file)
rutas=rutas.sample(frac=1)

rutas.head()

print("Número de rutas aéreas: ", len(rutas))
print("Número de países: ", len(rutas['Pais_origen'].unique()))


I am working on the file "04_Introduccion_estadistica/01_Tabla_frecuencias_y_medidas.ipynb".
The first task is:
Una vez ordenados los datos de menor a mayor, el percentil 10 es el valor de la variable por debajo del cual se encuentra el 10% de los datos. Para el percentil 50 corresponde al valor que encierra al 50% de los datos, y cuyo valor coincide con la mediana.
Calculemos los cuartiles usando la función percentile() y los valores 25, 50 y 75 que corresponden a los tres cuartiles.
Can you write Python code for it?

np.percentile(rutas['Distancia_km'],25)

np.percentile(rutas['Distancia_km'],50)

np.percentile(rutas['Distancia_km'],75)


I am working on the file "04_Introduccion_estadistica/01_Tabla_frecuencias_y_medidas.ipynb".
The first task is:
Vemos que el primer registro está por debajo del promedio y por ello su desviación es negativa.
Calulemos la varianza usando la función var()
Can you write Python code for it?


I am working on the file "04_Introduccion_estadistica/01_Tabla_frecuencias_y_medidas.ipynb".
The first task is:
Vemos que la varianza del conjunto de datos es bastante alta, pues su valor es 4.050.466,74 $km^2$. Es importante notar que las unidades de varianza son cuadráticas y por ello decimos $km^2$.
Calulemos la desviación típica o desviación estándar usando la función std()
Can you write Python code for it?


I am working on the file "04_Introduccion_estadistica/02_Analisis_de_correlacion.ipynb".
The first task is:
A continuación veremos cómo medir la asociación entre dos variables cuantitativas. Los índices más utilizados en estadística para analizar la intensidad o tamaño del efecto de la relación lineal entre dos variables son la covarianza y el coeficiente de correlación lineal.
Covarianza
La covarianza es un valor que indica el grado de variación conjunta de dos variables aleatorias respecto a sus medias. Es el dato básico para determinar si existe una dependencia entre ambas variables y además es el dato necesario para estimar otros parámetros básicos, como el coeficiente de correlación lineal.
Dadas dos variables estadísticas x e y definiremos la covarianza $S_{xy}$ como:
$S_{xy} = \frac{1}{n} \sum_{i=1}^n (x_i - \overline{x}) (y_i - \overline{y})$
Donde n corresponde al número total de registros, $\overline{x}$ corresponde a la media de la variable x e $\overline{y}$ corresponde a la media de la variable y.
Desarrollando algebraicamente la fórmula de la covarianza se puede llegar a una fórmula que se considera más conveniente, la cual queda expresada como:
$S_{xy} = \frac{1}{n} \big(\sum_{i=1}^n x_i \cdot y_i \big) - \overline{x} \cdot \overline{y}$
Usaremos la funcion cov() de pandas para determinar la covarianza entre algunos campos del conjunto de datos casas. Partiremos analizando la covarianza entre los campos precio_USD y area_m2_util.
Can you write Python code for it?


I am working on the file "04_Introduccion_estadistica/02_Analisis_de_correlacion.ipynb".
The first task is:
El resultado de la función corr() corresponde a una matriz que entrega el coeficiente de correlación entre todas las variables de interés. El valor que nos interesa corresponde a la fila 1 y columna 2 de la matriz, la cual representa la correlación entre los campos precio_USD y area_m2_util.
Podemos notar que el valor del coeficiente de correlación es $0.74$. Este valor es positivo y cercano a uno, por lo cual podemos concluir que existe una relación directa entre ambas variables y su correlación es muy alta.
Analicemos la covarianza entre las columnas precio_USD y año_construida.
Can you write Python code for it?


I am working on the file "04_Introduccion_estadistica/02_Analisis_de_correlacion.ipynb".
The first task is:
El resultado de la función cov() corresponde a una matriz que entrega la covarianza entre todas las variables de interés. El valor que nos interesa corresponde a la fila 1 y columna 2 de la matriz, la cual representa la covarianza entre los campos precio_USD y area_m2_util.
Podemos notar que el valor de la covarianza es $9.07 \times 10^6$. Este valor es positivo y mucho mayor que cero, por lo cual podemos concluir que existe una dependencia directa o positiva entre ambas variables.
Analicemos la covarianza entre las columnas precio_USD y año_construida.
Can you write Python code for it?


I am working on the file "04_Introduccion_estadistica/02_Analisis_de_correlacion.ipynb".
The first task is:
En general, la manera más rapida de verificar si existe una relación entre variables es mediante el uso de visualizaciones. La visualización más empleada para este caso es el gráfico de puntos, el cual permite rápidamente ver la existencia de alguna relación.
Supongamos que queremos ver si existe alguna relación entre las variables precio_USD y area_m2_util del conjunto de datos casas. Para ello usamos la función plot.scatter() de la librería pandas.
Can you write Python code for it?

casas.plot.scatter(x='area_m2_util', y='precio_USD', s=3);
plt.xlabel('Área en metros cuadrados')
plt.ylabel('Precio de casa (USD)')
plt.title('Análisis de relación entre precio y área')


I am working on the file "04_MachineLearning.ipynb".
The first task is:
Now, we use a DecisionTree to learn a model and test our result
Can you write Python code for it?

from sklearn.tree import DecisionTreeClassifier

instance = DecisionTreeClassifier()
r = instance.fit(data_train, target_train)
target_predict = instance.predict(data_test)

from sklearn.metrics import accuracy_score
print('Prediction accuracy: ',accuracy_score(target_predict, target_test))


I am working on the file "04_MachineLearning.ipynb".
The first task is:
pretty good, isn't it?
Dimension Reduction using MDS and PCA
if we go back to our K-Means example, the clustering doesn't really make sense. However, we are just looking at two out of four dimensions. So, we can't really see the real distances/similarities between items. Dimension reduction techniques reduce the number of dimensions, while preserving the inner structure of the higher dimensions. We take a look at two of them: Multi Dimensional Scaling (MDS) and Principal Component Analysis (PCA).
Can you write Python code for it?

from sklearn import manifold

#create mds instance
mds = manifold.MDS(n_components=2, random_state=5)

#fit the model and get the embedded coordinates
pos = mds.fit(data.data).embedding_

plt.scatter(pos[:, 0], pos[:, 1], s=20, c=[colors[i] for i in data.target])

#create a legend since we just have one plot and not three fake the legend using patches
import matplotlib.patches as mpatches
patches = [ mpatches.Patch(color=colors[i], label=data.target_names[i]) for i in range(3) ]
plt.legend(handles=patches)
plt.legend()

#compare with e.g. PCA

from sklearn import decomposition

pca = decomposition.PCA(n_components=2)
pca_pos = pca.fit(data.data).transform(data.data)

mds_pos = mds.fit(data.data).embedding_

plt.figure(figsize=[20,7])
plt.subplot(121)
plt.scatter(mds_pos[:, 0], mds_pos[:, 1], s=30, c=[colors[i] for i in data.target])
plt.title('MDS')

plt.subplot(122)
plt.scatter(pca_pos[:, 0], pca_pos[:, 1], s=30, c=[colors[i] for i in data.target])
plt.title('PCA')


I am working on the file "04_MachineLearning.ipynb".
The first task is:
seems like versicolor and virginicia are more similar then setosa
TASK

create an interactive colored plot of the Iris dataset projected in 2D using MDS. The color should correspong to the result of a K-Means clusterin alrogithm where the user can interactivly define the number of clusters between 1 and 10.
Can you write Python code for it?

from IPython.html.widgets import interact
colors = sns.color_palette(n_colors=10)


I am working on the file "04_MachineLearning_solution.ipynb".
The first task is:
Now, we use a DecisionTree to learn a model and test our result
Can you write Python code for it?


I am working on the file "04_MachineLearning_solution.ipynb".
The first task is:
Unsupervised Clustering using K-Means
Can you write Python code for it?

#disable some annoying warning
import warnings
warnings.filterwarnings('ignore', category=FutureWarning)

%matplotlib inline
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

#load the iris datasets
import sklearn.datasets

data = sklearn.datasets.load_iris()
data.data.shape

from sklearn.cluster import KMeans
iris_pred = KMeans(n_clusters=3, random_state = 102).fit_predict(data.data)

plt.figure(figsize=(12, 12))

colors = sns.color_palette()

plt.subplot(211)
plt.scatter(data.data[:, 0], data.data[:, 1], c=[colors[i] for i in iris_pred], s=40)
plt.title('KMeans-3 clusterer')
plt.xlabel(data.feature_names[0])
plt.ylabel(data.feature_names[1])

plt.subplot(212)
plt.scatter(data.data[:, 0], data.data[:, 1], c=[colors[i] for i in data.target],s=40)
plt.title('Ground Truth')
plt.xlabel(data.feature_names[0])
plt.ylabel(data.feature_names[1])


I am working on the file "04_MachineLearning_solution.ipynb".
The first task is:
pretty good, isn't it?
Dimension Reduction using MDS and PCA
if we go back to our K-Means example, the clustering doesn't really make sense. However, we are just looking at two out of four dimensions. So, we can't really see the real distances/similarities between items. Dimension reduction techniques reduce the number of dimensions, while preserving the inner structure of the higher dimensions. We take a look at two of them: Multi Dimensional Scaling (MDS) and Principal Component Analysis (PCA).
Can you write Python code for it?


I am working on the file "04_MachineLearning_solution.ipynb".
The first task is:
seems like versicolor and virginicia are more similar then setosa
TASK

create an interactive colored plot of the Iris dataset projected in 2D using MDS. The color should correspong to the result of a K-Means clusterin alrogithm where the user can interactivly define the number of clusters between 1 and 10.
Can you write Python code for it?

from IPython.html.widgets import interact
colors = sns.color_palette(n_colors=10)

mds_pos = mds.fit(data.data).embedding_

@interact(n_clusters=(1,10))
def draw_plot(n_clusters):
    instance = KMeans(n_clusters=n_clusters, random_state = 102)
    clusters_assignment = instance.fit_predict(data.data)
    plt.scatter(mds_pos[:, 0], mds_pos[:, 1], s=20, c=[colors[i] for i in clusters_assignment])


I am working on the file "04_NB_IntroductionVTKPython.ipynb".
The first task is:
Further exploration: Notebook example using this module here
Task: Use this module to build the pipeline in section 2 stepwise, try changing parameters, sources, etc.
Embedding VTK Renders in Jupyter Notebook
Can you write Python code for it?

# Original source: http://nbviewer.jupyter.org/gist/certik/5723420
# An explained version of this code: https://pyscience.wordpress.com/2014/09/03/ipython-notebook-vtk/

import vtk
from IPython.display import Image
def vtk_show(renderer, width=400, height=300):
    """
    Takes vtkRenderer instance and returns an IPython Image with the rendering.
    """
    renderWindow = vtk.vtkRenderWindow()
    renderWindow.SetOffScreenRendering(1)
    renderWindow.AddRenderer(renderer)
    renderWindow.SetSize(width, height)
    renderWindow.Render()

    windowToImageFilter = vtk.vtkWindowToImageFilter()
    windowToImageFilter.SetInput(renderWindow)
    windowToImageFilter.Update()

    writer = vtk.vtkPNGWriter()
    writer.SetWriteToMemory(1)
    writer.SetInputConnection(windowToImageFilter.GetOutputPort())
    writer.Write()
    data = bytes(memoryview(writer.GetResult()))

    return Image(data)

vtkSourceSphere = vtk.vtkSphereSource()
vtkSourceSphere.SetCenter(0.0, 0.0, 0.0)
vtkSourceSphere.SetRadius(10.0)
vtkSourceSphere.SetPhiResolution(10)
vtkSourceSphere.SetThetaResolution(10)

vtkMapperSphere = vtk.vtkPolyDataMapper()
vtkMapperSphere.SetInputConnection(vtkSourceSphere.GetOutputPort())

vtkActorSphere = vtk.vtkActor()
vtkActorSphere.SetMapper(vtkMapperSphere)
vtkActorSphere.GetProperty().SetColor(1.0, 0.0, 0.0)

vtkRenderer = vtk.vtkRenderer()
vtkRenderer.SetBackground(1.0, 1.0, 1.0)
vtkRenderer.AddActor(vtkActorSphere)

vtk_show(vtkRenderer, width=500, height=500)


I am working on the file "04_Parsing_Dynamic_Properties_into_Traits.ipynb".
The first task is:
How much more information might we be able to find in records that records that are not JSON parsable?
Can you write Python code for it?

(idb_triples
 .select(length(col("key")).alias("len_key"))
 .avg(col("len_key"))
 .show()
)

#joined = idb_dyn.join(idb_triples, idb_dyn["uuid"] == idb_triples["uuid"], "inner")

#joined.show(3, truncate=False)

#joined.count()


I am working on the file "04_Parsing_Dynamic_Properties_into_Traits.ipynb".
The first task is:
Need a udf that returns a mapType of string:string that explode will expand
Can you write Python code for it?

def json_to_map(s):
    """Convert a string containing JSON into a dictionary,
    Skip flattening for now."""
    try:
        return json.loads(s)
    except:
        return {}

json_to_map_udf = udf(json_to_map, MapType(StringType(), StringType()))

print(json_to_map('{ "solr_long_lat": "-5.87403,30.49728", "related_record_types": "PreservedSpecimen|PreservedSpecimen", "related_record_links": "YPM-IP-530950|YPM-IP-530951" }'))

idb_map = (idb_dyn
 .withColumn("props_map", json_to_map_udf(col("props_str")))
)
idb_map.select(col("props_map")).show(10, truncate=False)

idb_triples = (idb_map
 .select(col("uuid"),
         col("recordset"),
         col("institutioncode"),
         explode(col("props_map")).alias("key", "value"))
)
idb_triples.cache()

idb_triples.count()

idb_triples.show(20, truncate=False)

(idb_triples
 .groupBy(col("key"))
 .count()
 .sort(col("count"), ascending=False)
 .limit(1000)
 ).toPandas()

(idb_triples
 .groupBy(col("institutioncode"))
 .count()
 .sort(col("count"), ascending=False)
 .limit(1000)
 ).toPandas()

(idb_triples
 .filter(col("key") == "NSF_TCN")
 .count()
)

(idb_triples
 .filter(col("key") == "NSF_TCN")
 .groupBy(col("institutioncode"), col("value"))
 .count()
 .sort(col("count"), ascending=False)
 .limit(1000)
 ).toPandas()


I am working on the file "04_Parsing_Dynamic_Properties_into_Traits.ipynb".
The first task is:
Now let's write this out and go back and join to the main DF for some summaries
Can you write Python code for it?

#(idb_triples
# .write
# .parquet("/tmp/idigbio-20171014T023306-json-triples.parquet")
#)


I am working on the file "04_PredictiveAnalytics.ipynb".
The first task is:
1. Data acquisition
First, let's acquire the data formated in '02_data_preparation.ipynb'. The figure below gives a glimpse of what the data set looks like.
Can you write Python code for it?

%%time
# reads all predefined months for a year and merge into one data frame
rawData2014 = pd.DataFrame.from_csv('cache/predictionData/complete2014Data.csv')

print rawData2014.columns
rawData2014.head(5)


I am working on the file "04_PredictiveAnalytics.ipynb".
The first task is:
2. Random forest classifier
We will make prediction on the variable 'ARR_DEL15'. This variable takes the value 1 is the plane is more than 15 minutes late and 0 if not. Let's look at the baseline classifier, that is the classifiers that assign repectively 1 or 0 to 'ARR_DEL15' for every flight.
Here we look at the case whether a flight will be more than 15 minutes late. So we adjust the ARR_DELAY colum to an indicator.
Can you write Python code for it?

%%time
dexample['ARR_DELAY_COR'] = dexample.ARR_DELAY.map(lambda x: (x >= 15))
dexample.drop('ARR_DELAY', axis = 1, inplace = True)
file_path = "cache/predictionData/dexample_class.csv"
dexample.to_csv(path_or_buf= file_path)
dexample_class = dexample.copy()

#file_path = "cache/predictionData/dexample_class.csv"
#dexample_class = pd.read_csv(path_or_buf= file_path)
#dexample_class.drop('Unnamed: 0', axis= 1, inplace = True)

dexample_class.head(3)

from __future__ import division

def baseline_class(data, target):
    '''
    Compute the baseline classifiers along a target variable for a data set data

    Parameters:
    -----------

    data: pandas.DataFrame
       dataframe

    target: string
        Column of data along wich we compute the baseline classifiers
    '''

    score_baseline_1 = np.size(data[data[target] == 1][target].values) / np.size(data[target].values)
    score_baseline_0 = np.size(data[data[target] == 0][target].values) / np.size(data[target].values)

    print "baseline classifier everyone to 0: ", int(score_baseline_0*100) , "%"
    print "baseline classifier everyone to 1: ", int(score_baseline_1*100) , "%"

    return score_baseline_0, score_baseline_1

baseline_class(dexample_class, 'ARR_DELAY_COR')