I am working on the file "06-Literary Distinction (Probably)/Literary Patterns (Probably).ipynb".
The first task is:
3. Classification
Training, Feature Importance, and Prediction
Long and So selected a classification algorithm that specifically relies on Bayes' Theorem to model relationships between textual features and categories in our corpus of poetry volumes. (See link for more information about the method and its assumptions.)
Two ways that we learn about the model are its feature weights and predictions on new texts. The algorithm can explicity report to us which direction each word leans category-wise and how strongly. Based on those weights, it makes further predictions about the valences of previously unseen poetry volumes.
Can you write Python code for it?

from sklearn.naive_bayes import MultinomialNB

# Train the classifier and assign it to a variable

nb = MultinomialNB()
nb.fit(dtm, all_labels)

# Hand-waving the underlying statistics here...

def most_informative_features(text_class, vectorizer = cv, classifier = nb, top_n = 10):

    import numpy as np

    feature_names = vectorizer.get_feature_names()
    class_index = np.where(classifier.classes_==(text_class))[0][0]

    class_prob_distro = np.exp(classifier.feature_log_prob_[class_index])
    alt_class_prob_distro = np.exp(classifier.feature_log_prob_[1 - class_index])

    odds_ratios = class_prob_distro / alt_class_prob_distro
    odds_with_fns = sorted(zip(odds_ratios, feature_names), reverse = True)

    return odds_with_fns[:top_n]

# Returns feature name and odds ratio for a given class

most_informative_features('reviewed')

# Similarly, for words that indicate 'random' class membership

most_informative_features('random')

# Let's load up two poems that aren't in the training set and make predictions

dickinson_canonic = """Because I could not stop for Death –
He kindly stopped for me –
The Carriage held but just Ourselves –
And Immortality.

We slowly drove – He knew no haste
And I had put away
My labor and my leisure too,
For His Civility –

We passed the School, where Children strove
At Recess – in the Ring –
We passed the Fields of Gazing Grain –
We passed the Setting Sun –

Or rather – He passed us –
The Dews drew quivering and chill –
For only Gossamer, my Gown –
My Tippet – only Tulle –

We paused before a House that seemed
A Swelling of the Ground –
The Roof was scarcely visible –
The Cornice – in the Ground –

Since then – ‘tis Centuries – and yet
Feels shorter than the Day
I first surmised the Horses’ Heads
Were toward Eternity – """

anthem_patriotic = """O! say can you see, by the dawn's early light,
What so proudly we hailed at the twilight's last gleaming,
Whose broad stripes and bright stars through the perilous fight,
O'er the ramparts we...


I am working on the file "06-Literary Distinction (Probably)/Literary Patterns (Probably).ipynb".
The first task is:
Extra: Cross-Validation
Just how good is our classifier? We can evaluate it by randomly selecting texts from each category and setting them aside before training. We then see how well the classifier predicts their (known) categories.
Remember that if the classifier is trying to predict membership for just two categories, we would expect it to be correct about 50% of the time based on random chance. As a rule of thumb, if this kind of classifier has 65% accuracy or better under cross-validation, it has often identified a meaningful pattern.
Can you write Python code for it?

# Randomize the order of our texts
import numpy
randomized_review = numpy.random.permutation(review_texts)
randomized_random = numpy.random.permutation(random_texts)

# We'll train our classifier on the first 90% of texts in the randomized list
# Then, we'll test it using the last 10%

training_set = list(randomized_review[:324]) + list(randomized_random[:324])
test_set = list(randomized_review[324:]) + list(randomized_random[324:])

training_labels = ['reviewed'] * 324 + ['random'] * 324
test_labels = ['reviewed'] * 36 + ['random'] * 36

# Transform training and test texts into DTMs
# Note that 'min_df' has been adjusted to one quarter of the size of the training set

from sklearn.feature_extraction.text import CountVectorizer

cv = CountVectorizer(stop_words = 'english', min_df = 162, binary=True)
training_dtm = cv.fit_transform(training_set)
test_dtm = cv.transform(test_set)

# Train, Predict, Evaluate

from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import accuracy_score

nb = MultinomialNB()
nb.fit(training_dtm, training_labels)
predictions = nb.predict(test_dtm)
accuracy_score(predictions, test_labels)

## CHALLENGE: In fact, when Underwood and Sellers cross-validate, they do so by setting aside a single
##            author's texts (one or more) from the training set and making a prediction for that author alone.
##            After doing this for all authors, they tally the number of texts that were correctly predicted
##            to calculate their overall accuracy. Implement this.


I am working on the file "06-Literary Distinction (Probably)/Literary Patterns (Probably).ipynb".
The first task is:
Feature Selection
At this point, we transform our texts into a Document-Term Matrix in the same manner we have employed previously. However, it is important to note that neither Long and So nor Underwood and Sellers use all of the words that appear in their respective corpora when constructing their matrices. The process of choosing which words to comprise the columns is referred to as feature selection.
While there are several approaches one may take when selecting features, both of the literary studies under consideration use document frequency as the deciding criterion. The intuition is that a word that appears in a single text out of hundreds will not carry much weight when trying to determine the text's class membership.
In order to be selected as a feature, Long and So require that words appear in at least 2 texts, whereas Underwood and Sellers require that a word appear in about a quarter of all texts. Although this is quite a large difference (a minimum of 2 texts vs. ~180 texts), it perhaps makes sense since the texts are of very different lengths: individual haiku vs entire volumes of poetry. The latter will have much greater overlap in its vocabulary.
The process of feature selection is intimately tied to the object under study and the statistical model chosen.
Can you write Python code for it?

from sklearn.feature_extraction.text import CountVectorizer

# Intitialize the function that will transform our list of texts to a DTM
# 'min_df' and 'max_features' are arguments that enable flexible feature selection
# 'binary' tells CountVectorizer only to record whether a word appeared in a text or not

cv = CountVectorizer(stop_words = 'english', min_df=180, binary = True, max_features = None)

# Transform our texts to DTM

cv.fit_transform(all_texts)

# Transform our texts to a dense DTM

cv.fit_transform(all_texts).toarray()

# Assign this to a variable

dtm = cv.fit_transform(all_texts).toarray()

# Get the column headings

cv.get_feature_names()

# Assign to a variable

feature_list = cv.get_feature_names()

# Place this in a dataframe for readability

dtm_df = pandas.DataFrame(dtm, columns = feature_list, index = all_file_names)

# Check out the dataframe

dtm_df

# Get the dataframe's dimensions (# texts, # features)

dtm_df.shape

## EX. Re-initialize the CountVectorizer function above with the the argument min_df = 1.
##     How many unique words are in there in the total vocabulary of the corpus?

## EX. Repeat the exercise above with min_df = 360. (That is, words are only included if they appear
##     in at least half of all documents.) What is the size of the vocabulary now?
##     Does the list of these very common words look as you would expect?


I am working on the file "06-Literary Distinction (Probably)/Literary Patterns (Probably).ipynb".
The first task is:
Stop Words
Stop words, sometimes refered to as function words, include articles, prepositions, pronouns, and conjunctions among others. Although their frequencies encode information about textual features like authorship, they do not convey semantic meanings and are often removed before analysis.
Can you write Python code for it?

# By default scikit-learn uses this list of English stop words

from sklearn.feature_extraction.text import ENGLISH_STOP_WORDS

# Inspect

ENGLISH_STOP_WORDS

# How many are here?

len(ENGLISH_STOP_WORDS)

# NLTK has its own collection of stop words

from nltk.corpus import stopwords

# Pull up NLTK's list of English-language stop words

stopwords.words('english')

# How many stop words are in the list?

len(stopwords.words('english'))

# NLTK has stopwords for many Western languages

stopwords.words('spanish')

tokenized_sentence = ['what', 'is', 'the', 'air-speed', 'velocity', 'of', 'an', 'unladen', 'swallow']

# Remove stopwords from tokenized sentence

[word for word in tokenized_sentence if word not in stopwords.words('english')]

## Q.  Stop words are typically the most frequent words in a language, yet do not convey semantic meaning.
##     Does this make sense based on the words in NLTK's list of English stop words?
##     What about other languages with which you are familar?

stopword_languages = ['danish', 'dutch', 'english', 'finnish', 'french', 'german', 'hungarian', 'italian',\
                      'norwegian', 'portuguese', 'russian', 'spanish', 'swedish', 'turkish']

## EX. Use either sklearn or NLTK's stopword list to remove those words from the 'token_list' below.

## EX. How many tokens did you remove from the 'token_list' in total? What percent were removed?

## CHALLENGE.  Stop words are often instrumental in language detection for unknown texts.
##             How might you write a program to do this?

token_list = ['in', 'a', 'station', 'of', 'the', 'metro',\
              'the', 'apparition', 'of', 'these', 'faces', 'in', 'the', 'crowd',\
              'petals', 'on', 'a', 'wet', 'black', 'bough']


I am working on the file "06-Network-Analysis/01-Network-Analysis.ipynb".
The first task is:
All ones?
Can you write Python code for it?


I am working on the file "06-Network-Analysis/01-Network-Analysis.ipynb".
The first task is:
Challenge
What is the overlap ((rank) correlation) between the three measurements presented above? What does that mean for the play?
Bonus: Making a prettier graph
matplotlib isn't always the most beautiful option. A popular way of visualizing networks is by using Javascript's D3 library. Luckily, networkx allows us to export the network information to JSON:
Can you write Python code for it?

from networkx.readwrite import json_graph
import json

d3_data = json_graph.node_link_data(G)
d3_data


I am working on the file "06-Network-Analysis/01-Network-Analysis.ipynb".
The first task is:
Gini Coefficient
Algee-Hewitt was calculating the gini coefficient of the eigenvector centralities. He essentially wanted to know whether importance in a network was evenly distributed, or concentrated in the hands of a few. The lower the gini coefficient, the more equal the distribution, the closer to 1, the closer one gets to complete inequality. I've found a function online that will calculate the gini coefficient for you!
Can you write Python code for it?

def gini(array):
    """Calculate the Gini coefficient of a numpy array."""
    # https://github.com/oliviaguest/gini
    array = np.sort(array) # values must be sorted
    index = np.arange(1, array.shape[0] + 1) # index per array element
    n = array.shape[0] # number of array elements
    return ((np.sum((2 * index - n  - 1) * array)) / (n * np.sum(array))) #Gini coefficient


I am working on the file "06-Network-Analysis/01-Network-Analysis.ipynb".
The first task is:
Great start! In Network Analysis there are two fundamental principles. A node is an entity, it can have relationships with other entities. In literature, this is often a character, but it could be a Twitter user, organization, geographic location, or even words!
We may be interested in a node's properties. If it's a character, we may want to know how often they speak, age, etc. We can add this to the network as further layers.
The second concept is an edge. An edge connects nodes. We're foremost interested in the volume of connections between nodes. For literature, this would be the number of times two characters interact.
As we learned from Moretti and our readings for today, this is a very difficult task for most texts. Where does on character's speech end and another's begin? Luckily, in plays this is slightly easier to identify (though still not perfectly clear).
For Shakespeare, we'll settle for them being present in the same scene. If they're in the same scene together, we'll increase our measure of their interaction.
Thus for each character we want to know how many lines the speak in the entire play, along with which scenes they appear in. We can then collate this wil the other characters.
The get_cast_dict function below will parse the XML data and extract this information.
Can you write Python code for it?

cast_dict = {}
for c in set([e.text for e in all_elements if e.tag == "speaker"]):
    cast_dict[c] = {"num_lines": 0,
                    "scenes": []}

cast_dict

# extract all scene elements from the xml
scenes = [e for e in all_elements if e.tag == "scene"]
scenes

elements = [e.find("acttitle").text for e in all_elements if e.tag == "act"]

def get_cast_dict(all_elements):
    '''
    returns a dictionary with the total number of lines and scenes a character appears in
    '''

    cast_dict = {}

    # first get a unique set of all characters appearing in the play
    for c in set([e.text for e in all_elements if e.tag == "speaker"]):
        cast_dict[c] = {"num_lines": 0,
                        "scenes": []}

    # extract all scene elements from the xml
    scenes = [e for e in all_elements if e.tag == "scene"]
    acts = [e for e in all_elements if e.tag == "act"]
    # acts = [e.find("acttitle").text for e in all_elements if e.tag == "act"]

    for a in acts:

        # get title of acts
        act_title = a.find("acttitle").text

        # get scene elements
        scenes = [e for e in a if e.tag == "scene"]
        # iterate through each scene
        for sc in scenes:

            # grab all the speeches in the scene
            speeches = [s for s in sc.getchildren() if s.tag == "speech"]

            # iterate through speeches
            for s in speeches:

                # increment number of lines for the speaker
                cast_dict[s.find("speaker").text]["num_lines"] += len(s.findall("line"))

            # find all the speaker for each speech
            speakers = [s.find("speaker").text for s in speeches]

            # add the title of the scene for each speaker appearing in the scene
            for s in set(speakers):
                cast_dict[s]["scenes"].append(act_title + " " + sc.find("scenetitle").text)

        # reassign scenes to only a unique set
        for c in cast_dict.keys():
            cast_dict[c]["scenes"] =...


I am working on the file "06-Network-Analysis/01-Network-Analysis.ipynb".
The first task is:
Great, but that's not terribly interesting itself, we want to see how it relates to other plays. We'll do that for homework.
First, let's write a function to calculate Algee-Hewitt's second measure. He takes the percentage of characters in the top quartile of eigenvector centralities. You'll want to use the np.percentile method!
Challenge
Can you write Python code for it?

def percentage_top_quartile(character_table):
    # YOUR CODE HERE

    return percentage

percentage_top_quartile(network_tab['Eigenvector Centrality'])


I am working on the file "06-Network-Analysis/01-Network-Analysis.ipynb".
The first task is:
If we're trying to build a network we need two things: 1) nodes and 2) edges. For Algee-Hewitt, and for us today, that means we need to know the characters in Othello, and with whom they communicate. We'd also like to know how often that specific interaction occurs.
We can get all elements of the XML tree by iterating over all the nodes:
Can you write Python code for it?

all_elements = list(othello_xml.iter())
all_elements


I am working on the file "06-Network-Analysis/01-Network-Analysis.ipynb".
The first task is:
Just to demonstrate, let's make a very unequal array:
Can you write Python code for it?


I am working on the file "06-Network-Analysis/01-Network-Analysis.ipynb".
The first task is:
Now we can use the gini function on Othello to see how evenly distributed centrality is:
Can you write Python code for it?

import numpy as np
gini(network_tab['Eigenvector Centrality'])


I am working on the file "06-Network-Analysis/01-Network-Analysis.ipynb".
The first task is:
That's all we need to make a basic network and do some analysis! We have all the character names and the scenes in which they appear. We can collate some of this information to find out in which scenes certain characters appear together. This will happen in our make_graph function.
The NetworkX Python library will parse this dictionary for us to make a graph object. Let's write a function:
Can you write Python code for it?

def make_graph(c_dict):
    '''
    This function accepts a dictionary with number of lines and scenes to create a
    NetworkX graph object
    '''
    # setup graph object
    G = nx.Graph()

    # add nodes with attributes of number of lines and scenes
    for c in c_dict.keys():
        if c_dict[c]["num_lines"] > 0:
            G.add_node(
                c,
                number_of_lines=c_dict[c]["num_lines"],
                scenes=c_dict[c]["scenes"]
            )

    # make edges by iterating over all combinations of nodes
    for (node1, data1), (node2, data2) in itertools.combinations(G.nodes(data=True), 2):

        # count scenes together by getting union of their sets
        scenes_together = len(set(data1['scenes']) & set(data2['scenes']))

        if scenes_together:
            # add more weight for more scenes together
            G.add_edge(node1, node2, weight=scenes_together)

    return G

G = make_graph(cast_dict)


I am working on the file "06-Network-Analysis/01-Network-Analysis.ipynb".
The first task is:
The gini coefficient should be close to 1:
Can you write Python code for it?


I am working on the file "06-Network-Analysis/01-Network-Analysis.ipynb".
The first task is:
To get a unique list we'll use set:
Can you write Python code for it?

set([e.text for e in all_elements if e.tag == "speaker"])


I am working on the file "06-Network-Analysis/01-Network-Analysis.ipynb".
The first task is:
We can graph this using matplotlib:
Can you write Python code for it?

# nodes should be sized by number of lines
node_size = [data['number_of_lines'] for __, data in G.nodes(data=True)]
node_color = 'blue'

plt.figure(figsize=(13,8))  # make the figure size a little larger
plt.axis('off')  # remove the axis, which isn't meaningful in this case
plt.title("Othello's Social Network", fontsize=20)

# The 'k' argument determines how spaced out the nodes will be from
# one another on the graph.
pos = nx.spring_layout(G, k=0.5)

nx.draw_networkx(
    G,
    pos=pos,
    node_size=node_size,
    node_color=node_color,
    edge_color='gray',  # change edge color
    alpha=0.3,  # make nodes more transparent to make labels clearer
    font_size=14,
)


I am working on the file "06-Network-Analysis/01-Network-Analysis.ipynb".
The first task is:
What if we have half zeroes and half ones?
Can you write Python code for it?


I am working on the file "06-Network-Analysis/01-Network-Analysis.ipynb".
The first task is:
Wikipedia defines "betweeness centrality":

Betweenness is a centrality measure of a vertex within a graph (there is also edge betweenness, which is not discussed here). Betweenness centrality quantifies the number of times a node acts as a bridge along the shortest path between two other nodes.
Can you write Python code for it?

bc = [x[1] for x in sorted(nx.betweenness_centrality(G).items(), key=lambda x: x[0])]
network_tab.append_column(label="Betweenness Centrality", values=bc)
network_tab.show()


I am working on the file "06-Network-Analysis/01-Network-Analysis.ipynb".
The first task is:
Wikipedia defines "eigenvector centrality":

Eigenvector centrality (also called eigencentrality) is a measure of the influence of a node in a network. It assigns relative scores to all nodes in the network based on the concept that connections to high-scoring nodes contribute more to the score of the node in question than equal connections to low-scoring nodes.
$x_v = \frac{1}{\lambda} \sum_{t \in M(v)}x_t = \frac{1}{\lambda} \sum_{t \in G} a_{v,t}x_t$
Can you write Python code for it?

ec = [x[1] for x in sorted(nx.eigenvector_centrality(G).items(), key=lambda x: x[0])]
network_tab.append_column(label="Eigenvector Centrality", values=ec)
network_tab.show()


I am working on the file "06-Petlje.ipynb".
The first task is:
Isto se može postići korišćenjem petlje <i>while</i>.
Can you write Python code for it?

columns = ["A", "B", "C", "D", "E", "F", "G", "H"]
rows = [1, 2, 3, 4, 5, 6, 7, 8]

# The length of the lists
len_c = len(columns)
len_r = len(rows)

# Initialize the column counter
cnt_c = 0

while cnt_c < len_c:
    # Initialize the row counter
    # The row counter needs to be re-initialized to zero each time
    # we move to a new column. That's why we t inside the column loop
    cnt_r = 0

    while cnt_r < len_r:
        # Print a column-row combination
        #
        # Set print function's optional argumnt end to an
        # empty string to avoid going to a new line after each print
        print("%s%s " % (columns[cnt_c], rows[cnt_r]), end="")

        # Increment the row counter
        cnt_r += 1

    # Increment the columnt counter
    cnt_c += 1

    # After each printed rown, print a newline to make it look like a chess board
    print("\n")


I am working on the file "06-Petlje.ipynb".
The first task is:
Iteriranje petljom <i>while</i>
Can you write Python code for it?

my_str = "My string"

# Initialize counter
cnt = 0

while cnt < len(my_str):
    print("Character number %d is %s" % (cnt, my_str[cnt]))
    cnt += 1


I am working on the file "06-Petlje.ipynb".
The first task is:
Korišćenjem uglastih zagrada možemo promeniti sadržaj liste, odnosno vrednost nekog njenog elementa.
Can you write Python code for it?

my_list = [100, 200, 300, 400, 500, 600, 700, 800]

my_list[3] = -1

print(my_list) # The print function can take a list as an argument and print out all of its elements


I am working on the file "06-Petlje.ipynb".
The first task is:
Možemo joj proslediti i dva argumenta, koje će ona tumačiti kao početni i krajnji broj u intervalu zatvorenom s leve strane (prvi broj pripada intervalu, dok poslednji broj ne pripada intervalu).
Can you write Python code for it?

for i in range(8, 13): # 8 included, 13 not included
    print(i)


I am working on the file "06-Petlje.ipynb".
The first task is:
Neke operacije nad listama
Za pristupanje elementu liste koriste se uglaste zagrade. Između uglastih zagrada navodi se pozicija elementa kojem želimo da pristupimo - njegov indeks. U listi od N elemenata, prvom elementu liste odgovara indeks 0 (nula), a poslednjem - indeks N - 1.
Can you write Python code for it?

# Prints the ith element of a list of integers
def print_ith_element(input_list, i):
    print("The %dth element of the list is %d" % (i, input_list[i]))

# Define a list
my_list = [10, 20, 30, 40, 50]

# Print out a few elements of the list
print_ith_element(my_list, 0)
print_ith_element(my_list, 2)
print_ith_element(my_list, 4)


I am working on the file "06-Petlje.ipynb".
The first task is:
Petlja for
Još jedan tip petlje u Pajtonu je petlja for, koja se realizuje korišćenjem ključnih reči for i in. Sledi primer u kojem se na ekranu štampaju prirodni brojevi od 1 do 10, kao u prvom primeru petlje while.
Osim ključnih reči for i in, još nešto što koristimo kod petlji tipa for jeste tip podataka koji se naziva listom (eng. list). Lista se obeležava otvorenom uglastom zagradom, listom njenih elemenata razdvojenih zapetama i zatvorenom uglastom zagradom, tim redosledom. Listom zadajemo vrednosti kroz koje petlja prolazi u svojim ponavljanjima - u svakom ponavljanju Pajton će uzimati naredni unos iz liste. Ovakav način rada petlje for razlikuje se od tradicionalnih programskih jezika, i više liči na ono što se naziva for each ili foreach u mnogim programskim jezicima koji su u vreme nastajanja Pajtona bili popularni.
Can you write Python code for it?


I am working on the file "06-Petlje.ipynb".
The first task is:
Realizovaćemo istu funkcionalnost iz prethodnog primera na drugačiji način, tako što ćemo štampanje prvog i poslednjeg reda izmestiti iz petlje. Prvi red ćemo štampati pre petlje, a poslednji posle petlje.
Can you write Python code for it?

# Obtain the required number of passes from the user
num_passes = int(input("How many rows would you like printed?\n"))

# Print the first row BEFORE entering the loop
print("Here is the first row.")

# Initialize the counter to 2, because the first row has already been printed
i = 2

# Print the "middle rows" - all rows except the first and the last one
while (i <= num_passes - 1):
    print("Here is another row.")
    i += 1

# Print the last row AFTER finishing the loop
print("Here is the last (%dth) row." % i)


I am working on the file "06-Petlje.ipynb".
The first task is:
U sledećem primeru, broj ponavljanja zavisiće od broja koji korisnik unese s tastature, a prvi i poslednji prolazak kroz petlju razlikovaće se od ostalih.
Can you write Python code for it?

# Obtain the required number of passes from the user
num_passes = int(input("How many rows would you like printed?\n"))

# Initialize the counter
i = 1

# Loop and print the required number of rows
while i <= num_passes:
    if (1 == i):
        print("Here is the first row.")
    elif (num_passes == i):
        print("Here is the last (%dth) row." % i)
    else:
        print("Here is another row.")

    # Increment the counter inside the loop
    i += 1 # "i += x" is equivalent to "i = i + x"


I am working on the file "06-Petlje.ipynb".
The first task is:
Ugnježdene petlje
U telu petlje mogu se naći bilo koje instrukcije koje Pajton prepoznaje, pa se tako može naći i zaglavlje nove petlje. Ovo se naziva ugnježdenim petljama. Sledeći primer prikazaće sva polja na šahovskoj tabli. Polje na šahovskoj tabli određeno je kolonom i redom. Kolone se obeležavaju slovima od A do H, a redovi brojevima od 1 do 8.
Can you write Python code for it?

columns = ["A", "B", "C", "D", "E", "F", "G", "H"]
rows = [1, 2, 3, 4, 5, 6, 7, 8]

for c in columns:
    for r in rows:
        # Print a column-row combination
        #
        # Set print function's optional argumnt end to an
        # empty string to avoid going to a new line after each print
        print("%s%s " % (c, r), end="")

    # After each printed rown, print a newline to make it look like a chess board
    print("\n")


I am working on the file "06-Petlje.ipynb".
The first task is:
Ukoliko funkciji <i>range</i> prosledimo tri argumenta, ona će prvi tumačiti kao početak, a drugi kao kraj intervala zatvorenog s leve strane. Treći argument je korak kojim će niz brojeva u ovom intervalu napredovati (aritmetički).
Can you write Python code for it?


I am working on the file "06-clustering.ipynb".
The first task is:
Spectral Clustering
TODO
Can you write Python code for it?

from sklearn.datasets import make_moons, make_circles
from sklearn.cluster import SpectralClustering

f, ax = plt.subplots(1, 2, figsize=(13, 5))

X, y = make_moons(1000, noise=.05)
cl = SpectralClustering(n_clusters=2, affinity='nearest_neighbors').fit(X)
ax[0].scatter(X[:, 0], X[:, 1], c=cl.labels_, s=10, cmap='rainbow');

X, y = make_circles(1000, factor=.5, noise=.05)
cl = SpectralClustering(n_clusters=2, affinity='nearest_neighbors').fit(X)
ax[1].scatter(X[:, 0], X[:, 1], c=cl.labels_, s=10, cmap='rainbow');


I am working on the file "06-model-deployment.ipynb".
The first task is:
2. Execute the Model Deployment CI/CD routine in Cloud Build
The CI/CD routine is defined in the model-deployment.yaml file, and consists of the following steps:
1. Load and test the the trained model interface.
2. Create and endpoint in Vertex AI if it doesn't exists.
3. Deploy the model to the endpoint.
4. Test the endpoint.
Build CI/CD container Image for Cloud Build
This is the runtime environment where the steps of testing and deploying model will be executed.
Can you write Python code for it?

!echo $CICD_IMAGE_URI

!gcloud builds submit --tag $CICD_IMAGE_URI build/. --timeout=15m


I am working on the file "06-model-deployment.ipynb".
The first task is:
Run CI/CD from model deployment using Cloud Build
Can you write Python code for it?

REPO_URL = "https://github.com/GoogleCloudPlatform/mlops-with-vertex-ai.git" # Change to your github repo.
BRANCH = "main"

SUBSTITUTIONS=f"""\
_REPO_URL='{REPO_URL}',\
_BRANCH={BRANCH},\
_CICD_IMAGE_URI={CICD_IMAGE_URI},\
_PROJECT={PROJECT},\
_REGION={REGION},\
_MODEL_DISPLAY_NAME={MODEL_DISPLAY_NAME},\
_ENDPOINT_DISPLAY_NAME={ENDPOINT_DISPLAY_NAME},\
"""

!echo $SUBSTITUTIONS

!gcloud builds submit --no-source --config build/model-deployment.yaml --substitutions {SUBSTITUTIONS} --timeout=30m


I am working on the file "06-model-deployment.ipynb".
The first task is:
Run deploy model
Can you write Python code for it?

!python build/utils.py \
    --mode=deploy-model\
    --project={PROJECT}\
    --region={REGION}\
    --endpoint-display-name={ENDPOINT_DISPLAY_NAME}\
    --model-display-name={MODEL_DISPLAY_NAME}


I am working on the file "06-model-deployment.ipynb".
The first task is:
Run the model artifact testing
Can you write Python code for it?


I am working on the file "06-model-deployment.ipynb".
The first task is:
Set configurations
Can you write Python code for it?

VERSION = 'v01'
DATASET_DISPLAY_NAME = 'chicago-taxi-tips'
MODEL_DISPLAY_NAME = f'{DATASET_DISPLAY_NAME}-classifier-{VERSION}'
ENDPOINT_DISPLAY_NAME = f'{DATASET_DISPLAY_NAME}-classifier'

CICD_IMAGE_NAME = 'cicd:latest'
CICD_IMAGE_URI = f"gcr.io/{PROJECT}/{CICD_IMAGE_NAME}"


I am working on the file "06-model-deployment.ipynb".
The first task is:
Setup Google Cloud project
Can you write Python code for it?

PROJECT = '[your-project-id]' # Change to your project id.
REGION = 'us-central1' # Change to your region.

if PROJECT == "" or PROJECT is None or PROJECT == "[your-project-id]":
    # Get your GCP project id from gcloud
    shell_output = !gcloud config list --format 'value(core.project)' 2>/dev/null
    PROJECT = shell_output[0]

print("Project ID:", PROJECT)
print("Region:", REGION)


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
Adding multiple axes by hand is often annoying (although sometimes necessary). There are a number of tools that can be used to simplify this in standard cases: add_subplot is the standard one. When you want a figure containing multiple subplots all the same size, with r rows and c columns, the command is add_subplot(r, c, <subplot_number>). For example:
Can you write Python code for it?

fig = pyplot.figure(figsize=(12, 9))
x = numpy.linspace(0.0, 1.0)
for subplot in range(1, 7):
    axis = fig.add_subplot(2, 3, subplot)
    axis.plot(x, numpy.sin(numpy.pi*x*subplot))
    axis.set_xlabel(r'$x$')
    axis.set_ylabel(r'$y$')
    axis.set_title(r'$\sin({} \pi x)$'.format(subplot))
fig.tight_layout();


fig = pyplot.figure(figsize=(10, 6))
x = numpy.linspace(0.0, 1.0)
for subplot in range(1, 7):
    axis = fig.add_subplot(2, 3, subplot)
    axis.plot(x, numpy.sin(numpy.pi*x*subplot))
    axis.set_xlabel(r'$x$')
    axis.set_ylabel(r'$y$')
    axis.set_title(r'$\sin({} \pi x)$'.format(subplot))
fig.tight_layout();


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
Each axis contains additional objects that can be modified.
Can you write Python code for it?

axis2.set_xscale('log')
axis1.set_xlabel(r'$x$', fontsize=16)
fig

axis1.set_xticks([0, 1, 2])
axis1.set_xticklabels(['Start', 'Middle', 'End'])
fig


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
Finally, we can read the contents of that file into a new variable and check that it matches:
Can you write Python code for it?

A_from_file = numpy.loadtxt('A_numpy.txt')
print(A_from_file == A_numpy)


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
Finally, we'll see what it looks like:
Can you write Python code for it?


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
If we want to plot a surface, then we need to construct 2d arrays containing the locations of the $x$ and $y$ coordinates, and a 2d array containing the "height" of the surface. For structured data (ie, where the $x$ and $y$ coordinates lie on a regular grid) the meshgrid function helps. For example, the function
$$ \phi(x, y) = \sin^2 ( \pi x y ) \cos( 2 \pi y^2 ), \qquad x \in [0, 1], \quad y \in [0, 1], $$
would be plotted using
Can you write Python code for it?

fig = pyplot.figure(figsize=(12, 9))
axis = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection='3d')

x = numpy.linspace(0.0, 1.0)
y = numpy.linspace(0.0, 1.0)

X, Y = numpy.meshgrid(x, y)
# x, y are vectors
# X, Y are 2d arrays

phi = numpy.sin(numpy.pi*X*Y)**2 * numpy.cos(2.0*numpy.pi*Y**2)

axis.plot_surface(X, Y, phi)
axis.set_xlabel(r'$x$')
axis.set_ylabel(r'$y$')
axis.set_zlabel(r'$\phi$');


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
If we want to plot a surface, then we need to construct 2d arrays containing the locations of the $x$ and $y$ coordinates, and a 2d array containing the "height" of the surface. For structured data (ie, where the $x$ and $y$ coordinates lie on a regular grid) the meshgrid function helps. For example, the function
\begin{equation}
  \phi(x, y) = \sin^2 ( \pi x y ) \cos( 2 \pi y^2 ), \qquad x \in [0, 1], \quad y \in [0, 1],
\end{equation}
would be plotted using
Can you write Python code for it?


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
In addition to solving linear systems and computing determinants, you can also factorize matrices and generally do most linear algebra operations that you need. The scipy documentation is comprehensive, and has a specific section on Linear Algebra, as well as a section in the tutorial. Johansson also has a tutorial on scipy in general.
Working with files
Often we will want to work with data - constants, parameters, initial conditions, measurements, and so on. numpy provides ways to work with data stored in files - either reading them in or writing them out. A list of "File I/O routines" is available, but the two key routines are loadtxt and savetxt.
As a simple example we take our matrix A_numpy above and save it to a file:
Can you write Python code for it?


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
Note that the result for $y$ is not a vector, but a two dimensional array. This is because scipy will solve a general system of ODEs. This scalar case is a system of size $1$, but it still returns an array. To solve a system, the RHS function must take a vector for y, return a vector for dydt, and the initial data y0 must be a vector. All these vectors must be the same size.
The output is the numerical approximation to $y$ at the input times $t$, and can be immediately plotted:
Can you write Python code for it?

pyplot.plot(t, y[:,0])
pyplot.xlabel(r'$t$')
pyplot.ylabel(r'$y$')
pyplot.show()


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
Note that we have appeared to multiply a matrix by a row vector, and get a row vector back. This is because numpy does not distinguish between row and column vectors, so everything appears as a row vector. (You could define a $n \times 1$ array instead, but there is no advantage).
To actually check the shape and size of numpy arrays, you can directly check their attributes:
Can you write Python code for it?

print(x_numpy.size)
print(x_numpy.shape)
print(A_numpy.size)
print(A_numpy.shape)


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
Note: the line %matplotlib inline is a special IPython command that makes the plot show up inline in the IPython console or notebook. It has no effect in a standard Python script.
This plotting interface is straightforward, but the results are not particularly nice. The following commands illustrate some of the ways of improving the plot:
Can you write Python code for it?

x = numpy.linspace(0, 2.0)
y = numpy.sin(numpy.pi*x)**2
pyplot.plot(x, y, marker='x', markersize=10, linestyle=':', linewidth=3,
            color='b', label=r'$\sin^2(\pi x)$')
pyplot.legend(loc='lower right')
pyplot.xlabel(r'$x$')
pyplot.ylabel(r'$y$')
pyplot.title('A basic plot')
pyplot.show()


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
Passing parameters is also similar to the integration case. For example, consider the problem
$$  \frac{\text{d}}{\text{d} t} \begin{pmatrix} x \ y \end{pmatrix} = \begin{pmatrix} -y + \alpha \ x \end{pmatrix}, \qquad \begin{pmatrix} x \ y \end{pmatrix}(0) = \begin{pmatrix} 1 \ 0 \end{pmatrix}. $$
If $\alpha$ is zero, the solution is a circle in the $x, y$ plane. We solve this using odeint, denoting the state vector $\vec{z} = (x, y)^T$:
Can you write Python code for it?

import numpy
from scipy.integrate import odeint

def dzdt(z, t, alpha):
    """
    Defining the ODE dz/dt.

    Parameters
    ----------

    z : real, list
        The value of z at time t (the current numerical approximation)
    t : real
        The current time t
    alpha : real
        Parameter

    Returns
    -------

    dzdt : real
        The RHS function defining the ODE.
    """

    dzdt = numpy.zeros_like(z)
    x, y = z
    dzdt[0] = -y + alpha
    dzdt[1] = x

    return dzdt

t = numpy.linspace(0.0, 50.0, 1000)
z0 = [1.0, 0.0]
alpha = 1e-5

z = odeint(dzdt, z0, t, args=(alpha,))

fig = pyplot.figure(figsize=(12,12))
ax = fig.add_subplot(1,1,1)
ax.plot(z[:,0], z[:,1])
ax.set_xlabel(r'$x$')
ax.set_ylabel(r'$y$')
ax.set_xlim(-1.1, 1.1)
ax.set_ylim(-1.1, 1.1);


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
Passing parameters is also similar to the integration case. For example, consider the problem
\begin{equation}
  \frac{\text{d}}{\text{d} t} \begin{pmatrix} x \ y \end{pmatrix} = \begin{pmatrix} -y + \alpha \ x \end{pmatrix}, \qquad \begin{pmatrix} x \ y \end{pmatrix}(0) = \begin{pmatrix} 1 \ 0 \end{pmatrix}.
\end{equation}
If $\alpha$ is zero, the solution is a circle in the $x, y$ plane. We solve this using odeint, denoting the state vector $\vec{z} = (x, y)^T$:
Can you write Python code for it?


import numpy
from scipy.integrate import odeint

def dzdt(z, t, alpha):
    """
    Defining the ODE dz/dt.

    Parameters
    ----------

    z : real, list
        The value of z at time t (the current numerical approximation)
    t : real
        The current time t
    alpha : real
        Parameter

    Returns
    -------

    dzdt : real
        The RHS function defining the ODE.
    """

    dzdt = numpy.zeros_like(z)
    x, y = z
    dzdt[0] = -y + alpha
    dzdt[1] = x

    return dzdt

t = numpy.linspace(0.0, 50.0, 1000)
z0 = [1.0, 0.0]
alpha = 1e-5

z = odeint(dzdt, z0, t, args=(alpha,))

fig = pyplot.figure(figsize=(8,8))
ax = fig.add_subplot(1,1,1)
ax.plot(z[:,0], z[:,1])
ax.set_xlabel(r'$x$')
ax.set_ylabel(r'$y$')
ax.set_xlim(-1.1, 1.1)
ax.set_ylim(-1.1, 1.1);


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
Plotting
There are many Python plotting libraries depending on your purpose. However, the standard general-purpose library is matplotlib. This is often used through its pyplot interface.
This is a quick recap of the basic plotting commands, but using numpy as well.
Can you write Python code for it?

from matplotlib import pyplot

%matplotlib inline
from matplotlib import rcParams
rcParams['figure.figsize']=(12,9)

x = numpy.linspace(0, 2.0)
y = numpy.sin(numpy.pi*x)**2
pyplot.plot(x, y)
pyplot.show()


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
Similarly, we cannot apply algebraic operations or functions to lists in a straightforward manner that matches our expectations.
However, there is a Python package - numpy - that does give us the behaviour we want.
numpy
Can you write Python code for it?


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
Solving ODEs
There is a link between the solution of integrals and the solution of differential equations. Unfortunately, the numerical solution of an ODE is more complex than the solution of an integral. Fortunately, scipy contains a number of methods for these as well.
The methods in scipy solve ODEs of the form
$$  \frac{\text{d} \vec{y}}{\text{d} t} = \vec{f} \left( \vec{y}, t \right), \qquad \vec{y}(0) = \vec{y}_0. $$
For example, the ODE
$$  \frac{\text{d} y}{\text{d} t} = e^{-t} - y, \qquad y(0) = 1 $$
has $f(y, t) = e^{-t} - y$.
The method for using scipy is similar to the integration case.

Define a function that specifies the system, by defining the RHS.
Import the function that solves ODEs (odeint)
Call the function, passing the RHS function, the initial data $\vec{y}_0$, the times at which the solution is needed, and any parameters.

To solve our example, we use:
Can you write Python code for it?

from numpy import exp
from scipy.integrate import odeint

def dydt(y, t):
    """
    Defining the ODE dy/dt = e^{-t} - y.

    Parameters
    ----------

    y : real
        The value of y at time t (the current numerical approximation)
    t : real
        The current time t

    Returns
    -------

    dydt : real
        The RHS function defining the ODE.
    """

    return exp(-t) - y

t = numpy.linspace(0.0, 1.0)
y0 = [1.0]

y = odeint(dydt, y0, t)
print("The shape of the result is {}.".format(y.shape))
print("The value of y at t=1 is {}.".format(y[-1,0]))


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
Solving ODEs
There is a link between the solution of integrals and the solution of differential equations. Unfortunately, the numerical solution of an ODE is more complex than the solution of an integral. Fortunately, scipy contains a number of methods for these as well.
The methods in scipy solve ODEs of the form
\begin{equation}
  \frac{\text{d} \vec{y}}{\text{d} t} = \vec{f} \left( \vec{y}, t \right), \qquad \vec{y}(0) = \vec{y}_0.
\end{equation}
For example, the ODE
\begin{equation}
  \frac{\text{d} y}{\text{d} t} = e^{-t} - y, \qquad y(0) = 1
\end{equation}
has $f(y, t) = e^{-t} - y$.
The method for using scipy is similar to the integration case.

Define a function that specifies the system, by defining the RHS.
Import the function that solves ODEs (odeint)
Call the function, passing the RHS function, the initial data $\vec{y}_0$, the times at which the solution is needed, and any parameters.

To solve our example, we use:
Can you write Python code for it?


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
The steps we have taken are:

Define the integrand by defining a function. This function takes the points at which the integrand is evaluated. By using numpy we can do this with a single command.
Import the quad function.
Call the quad function, passing the function defining the integrand, and the lower and upper limits.

The result we get back, as seen from the screen output, is not just $I$. It is a tuple containing both $I$, and also the accuracy with which quad believes it has computed the result. The quadrature is a numerical approximation, so can never be perfect. You should check this error estimate to ensure the result is "good enough" for your purposes.
We can also pass additional parameters if needed. Consider the problem
\begin{equation}
  I_a = \int_0^{\pi} \sin^2 (a x) \, \text{d} x.
\end{equation}
If we wanted to solve this for many values of $a$, say $a = 1, 2, \dots, 5$, we could create a function taking a parameter, and then pass that parameter through:
Can you write Python code for it?

from numpy import sin
from scipy.integrate import quad

def integrand_param(x, a):
    """
    The integrand \sin^2(a x).

    Parameters
    ----------

    x : real (list)
        The point(s) at which the integrand is evaluated
    a : real
        The parameter for the integrand

    Returns
    -------

    integrand : real (list)
        The integrand evaluated at x
    """

    return sin(a*x)**2

for a in range(1, 6):
    result, accuracy = quad(integrand_param, 0.0, numpy.pi, args=(a,))
    print("For a={}, the result is {}.".format(a, result))


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
The tight_layout function call at the end ensures that the axis labels and titles do not overlap with other subplots.
Higher dimensions
To plot three-dimensional objects, we need to modify the axis so that it knows a third dimension is required. To do this, we import another module and modify the command that sets up the axis object.
Can you write Python code for it?

from mpl_toolkits.mplot3d.axes3d import Axes3D

fig = pyplot.figure(figsize=(12, 9))
axis = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection='3d')


from mpl_toolkits.mplot3d.axes3d import Axes3D

fig = pyplot.figure(figsize=(10, 6))
axis = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection='3d')


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
The type of the file is taken from the extension. Here we have used a png file, but svg and pdf output will also work.
Object-based approach
To get a more detailed control over the plot it's better to look at the objects that matplotlib is producing. Remember, when we talked about classes we said that it is an object with attributes and methods (functions) that are accessed using dot notation. Here are steps to completely control the plot.
First we define a figure object. We do not have to define the figure class - it is defined within matplotlib itself, along with a lot of useful methods. We call the constructor of the figure object in the same way as in the previous section, by calling pyplot.figure(). We can and will control its size (the units default to inches) by passing additional arguments to the constructor:
Can you write Python code for it?


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
The type of the file is taken from the extension. Here we have used a png file, but svg and pdf output will also work.
Object-based approach
To get a more detailed control over the plot it's better to look at the objects that matplotlib is producing. Remember, when we talked about classes we said that it is an object with attributes and methods (functions) that are accessed using dot notation. Here are steps to completely control the plot.
First we define a figure object. We will control its size (the units default to inches):
Can you write Python code for it?


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
There are a lot of options to modify the appearance of this plot. Important ones include the colormap (note the US spelling), which requires importing the cm module from matplotlib, and the stride parameters changing the appearance of the grid. For example
Can you write Python code for it?

from matplotlib import cm

fig = pyplot.figure(figsize=(10, 6))
axis = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection='3d')

p = axis.plot_surface(X, Y, phi, rstride=1, cstride=2, cmap = cm.coolwarm)
axis.set_xlabel(r'$x$')
axis.set_ylabel(r'$y$')
axis.set_zlabel(r'$\phi$')
fig.colorbar(p, shrink=0.5);


from matplotlib import cm

fig = pyplot.figure(figsize=(12, 9))
axis = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection='3d')

p = axis.plot_surface(X, Y, phi, rstride=1, cstride=2, cmap = cm.coolwarm)
axis.set_xlabel(r'$x$')
axis.set_ylabel(r'$y$')
axis.set_zlabel(r'$\phi$')
fig.colorbar(p, shrink=0.5);


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
Think about these carefully.

The first case is straightforward: all elements of the vector are multiplied by a constant.
The second case applies a function to each element separately. numpy implements a version of most interesting mathematical functions, which are applied directly to each element.
The third case is elementwise multiplication of the vectors. The first component of the answer is the product of the first component of x_numpy with the first component of y_numpy. The second component of the answer is the product of the second component of x_numpy with the second component of y_numpy. We cannot use the * operator to represent matrix multiplication, but must use a function (see below; note that there will be an operator in Python 3.5+, but using it will mean your code is, for now, not widely useable).
The fourth case shows a combination of cases above. The answer is given by elementwise subtraction of 1, then squaring (elementwise) that result.

Defining a matrix can be done by applying the array function to a list of lists:
Can you write Python code for it?


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
This plotting interface is straightforward, but the results are not particularly nice. The following commands illustrate some of the ways of improving the plot:
Can you write Python code for it?


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
We can then check the contents of that file (you should open the file on your machine to check):
Can you write Python code for it?


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
We can then check the file on disk (you should open the file on your machine to check):
Can you write Python code for it?

from IPython.display import Image
Image('simple_plot.png')


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
We can then construct, for example, a parametric spiral:
Can you write Python code for it?

t = numpy.linspace(0.0, 10.0, 500)
x = numpy.cos(2.0*numpy.pi*t)
y = numpy.sin(2.0*numpy.pi*t)
z = 0.1*t

axis.plot(x, y, z)
axis.set_xlabel(r'$x$')
axis.set_ylabel(r'$y$')
axis.set_zlabel(r'$z$')
fig


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
We see that for higher rank objects such as matrices, the operations are still performed elementwise.
To multiply a matrix by a vector, or a vector by a vector, in the standard linear algebra sense, we use the numpy.dot function:
Can you write Python code for it?

x_squared = numpy.dot(x_numpy, x_numpy)
A_times_x = numpy.dot(A_numpy, x_numpy)
print(x_squared)
print(A_times_x)


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
We see that the array objects behave as we would expect, and accessing elements is exactly the same as for a list. We can also perform other mathematical operations on the whole vector:
Can you write Python code for it?

print(3*x_numpy)
print(numpy.log(x_numpy))
print(x_numpy*y_numpy)
print((x_numpy-1)**2)


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
We will then add data to the both axes:
Can you write Python code for it?


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
We will then set the range of the second axis:
Can you write Python code for it?

axis2.set_xbound(0.7, 0.8)
axis2.set_ybound(0.3, 0.7)


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
Whilst most of the commands are self-explanatory, a brief note should be made of the strings line r'$x$'. These strings are in LaTeX format, which is the standard typesetting method for professional-level mathematics. The $ symbols surround mathematics. The r before the definition of the string says that the following string will be "raw": that backslash characters should be left alone. Then, special LaTeX commands have a backslash in front of them: here we use \pi and \sin. We can also use ^ to denote superscripts (used here), _ to denote subscripts, and use {} to group terms.
By combining these basic commands with other plotting types (semilogx and loglog, for example), most simple plots can be produced quickly.
Saving figures
If you want to save the figure to a file, instead of printing it to the screen, use the savefig command instead of the show command. For example, try:
Can you write Python code for it?

x = numpy.linspace(0, 2.0)
y = numpy.sin(numpy.pi*x)**2
pyplot.plot(x, y, marker='^', markersize=10, linestyle='-.', linewidth=3,
            color='b', label=r'$\sin^2(\pi x)$')
pyplot.legend(loc='lower right')
pyplot.xlabel(r'$x$')
pyplot.ylabel(r'$y$')
pyplot.title('A basic plot')
pyplot.savefig('simple_plot.png')


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
numpy contains a number of very efficient functions for working with arrays, for finding extreme values, and performing linear algebra tasks. Particular functions that are worth knowing, or starting from, are

arange: constructs an array containing increasing integers
linspace: constructs a linearly spaced array
zeros and ones: constructs arrays containing just ones or zeros
diag: extracts the diagonal of a matrix, or build a matrix with just diagonal entries
mgrid: constructs matrices from vectors for 3d plots
random.rand: constructs an array of random numbers.

Linear algebra
numpy also defines a number of linear algebra functions. However, a more comprehensive set of functions, which is better maintained and often more efficient, is given by scipy:
Can you write Python code for it?

from scipy import linalg

print(linalg.solve(A_numpy, x_numpy))
print(linalg.det(A_numpy))


I am working on the file "06-numpy-plotting.ipynb".
The first task is:
numpy is used so frequently that in a lot of cases and online explanations you will see it abbreviated, using import numpy as np. Here we try to avoid that - auto-completion inside spyder means that the additional typing is trivial, and using the full name is clearer.
numpy defines a special type, an array, which can represent vectors, matrices, and other higher-rank objects. Unlike standard Python lists, an array can only contain objects of a single type. The notation to create these objects is straightforward: one easy way is to start with a list:
Can you write Python code for it?

x_numpy = numpy.array(x)
y_numpy = numpy.array(y)
print(x_numpy + y_numpy)
print(x_numpy[0])
print(y_numpy[1:])


I am working on the file "06-pandas DataFrame-02.ipynb".
The first task is:
DataFrame から特定の列を Series として取り出す例です。
Can you write Python code for it?

from numpy.random import randint
dices = randint(1,7,(5,2))
diceroll = DataFrame(dices, columns=['dice1','dice2'])
diceroll


I am working on the file "06-pandas DataFrame-02.ipynb".
The first task is:
DataFrame から行を指定して取り出す例です。
配列のスライス記法で取り出す行を指定します。
Can you write Python code for it?


I am working on the file "06-pandas DataFrame-02.ipynb".
The first task is:
column 名を属性に指定して取り出します。
Can you write Python code for it?


I am working on the file "06-pandas DataFrame-02.ipynb".
The first task is:
iterrows メソッドは、各行の index とその行を表わす Series オブジェクトを順に返します。
Can you write Python code for it?

for index, line in cities.iterrows():
    print 'Index:', index
    print line, '\n'


I am working on the file "06-pandas DataFrame-02.ipynb".
The first task is:
データフレームを変更する例です。
DataFrame から抽出したオブジェクトを変更する際は、明示的にコピーを作成します。
Can you write Python code for it?

humidity = cities['Humidity'].copy()
humidity[2] = 50
humidity


I am working on the file "06-pandas DataFrame-02.ipynb".
The first task is:
条件による行の指定と組み合わせることもできます。
Can you write Python code for it?

cities.loc[(cities['Temperature']>27)&(cities['Temperature']<29), 'Temperature'] = 28
cities


I am working on the file "06-pandas DataFrame-02.ipynb".
The first task is:
次のように、単一の列を DataFrame として取り出すこともできます。
Can you write Python code for it?


I am working on the file "06-pandas DataFrame-02.ipynb".
The first task is:
練習問題
(1) 次の関数 create_dataset() を用いて、num=10 個のデータからなるデータフレーム data を作成します。その後、iterrowsメソッドを利用して、データポイント (x,y) のy値と関数 sin(2πx) の平方根平均二乗誤差 √{sum(sin(2πx) - y)**2 / num} を計算してください。
ヒント：この例では、平方根平均二乗誤差は約0.3になります。
Can you write Python code for it?

from numpy.random import normal

def create_dataset(num):
    data_x = np.linspace(0,1,num)
    data_y = np.sin(2*np.pi*data_x) + normal(loc=0, scale=0.3, size=num)
    return DataFrame({'x': data_x, 'y': data_y})


I am working on the file "06-pandas DataFrame-02.ipynb".
The first task is:
行はスライス記法、列は column 名のリストで指定します。
Can you write Python code for it?


I am working on the file "06-pandas DataFrame-02.ipynb".
The first task is:
複数の列を DataFrame として取り出す例です。
Can you write Python code for it?

data = {'City': ['Tokyo','Osaka','Nagoya','Okinawa'],
                 'Temperature': [25.0,28.2,27.3,30.9],
                 'Humidity': [44,42,np.nan,62]}
cities = DataFrame(data)
cities

cities[['City', 'Humidity']]


I am working on the file "06-prestamos.ipynb".
The first task is:
Abono constante a capital
fixed_ppal_loan(amount, nrate, grace=0, dispoints=0, orgpoints=0,
   prepmt=None, balloonpmt=None)
En este tipo de crédito el abono al capital es una cantidad fija durante todos los períodos, de tal forma que el pago total por período es variable (ya que incluye los intereses pagados sobre el saldo de la deuda).

amount -- monto del crédito.
nrate -- tasa nominal de interés.
grace -- número de períodos de gracia antes del pago del capital.
dispoints -- puntos (costo) de descuento como porcentaje de amount. Se consideran como intereses anticipados y son deducibles de impuestos.
orgpoints -- puntos (costo) de constitución como porcentaje de amount. Son costos no deducibles para el pago de impuestos.
prepmt -- flujo de efectivo que representa prepago de la deuda.
balloonpmt -- pagos extra al pago períodico especificados como un objeto cashflow.

Ejemplo.-- Modele un crédito por $ 1000 a 10 años y una tasa del 10%. Los pagos son anuales.
Can you write Python code for it?

nrate = cf.interest_rate(const_value=[10]*11, start=2018)
cf.fixed_ppal_loan(amount=1000,
                   nrate=nrate,
                   grace=0,
                   dispoints=0,
                   orgpoints=0,
                   prepmt=None,
                   balloonpmt=None)

##
## período de gracia de 3
##
nrate = cf.interest_rate(const_value=[10]*11, start=2018)

cf.fixed_ppal_loan(amount=1000,
                   nrate=nrate,
                   grace=3,
                   dispoints=0,
                   orgpoints=0,
                   prepmt=None,
                   balloonpmt=None)

##
## este tipo de crédito admite una tasa de interés variable
##
nrate = cf.interest_rate(const_value=[10]*11, start=2018, chgpts={'2024':8})

cf.fixed_ppal_loan(amount=1000,
                   nrate=nrate,
                   grace=0,
                   dispoints=0,
                   orgpoints=0,
                   prepmt=None,
                   balloonpmt=None)

##
## este tipo de crédito admite pagos adicionales
## programados como abono a la deuda
##
nrate      = cf.interest_rate(const_value=[10]*11, start=2018)
balloonpmt = cf.cashflow(const_value=[0]*11, start=2018)
balloonpmt['2023'] = 500

cf.fixed_ppal_loan(amount=1000,
                   nrate=nrate,
                   grace=0,
                   dispoints=0,
                   orgpoints=0,
                   prepmt=None,
                   balloonpmt=balloonpmt)

##
## este tipo de crédito admite
## una tasa de interés variable
##
nrate = cf.interest_rate(const_value=[10]*11, start=2018, chgpts={'2024':8})
balloonpmt = cf.cashflow(const_value=[0]*11,  start=2018)
balloonpmt['2023'] = 500

cf.fixed_ppal_loan(amount=1000,
                   nrate=nrate,
                   grace=0,
                   dispoints=0,
                   orgpoints=0,
                   prepmt=None,
                   balloonpmt=balloonpmt)

##
## ejemplo anterior con período de gracia
##
nrate = cf.interest_rate(const_value=[10]*11, start=2018,...


I am working on the file "06-prestamos.ipynb".
The first task is:
Balloon loan / tasa fija
fixed_rate_loan(amount, nrate, life, start, pyr=1,
   grace=0, dispoints=0, orgpoints=0, prepmt=None,
   balloonpmt=None)
En este tipo de crédito la tasa permanece fija durante toda la vida de la deuda. El pago periodico (intereses + capital) es constante. Admite la especificación de cuotas extras (balloon payments) pactadas desde el principio del crédito que tienen como fin reducir el pago períodico.

amount -- monto del crédito.
nrate -- tasa nominal de interés.
life -- plazo del crédito.
start -- especificación del período de inicio del crédito.
pyr -- número de periodos de capitalización por año para la tasa.
grace -- número de períodos de gracia antes del pago del capital.
dispoints -- puntos (costo) de descuento como porcentaje de amount. Se consideran como intereses anticipados y son deducibles de impuestos.
orgpoints -- puntos (costo) de constitución como porcentaje de amount. Son costos no deducibles para el pago de impuestos.
prepmt -- flujo de efectivo que representa prepago de la deuda.
balloonpmt -- pagos extra al pago períodico especificados como un objeto cashflow.

Ejemplo.-- Modele un préstamo de  $ 1000 a un plazo de 10 años, cuotas anuales y una tasa del 10%.
Can you write Python code for it?

cf.fixed_rate_loan(amount=1000, # monto
                   nrate=10,    # tasa de interés
                   freq='A',
                   life=10,     # número de cuotas
                   start=2018,
                   grace=0,
                   dispoints=0,
                   orgpoints=0,
                   prepmt=None,
                   balloonpmt=None)


I am working on the file "06-prestamos.ipynb".
The first task is:
Bullet Loan
bullet_loan(amount, nrate, dispoints=0, orgpoints=0, prepmt=None)
En este tipo de préstamo se pagan únicamente intereses durante la vida del crédito; con la última cuota se paga el capital.

amount -- monto del crédito.
nrate -- tasa nominal de interés.
dispoints -- puntos (costo) de descuento como porcentaje de amount. Se consideran como intereses anticipados y son deducibles de impuestos.
orgpoints -- puntos (costo) de constitución como porcentaje de amount. Son costos no deducibles para el pago de impuestos.
prepmt -- flujo de efectivo que representa prepago de la deuda.

Ejemplo.- Modele un préstamo de  $ 1000 a una tasa de interés del 10% y una duración de 10 años.
Can you write Python code for it?

cf.bullet_loan(amount=1000,
               nrate=cf.interest_rate(const_value=10, periods=11, start=2017, freq='A'),
               dispoints=0,
               orgpoints=0,
               prepmt=None)

## se puede asignar a una variable
x = cf.bullet_loan(amount=1000,
                   nrate=cf.interest_rate(const_value=10, periods=11, start=2017, freq='A'),
                   dispoints=0,
                   orgpoints=0,
                   prepmt=None)
x

## todos los tipos de créditos tiene funciones
## para obtener las columnas de la tabla de
## amortizacion como un flujo de efectivo
x.Int_Payment

sum(x.Int_Payment)

x.Ppal_Payment  ## pagos a capital

x.Beg_Ppal_Amount ## balance inicial del período

x.End_Ppal_Amount ## balance final del período


I am working on the file "06-prestamos.ipynb".
The first task is:
Buydown loan
buydown_loan(amount, nrate, grace=0, dispoints=0,
   orgpoints=0, prepmt=None)
Este tipo de préstamo es similar a los préstamos de cuota fija (balloon loans) pero con tasa cambiante en el tiempo. No admiten cuotas adicionales para reducir el pago fijo períodico. Cuando hay un cambio en la tasa de interés, el pago períodico total se recalcula para reflejar el cambio de tasa de interés.

amount -- monto del crédito.
nrate -- tasa nominal de interés.
grace -- número de períodos de gracia antes del pago del capital.
dispoints -- puntos (costo) de descuento como porcentaje de amount. Se consideran como intereses anticipados y son deducibles de impuestos.
orgpoints -- puntos (costo) de constitución como porcentaje de amount. Son costos no deducibles para el pago de impuestos.
prepmt -- flujo de efectivo que representa prepago de la deuda.
Can you write Python code for it?

##
## los resultados son iguales a un crédito balloon
##
nrate = cf.interest_rate(const_value=[10]*11, start=2018)

cf.buydown_loan(amount=1000,
                nrate=nrate,
                dispoints=0,
                orgpoints=0,
                prepmt=None)

##
## cambios en la tasa de interés
##
nrate = cf.interest_rate(const_value=[10]*11, start=2018, chgpts={'2024':5})

cf.buydown_loan(amount=1000,
                nrate=nrate,
                dispoints=0,
                orgpoints=0,
                prepmt=None)

##
## se introducen 2 prepagos por $ 100 cada uno
## en t = 3, 6
##
nrate = cf.interest_rate(const_value=[10]*11, start=2018)

prepmt = cf.cashflow(const_value=[0]*11, start='2018')
prepmt['2021'] = 100
prepmt['2024'] = 100

cf.buydown_loan(amount=1000,
                nrate=nrate,
                dispoints=0,
                orgpoints=0,
                prepmt=prepmt)


I am working on the file "06-prestamos.ipynb".
The first task is:
Ejemplo.-- Considere el caso anterior y un prepago de la deuda de $ 100 en los períodos 3 y 7.
Can you write Python code for it?

prepmt = cf.cashflow(const_value=[0]*11, start=2018)
prepmt['2021'] = 100
prepmt['2025'] = 100

cf.fixed_rate_loan(amount=1000,
                   nrate=10,
                   life=10,
                   start=2018,
                   grace=0,
                   dispoints=0,
                   orgpoints=0,
                   prepmt=prepmt,
                   balloonpmt=balloonpmt)


I am working on the file "06-prestamos.ipynb".
The first task is:
Ejemplo.-- Modele el crédito anterior suponiendo que la tasa cambia al 8% a partir de t = 6.
Can you write Python code for it?

nrate = cf.interest_rate(const_value=[10]*11, start=2018, chgpts={'2023':8})

cf.bullet_loan(amount=1000,
               nrate=nrate,
               dispoints=0,
               orgpoints=0,
               prepmt=None)


I am working on the file "06-prestamos.ipynb".
The first task is:
Ejemplo.-- Un crédito bullet puede modelarse como un crédito balloon usando un prepago al final igual al monto de la deuda.
Can you write Python code for it?

balloonpmt = cf.cashflow(const_value=[0]*11, start=2018)
balloonpmt['2028'] = 1000

cf.fixed_rate_loan(amount=1000,
                   nrate=10,
                   life=10,
                   start=2018,
                   grace=0,
                   dispoints=0,
                   orgpoints=0,
                   prepmt=None,
                   balloonpmt=balloonpmt)


I am working on the file "06-prestamos.ipynb".
The first task is:
to_cashflow(tax_rate=0)
Convierte el crédito a un flujo de fondos equivalente.

tax_rate -- impuesto de renta. Se usa para tener en cuenta la reducción del pago por impuesto de renta debido a que los intereses son considerados como costo financiero deducible de impuestos.
Can you write Python code for it?

nrate = cf.interest_rate(const_value=[10]*11, start=2018)

prepmt = cf.cashflow(const_value=[0]*11, start='2018')
prepmt['2021'] = 100
prepmt['2024'] = 100

cf.buydown_loan(amount=1000,
                nrate=nrate,
                dispoints=0,
                orgpoints=0,
                prepmt=prepmt).tocashflow()


I am working on the file "06-prestamos.ipynb".
The first task is:
true_rate(tax_rate=0)
Calcula la tasa real del interés del crédito. Permite la comparación de créditos. Para el cálculo, el préstamo es convertido al flujo de efectivo equivalente teniendo en cuenta lo siguiente:

Los puntos de causación son considerados como no deducibles y son ignorados en el cálculo del beneficio del impuesto de renta.

Los puntos de descuento son considerado como intereses prepagados y son deducibles de impuestos.

Si tax_rate es diferente de cero, la tasa de interés verdadera después de impuestos es calculada. Esto implica que en el cálculo solo la porción (1-tax_rate) de los intereses (incluyendo los puntos de descuento) es considerada en el cálculo.
Can you write Python code for it?

nrate = cf.interest_rate(const_value=[10]*11, start=2018)

prepmt = cf.cashflow(const_value=[0]*11, start='2018')
prepmt['2021'] = 100
prepmt['2024'] = 100

cf.buydown_loan(amount=1000,
                nrate=nrate,
                dispoints=0,
                orgpoints=0,
                prepmt=prepmt).true_rate()


I am working on the file "06. 기초 선형대수/01. NumPy 소개.ipynb".
The first task is:
2차원 이상의 인덱스인 경우에는 다음과 같이
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/01. NumPy 소개.ipynb".
The first task is:
각각의 코드 실행시에 IPython의 %time 매직 명령을 이용하여 실행 시간을 측정한 결과 ndarray의 유니버설 연산 실행 속도가 리스트 반복문 보다 빠른 것을 볼 수 있다. ndarray의 메모리 할당을 한 번에 하는 것도 빨라진 이유의 하나이고 유니버설 연산을 사용하게 되면 NumPy 내부적으로 구현된 반복문을 사용하기 때문에 반복문 실행 자체도 빨라진다.
따라서 Python의 성능 개선을 위해 반드시 지켜야하는 코딩 관례 중의 하나가 NumPy의 ndarray의 벡터화 연산으로 대체할 수 있는 경우에는  Python 자체의 반복문을 사용하지 않는다는 점이다.(for문)

Python 리스트

여러가지 타입의 원소

linked List 구현
메모리 용량이 크고 속도가 느림

벡터화 연산 불가

NumPy ndarray

동일 타입의 원소

contiguous memory layout
메모리 최적화, 계산 속도 향상
벡터화 연산 가능

참고로 일반적인 리스트 객체에 정수를 곱하면 객체의 크기가 정수배 만큼으로 증가한다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/01. NumPy 소개.ipynb".
The first task is:
그러나 ndarray 클래스 객체 a와 리스트 클래스 객체 b는 많은 차이가 있다. 우선 리스트 클래스 객체는 내부적으로 linked list와 같은 형태를 가지므로 각각의 원소가 다른 자료형이 될 수 있다. 그러나 ndarray 클래스 객체는 C언어의 행렬처럼 연속적인 메모리 배치를 가지기 때문에 모든 원소가 같은 자료형이어야 한다. 이러한 제약을 가지는 대신 내부의 원소에 대한 접근과 반복문 실행이 빨라진다.
ndarray 클래스의 또 다른 특성은 행렬의 각 원소에 대한 연산을 한 번에 처리하는 벡터화  연산(vectorized operation)을 지원한다는 점이다. 예를 들어 ndarray 클래스 객체의 원소의 크기를 모두 제곱하기 위해서는 객체 자체를 제곱하는 것만으로 원하는 결과를 얻을 수 있다.
Can you write Python code for it?

a = np.arange(1000) #arange : 그냥 array range임 array로 바꿈
%time a2 = a**2

a1 = np.arange(10)
print(a1)
print(2 * a1)


I am working on the file "06. 기초 선형대수/01. NumPy 소개.ipynb".
The first task is:
다차원 행렬의 생성
ndarray 는 N-dimensional Array의 약자이다. 이름 그대로 ndarray 클래스는 단순 리스트와 유사한 1차원 행렬 이외에도 2차원 행렬, 3차원 행렬 등의 다차원 행렬 자료 구조를 지원한다.
예를 들어 다음과 같이 리스트의 리스트를 이용하여 2차원 행렬을 생성하거나 리스트의 리스트의 리스트를 이용하여 3차원 행렬을 생성할 수 있다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/01. NumPy 소개.ipynb".
The first task is:
다차원 행렬의 슬라이싱
ndarray 클래스로 구현한 다차원 행렬의 원소 중 복수 개를 접근하려면 일반적인 파이썬 슬라이싱(slicing)과 comma(,)를 함께 사용하면 된다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/01. NumPy 소개.ipynb".
The first task is:
이는 다음과 같이 간단하게 쓸 수도 있다.
Can you write Python code for it?

a[a % 2 == 0]

a[a % 2] # 0이 True, 1이 False


I am working on the file "06. 기초 선형대수/01. NumPy 소개.ipynb".
The first task is:
정수 행렬 인덱스의 크기는 원래의 행렬 크기와 달라도 상관없다. 같은 원소를 반복해서 가리키는 경우에는 원래의 행렬보다 더 커지기도 한다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/01. NumPy 소개.ipynb".
The first task is:
정수 행렬 인덱싱에서는 인덱스 행렬의 원소 각각이 원래 ndarray 객체 원소 하나를 가리키는 인덱스 정수이여야 한다.
예를 들어 1차원 행렬에서 홀수번째 원소만 골라내려만 다음과 같다
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/01. NumPy 소개.ipynb".
The first task is:
행렬 인덱싱
NumPy ndarray 클래스의 또다른 강력한 기능은 행렬 인덱싱(fancy indexing)이라고도 부르는 행렬 인덱싱(array indexing) 방법이다. 인덱싱이라는 이름이 붙었지만 사실은 데이터베이스의 질의(Query) 기능을 수행한다.
행렬 인덱싱에서는 대괄호(Bracket, [])안의 인덱스 정보로 숫자나 슬라이스가 아닌 ndarray 행렬을 받을 수 있다. 여기에서는 이 행렬을 편의상 인덱스 행렬이라고 부르겠다. 행렬 인덱싱의 방식에은 불리안(Boolean) 행렬 방식과 정수 행렬 방식 두가지가 있다.
먼저 불리안 행렬 인덱싱 방식은 인덱스 행렬의 원소가 True, False 두 값으로만 구성되며 인덱스 행렬의 크기가 원래 ndarray 객체의 크기와 같아야 한다.
예를 들어 다음과 같은 1차원 ndarray에서 홀수인 원소만 골라내려면 홀수인 원소에 대응하는 인덱스 값이 True이고 짝수인 원소에 대응하는 인덱스 값이 False인 인덱스 행렬 사용한다.
Can you write Python code for it?

a = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
idx = np.array([True, False, True, False, True, False, True, False, True, False])
a[idx]


I am working on the file "06. 기초 선형대수/02. NumPy 배열 생성과 변형.ipynb".
The first task is:
arange 명령은 NumPy 버전의 range 명령이라고 볼 수 있다. 해당하는 범위의 숫자 순열을 생성한다.
Can you write Python code for it?

np.arange(10)  # 0 .. n-1

np.arange(3, 21, 2)  # start, end (exclusive), step


I am working on the file "06. 기초 선형대수/02. NumPy 배열 생성과 변형.ipynb".
The first task is:
linspace 명령이나 logspace 명령은 선형 구간 혹은 로그 구간을 지정한 구간의 수만큼 분할한다.
Can you write Python code for it?

np.linspace(0, 100, 5)  # start, end, num-points

np.linspace(0, 100, 4)

np.logspace(0, 4, 4, endpoint=False)


I am working on the file "06. 기초 선형대수/02. NumPy 배열 생성과 변형.ipynb".
The first task is:
r_ 메서드는 hstack 명령과 유사하다. 다만 메서드임에도 불구하고 소괄호(parenthesis, ())를 사용하지 않고 인덱싱과 같이 대괄호(bracket, [])를 사용한다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/02. NumPy 배열 생성과 변형.ipynb".
The first task is:
stack 명령은 새로운 차원(축으로) 배열을 연결하며 당연히 연결하고자 하는 배열들의 크기가 모두 같아야 한다.
axis 인수(디폴트 0)를 사용하여 연결후의 회전 방향을 정한다.
Can you write Python code for it?

np.stack([c4, c2])

np.stack([c4, c2], axis=1)


I am working on the file "06. 기초 선형대수/02. NumPy 배열 생성과 변형.ipynb".
The first task is:
tile 명령은 동일한 배열을 반복하여 연결한다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/02. NumPy 배열 생성과 변형.ipynb".
The first task is:
vstack 명령은 열의 수가 같은 두 개 이상의 배열을 위아래로 연결하여 행의 수가 더 많은 배열을 만든다. 연결할 배열은 마찬가지로 하나의 리스트에 담아야 한다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/02. NumPy 배열 생성과 변형.ipynb".
The first task is:
그리드 생성
변수가 2개인 2차원 함수의 그래프를 그리거나 표를 작성하려면 많은 좌표를 한꺼번에 생성하여 각 좌표에 대한 함수 값을 계산해야 한다.
예를 들어 x, y 라는 두 변수를 가진 함수에서 x가 0부터 2까지, y가 0부터 4까지의 사각형 영역에서 변화하는 과정을 보고 싶다면 이 사각형 영역 안의 다음과 같은 (x,y) 쌍 값들에 대해 함수를 계산해야 한다.
$$ (x,y) = (0,0), (0,1), (0,2), (0,3), (0,4), (1,0), \cdots (2,4) $$
이러한 과정을 자동으로 해주는 것이 NumPy의 meshgrid 명령이다. meshgrid 명령은 사각형 영역을 구성하는 가로축의 점들과 세로축의 점을 나타내는 두 벡터를 인수로 받아서 이 사각형 영역을 이루는 조합을 출력한다. 단 조합이 된 (x,y)쌍을 x값만을 표시하는 행렬과 y값만을 표시하는 행렬 두 개로 분리하여 출력한다.
Can you write Python code for it?

x = np.arange(3)
x

y = np.arange(5)
y

X, Y = np.meshgrid(x, y)

X

Y

[zip(x, y) for x, y in zip(X, Y)] # 리스트의 리스트. 2차원 포인트에 대한 값 계산

plt.scatter(X, Y, linewidths=10);


I am working on the file "06. 기초 선형대수/02. NumPy 배열 생성과 변형.ipynb".
The first task is:
길이가 5인 1차원 배열과 행, 열의 갯수가 (5,1)인 2차원 배열은 데이터는 같아도 엄연히 다른 객체이다.
Can you write Python code for it?

x = np.arange(5)
x

y = x.reshape(5,1)
y


I am working on the file "06. 기초 선형대수/02. NumPy 배열 생성과 변형.ipynb".
The first task is:
만약 부동소수점을 사용하는 경우에는 무한대를 표현하기 위한 np.inf와 정의할 수 없는 숫자를 나타내는 np.nan 을 사용할 수 있다.
Can you write Python code for it?

np.exp(-np.inf)

np.array([1, 0]) / np.array([0, 0])


I am working on the file "06. 기초 선형대수/02. NumPy 배열 생성과 변형.ipynb".
The first task is:
만약 크기를 튜플(tuple)로 명시하지 않고 특정한 배열 혹은 리스트와 같은 크기의 배열을 생성하고 싶다면 ones_like, zeros_like 명령을 사용한다.
Can you write Python code for it?

e = range(10)
print(e)
f = np.ones_like(e, dtype="f")
f

np.random.rand(4)


I am working on the file "06. 기초 선형대수/02. NumPy 배열 생성과 변형.ipynb".
The first task is:
사용하는 원소의 갯수가 정해저 있기 때문에 reshape 명령의 형태 튜플의 원소 중 하나는 -1이라는 숫자로 대체할 수 있다. -1을 넣으면 해당 숫자는 다를 값에서 계산되어 사용된다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/02. NumPy 배열 생성과 변형.ipynb".
The first task is:
임의의 난수를 생성하고 싶다면 random 서브패키지의 rand 혹은 randn 명령을 사용한다. rand 명령을 uniform 분포를 따르는 난수를 생성하고 randn 명령을 가우시안 정규 분포를 따르는 난수를 생성한다. 생성할 시드(seed)값을 지정하려면 seed 명령을 사용한다.
Can you write Python code for it?

np.random.seed(0)

np.random.rand(4) #0~1에서 나옴

np.random.randn(3,5) #randn n=normal을 의미. -1 ~ 1


I am working on the file "06. 기초 선형대수/03. NumPy 연산.ipynb".
The first task is:
NumPy 곱셉의 경우에는 행렬의 곱, 즉 내적(inner product, dot product)의 정의와 다르다. 따라서 이 경우에는 별도로 dot이라는 명령 혹은 메서드를 사용해야 한다.
Can you write Python code for it?

x = np.arange(10)
y = np.arange(10)
x * y

np.dot(x, y)

x.dot(y)


I am working on the file "06. 기초 선형대수/03. NumPy 연산.ipynb".
The first task is:
axis=-1 : 마지막 차원을 남겨라
Can you write Python code for it?

y = np.array([[1, 2, 3], [5, 6, 1]])
np.median(y, axis=-1) # last axis

np.median(y, axis=0)


I am working on the file "06. 기초 선형대수/03. NumPy 연산.ipynb".
The first task is:
sort 메서드는 해당 객체의 자료 자체가 변화하는 in-place 메서드이므로 사용할 때 주의를 기울여야 한다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/03. NumPy 연산.ipynb".
The first task is:
그러나 NumPy는 벡터화 연산을 지원하므로 다음과 같이 덧셈 연산 하나로 끝난다. 위에서 보인 선형 대수의 벡터 기호를 사용한 연산과 코드가 완전히 동일하다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/03. NumPy 연산.ipynb".
The first task is:
만약 NumPy 에서 제공하는 지수 함수, 로그 함수 등의 수학 함수를 사용하면 element-wise 벡터화 연산을 지원한다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/03. NumPy 연산.ipynb".
The first task is:
만약 NumPy에서 제공하는 함수를 사용하지 않으면 벡터화 연산은 불가능하다.
Can you write Python code for it?

import math
a = [1, 2, 3]
math.exp(a) #이때 하고싶으면 for문을 써야됨


I am working on the file "06. 기초 선형대수/03. NumPy 연산.ipynb".
The first task is:
만약 배열 전체를 비교하고 싶다면 array_equal 명령을 사용한다.
Can you write Python code for it?

a = np.array([1, 2, 3, 4])
b = np.array([4, 2, 2, 4])
c = np.array([1, 2, 3, 4])

np.array_equal(a, b) #내부적으로 for문이 돌아가서 빠름

np.array_equal(a, c)


I am working on the file "06. 기초 선형대수/03. NumPy 연산.ipynb".
The first task is:
브로드캐스팅
선형대수와 상관 없는 Numpy만의 개념(shape가 다른데 반복해서 같게 해줌)
선형 대수의 행렬 덧셈 혹은 뺄셈을 하려면 두 행렬의 크기가 같아야 한다. 그러나 NumPy에서는 서로 다른 크기를 가진 두 ndarray 배열의 사칙 연산도 지원한다. 이 기능을 브로드캐스팅(broadcasting)이라고 하는데 크기가 작은 배열을 자동으로 반복 확장하여 크기가 큰 배열에 맞추는 방벙이다.
예를 들어 다음과 같이 벡터와 스칼라를 더하는 경우를 생각하자. 선형 대수에서는 이러한 연산이 불가능하다.
$$
x = \begin{bmatrix}0 \ 1 \ 2 \ 3 \ 4 \end{bmatrix}, \;\;\;\;
x + 1 = \begin{bmatrix}0 \ 1 \ 2 \ 3 \ 4 \end{bmatrix} + 1 = ?
$$
그러나 NumPy는 브로드캐스팅 기능을 사용하여 스칼라를 벡터와 같은 크기로 확장시켜서 덧셈 계산을 한다.
$$
\begin{bmatrix}0 \ 1 \ 2 \ 3 \ 4 \end{bmatrix} \overset{\text{numpy}}+ 1 =
\begin{bmatrix}0 \ 1 \ 2 \ 3 \ 4 \end{bmatrix} +  \begin{bmatrix}1 \ 1 \ 1 \ 1 \ 1 \end{bmatrix} =
\begin{bmatrix}1 \ 2 \ 3 \ 4 \ 5 \end{bmatrix}
$$
Can you write Python code for it?

x = np.arange(5)
y = np.ones_like(x)
x + y

x + 1


I am working on the file "06. 기초 선형대수/03. NumPy 연산.ipynb".
The first task is:
브로드캐스팅은 더 차원이 높은 경우에도 적용된다. 다음 그림을 참조하라.
<img src="https://datascienceschool.net/upfiles/dbd3775c3b914d4e8c6bbbb342246b6a.png" style="width: 60%; margin: 0 auto 0 auto;">
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/03. NumPy 연산.ipynb".
The first task is:
비교 연산도 마찬가지로 element-wise 연산이다. 따라서 벡터 혹은 행렬 전체의 원소가 모두 같아야 하는 선형 대수의 비교 연산과는 다르다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/03. NumPy 연산.ipynb".
The first task is:
연산 속도도 벡터화 연산이 훨씬 빠른 것을 볼 수 있다.
Element-Wise 연산
NumPy의 벡터화 연산은 같은 위치의 원소끼리 연산하는 element-wise 연산이다. NumPy의 ndarray를 선형 대수의 벡터나 행렬이라고 했을 때 덧셈, 뺄셈은 NumPy 연산과 일치한다
스칼라와 벡터의 곱도 마찬가지로 선형 대수에서 사용하는 식과 NumPy 코드가 일치한다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/03. NumPy 연산.ipynb".
The first task is:
연산의 대상이 2차원 이상인 경우에는 어느 차원으로 계산을 할 지를 axis 인수를 사용하여 지시한다. axis=0인 경우는 행 연산, axis=1인 경우는 열 연산 등으로 사용한다. 디폴트 값은 0이다.
<img src="https://datascienceschool.net/upfiles/edfaf93a7f124f359343d1dcfe7f29fc.png", style="margin: 0 auto 0 auto;">
axis를 주지 않으면 행, 열로 2번 실행함(그러나 메쏘드마다 조금 다를 수 있음)
Can you write Python code for it?

x = np.array([[1, 1], [2, 2]])
x

x.sum()

x.sum(axis=0)   # columns (first dimension) row만 남기고 column을 없애라

x.sum(axis=1)   # rows (second dimension)


I am working on the file "06. 기초 선형대수/03. NumPy 연산.ipynb".
The first task is:
정렬
sort 명령이나 메서드를 사용하여 배열 안의 원소를 크기에 따라 정렬하여 새로운 배열을 만들 수도 있다. 2차원 이상인 경우에는 마찬가지로 axis 인수를 사용하여 방향을 결정한다.
대부분 메쏘드와 명령어가 동일한 기능을 하는데 이 친구들은 다름
명령어를 하게되면 새로운 행렬을 만들어줌 np.sort(a)
메쏘드를 하면 행렬 자체가 바뀜(a.sort) -> in-place 메쏘드(메모리 할당할 수 있는 시간을 절약할 수 있다는 장점이 있음. 기본적으로 인플레이스를 자주 쓰지만 원래의 값이 변하니까 주의해야됨
Can you write Python code for it?

a = np.array([[4, 3, 5], [1, 2, 1]])
a

np.sort(a)

np.sort(a, axis=0)

np.sort(a, axis=1)


I am working on the file "06. 기초 선형대수/03. NumPy 연산.ipynb".
The first task is:
차원 축소 연산
ndarray의 하나의 행에 있는 원소를 하나의 데이터 집합으로 보고 평균을 구하면 각 행에 대해 하나의 숫자가 나오게 된다. 예를 들어 10x5 크기의 2차원 배열에 대해 행-평균을 구하면 10개의 숫자를 가진 1차원 벡터가 나오게 된다. 이러한 연산을 차원 축소(dimension reduction) 연산이라고 한다.
ndarray 는 다음과 같은 차원 축소 연산 명령 혹은 메서드를 지원한다.

최대/최소: min, max, argmin, argmax
통계: sum, mean, median, std, var
불리언: all, any
Can you write Python code for it?

x = np.array([1, 2, 3, 4])
x

np.sum(x)

x.sum() #function, method로도 존재함

x = np.array([1, 3, 2])

x.min()

x.max()

x.argmin()  # index of minimum 최소값의 위치를 출력

x.argmax()  # index of maximum

x = np.array([1, 2, 3, 1])

x.mean() # 평균

np.median(x) # 중앙값 1~100명. 50등의 점수

np.all([True, True, False]) # 불리언일 경우 주로 사용

np.any([True, True, False]) # 하나라도 존재하면 ㅇㅋ

a = np.zeros((100, 100), dtype=np.int)
a

np.any(a != 0) # 0이 아닌 것이 하나라도 있습니까?

np.all(a == a) #equal array와 비슷함

a = np.array([1, 2, 3, 2])
b = np.array([2, 2, 3, 2])
c = np.array([6, 4, 4, 5])

((a <= b) & (b <= c)).all() #all도 메쏘드로 출력 가능


I am working on the file "06. 기초 선형대수/04. NumPy를 활용한 선형대수 입문.ipynb".
The first task is:
이차 형식
벡터의 이차 형식(Quadratic Form) 이란 어떤 벡터의 각 원소에 대해 가능한 모든 쌍의 조합 $(x_i, x_j)$을 구한 다음 그 곱셈$x_ix_j$을 더한 것을 말한다. 이 때 각 쌍에 대해 서로 다른 가중치 $a_{i,j}$를 적용하여 $a_{i,j}x_ix_j$의 합을 구한다면 다음과 같이 $x^TAx$라는 간단한 식으로 쓸 수 있다.
$$
x^T A x =
\begin{bmatrix}
x_{1} & x_{2} & \cdots & x_{N}
\end{bmatrix}
\begin{bmatrix}
a_{1,1} & a_{1,2} & \cdots & a_{1,N} \
a_{2,1} & a_{2,2} & \cdots & a_{2,N} \
\vdots & \vdots & \ddots & \vdots \
a_{N,1} & a_{N,2} & \cdots & a_{N,N} \
\end{bmatrix}
\begin{bmatrix}
x_{1} \
x_{2} \
\vdots \
x_{N} \
\end{bmatrix} = \sum_{i=1}^{N} \sum_{j=1}^{N} a_{i,j} x_i x_j
$$
예를 들어 $ x = [1, 2, 3]^T $ 이고 A가 다음과 같다면
$$ A =
\begin{pmatrix}
1 & 2 & 3 \
4 & 5 & 6 \
7 & 8 & 9 \
\end{pmatrix}
$$
NumPy 에서 벡터의 이차 형식은 다음과 같이 계산한다.
Can you write Python code for it?

x = np.array([1,2,3])
x

A = np.arange(1, 10).reshape(3,3)
A

np.dot(np.dot(x, A), x)


I am working on the file "06. 기초 선형대수/04. NumPy를 활용한 선형대수 입문.ipynb".
The first task is:
제곱합
데이터 분석시에 분산(variance), 표준 편차(standard deviation)을 구하는 경우에는 각각의 데이터를 제곱한 값을 모두 더하는 계산 즉 제곱합(sum of squares)을 계산하게 된다. 이 경우에도 벡터의 곱을 사용하여 $x^Tx$로 쓸 수 있다.
$$
x^T x =
\begin{bmatrix}
x_{1} & x_{2} & \cdots & x_{N}
\end{bmatrix}
\begin{bmatrix}
x_{1} \
x_{2} \
\vdots \
x_{N} \
\end{bmatrix} = \sum_{i=1}^{N} x_i^2
$$
행렬의 곱셈
벡터의 곱셈을 정의한 후에는 다음과 같이 행렬의 곱셈을 정의할 수 있다.
$A$ 행렬과 $B$ 행렬을 곱한 결과인 $C$ 행렬의 $i$번째 행, $j$번째 열의 원소의 값은 $A$ 행렬의 $i$번째 행 벡터 $a_i^T$와 $B$ 행렬의 $j$번째 열 벡터 $b_j$의 곱으로 계산된 숫자이다.
$$ C = AB \; \rightarrow \; [c_{ij}] = a_i^T b_j $$
이 정의가 성립하려면 앞의 행렬 $A$의 열의 수가 뒤의 행렬 $B$의 행의 수와 일치해야만 한다.
$$ A \in \mathbb{R}^{N \times L} , \; B \in \mathbb{R}^{L \times M} \;  \rightarrow \; AB \in \mathbb{R}^{N \times M} $$
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/04. NumPy를 활용한 선형대수 입문.ipynb".
The first task is:
특수한 행렬
몇가지 특수한 행렬에 대해서는 별도의 이름이 붙어있다.
행렬에서 행의 숫자와 열의 숫자가 같은 위치를 대각(diagonal)이라고 하고 대각 위치에 있지 않은 것들은 비대각(off-diagonal)이라고 한다. 모든 비대각 요소가 0인 행렬을 대각 행렬(diagonal matrix)이라고 한다.
$$ D \in \mathbb{R}^{N \times N} $$
$$
D =
\begin{bmatrix}
D_{1} & 0 & \cdots & 0 \
0 & D_{2} & \cdots & 0 \
\vdots & \vdots & \ddots & \vdots \
0 & 0 & \cdots & D_{N} \
\end{bmatrix}
$$
NumPy로 대각행렬을 생성하려면 diag 명령을 사용한다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/04. NumPy를 활용한 선형대수 입문.ipynb".
The first task is:
행렬의 행 표기법과 열 표기법
전치 연산과 행 벡터, 열 벡터를 이용하면 행렬을 다음과 같이 복수의 열 벡터들 $c_i$, 또는 복수의 열 벡터들 $r_j^T$ 을 합친(concatenated) 형태로 표기할 수도 있다.
$$
X
=
\begin{bmatrix}
c_1 & c_2 & \cdots & c_M
\end{bmatrix}
=
\begin{bmatrix}
r_1^T \ r_2^T \ \vdots \ r_N^T
\end{bmatrix}
$$
$$ X \in \mathbb{R}^{N\times M} ,\;\;\; c_i \in R^{N \times 1} \; (i=1,\cdots,M) ,\;\;\; r_j \in R^{M \times 1} \; (j=1,\cdots,N) $$
행렬 덧셈과 뺄셈
행렬의 덧셈과 뺄셈은 같은 크기를 가진 두개의 행렬에 대해 정의되며 각각의 원소에 대해 덧셈과 뺄셈을 하면 된다. 이러한 연산을 element-wise 연산이라고 한다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/05. 행렬의 연산과 성질.ipynb".
The first task is:
대각 성분
대각 성분(trace) 행렬의 특성을 결정하는 숫자 중 하나로 정방 행렬(square matrix)에 대해서만 정의되며 다음과 같이 대각 성분(diaginal)의 합으로 계산된다.
$$ \operatorname{tr}(A) = a_{11} + a_{22} + \dots + a_{nn}=\sum_{i=1}^{n} a_{ii} $$
대각 성분은 다음과 같은 성질을 지닌다.
$$ \text{tr} (cA) = c\text{tr} (A) $$
$$ \text{tr} (A^T) = \text{tr} (A) $$
$$ \text{tr} (A + B) = \text{tr} (A) + \text{tr} (B)$$
$$ \text{tr} (AB) = \text{tr} (BA) $$
$$ \text{tr} (ABC) = \text{tr} (BCA) = \text{tr} (CAB) $$
실수는 그 자체가 trace임
특히 마지막 성질은 trace trick이라고 하여 이차 형식(quadratic form)의 값을 구하는데 유용하게 사용된다.
$$ x^TAx = \text{tr}(x^TAx) = \text{tr}(Axx^T)  = \text{tr}(xx^TA) $$
NumPy에서는 trace 명령으로 trace를 계산할 수 있다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/05. 행렬의 연산과 성질.ipynb".
The first task is:
전치 행렬과 대칭 행렬
전치 연산을 통해서 얻어진 행렬을 전치 행렬(transpose matrix)이라고 한다.
$$ [\mathbf{A}^\mathrm{T}]{ij} = [\mathbf{A}]{ji} $$
만약 전치 행렬과 원래의 행렬이 같으면 대칭 행렬(symmetric matrix)이라고 한다.
$$ A^\mathrm{T} = A $$
전치 연산은 다음과 같은 성질을 만족한다.
$$ ( A^\mathrm{T} ) ^\mathrm{T} = A  $$
$$ (A+B) ^\mathrm{T} = A^\mathrm{T} + B^\mathrm{T} $$
$$ \left( A B \right) ^\mathrm{T} = B^\mathrm{T} A^\mathrm{T}  $$
$$ \det(A^\mathrm{T}) = \det(A) $$
$$ (A^\mathrm{T})^{-1} = (A^{-1})^\mathrm{T} $$
지수 행렬
행렬 $A$에 대해 다음과 같은 급수로 만들어지는 행렬 $e^A=\exp A$ 를 지수 행렬(exponential matrix)이라고 한다.
A가 행렬인 경우임
테일러 시리즈.
$$ e^X = \sum_{k=0}^\infty \dfrac{X^k}{k!} = I + X + \dfrac{1}{2}X^2 + \dfrac{1}{3!}X^3 + \cdots $$
지수 행렬은 다음과 같은 성질을 만족한다.
$$ e^0 = I $$
$$ e^{aX} e^{bX} =  e^{(a+b)X} $$
$$ e^X e^{-X} = I $$
$$ XY = YX  \;\; \rightarrow \;\; e^Xe^Y = e^Ye^X = e^{X+Y} $$
로그 행렬
행렬 $A$에 대해 다음과 같은 급수로 만들어지는 행렬 $B=e^A$ 가 존재할 때, $A$를 $B$에 대한 로그 행렬이라고 하고 다음과 같이 표기한다.
$$ A = \log B $$
로그 행렬은 다음과 같은 성질은 만족한다.
만약 행렬 $A$, $B$가 모두 양-한정(positive definite)이고 $AB=BA$이면
$$ AB = e^{\ln(A)+\ln(B)} $$
만약 행렬 $A$의 역행렬이 존재하면
$$ A^{-1} = e^{-\ln(A)} $$
지수 행렬이나 로그 행렬은 NumPy에서 계산할 수 없다. SciPy의 linalg 서브패키지의 expm, logm 명령을 사용한다.
Can you write Python code for it?

A = np.array([[1.0, 3.0], [1.0, 4.0]])
A

B = sp.linalg.logm(A)
B

sp.linalg.expm(B)


I am working on the file "06. 기초 선형대수/05. 행렬의 연산과 성질.ipynb".
The first task is:
행렬식
정방 행렬 $A$의 행렬식(determinant) $\det (A)$ 는 Laplace formula라고 불리는 재귀적인 방법으로 정의된다.
이 식에서 $a_{i,j}$는 $A$의 i행, j열 원소이고 $M_{i,j}$은 정방 행렬 $A$ 에서 i행과 j열을 지워서 얻어진 행렬의 행렬식이다.
$$ \det(A) = \sum_{j=1}^n (-1)^{i+j} a_{i,j} M_{i,j} $$
행렬식은 다음과 같은 성질을 만족한다.
$$ \det(I) = 1 $$
$$ \det(A^{\rm T}) = \det(A) $$
$$ \det(A^{-1}) = \frac{1}{\det(A)}=\det(A)^{-1} $$
$$ \det(AB) = \det(A)\det(B) $$
$$ A \in \mathbf{R}^n \;\;\; \rightarrow \;\;\; \det(cA) = c^n\det(A) $$
또한 역행렬은 행렬식과 다음과 같은 관계를 가진다.
$$ A^{-1} = \dfrac{1}{\det A} M = \dfrac{1}{\det A}
\begin{bmatrix}
M_{1,1}&\cdots&M_{1,n}\
\vdots&\ddots&\vdots\
M_{n,1}&\cdots&M_{n,n}\
\end{bmatrix}
$$
NumPy에서는 linalg 서브패키지의 det 명령으로 det를 계산할 수 있다.
Can you write Python code for it?

A = np.array([[1, 2], [3, 4]])
A

np.linalg.det(A)


I am working on the file "06. 기초 선형대수/06. 연립방정식과 역행렬.ipynb".
The first task is:
위 해결 방법에는 두 가지 의문이 존재한다. 우선 역행렬이 존재하는지 어떻게 알 수 있는가? 또 두 번째 만약 미지수의 수와 방정식의 수가 다르다면 어떻게 되는가?
행렬식
우선 역행렬이 존재하는지 알아보는 방법의 하나로 행렬식(determinant)라는 정방 행렬의 특징을 계산하는 방법이다. 행렬 $A$ 에 대한 행렬식은 $\text{det}A$라는 기호로 표기한다.
행렬식(determinant)의 수학적인 정의는 상당히 복잡하므로 여기에서는 생략한다. 다만 몇가지 크기의 정방 행렬에 대해서는 다음과 같은 수식으로 구할 수 있다.

1×1 행렬의 행렬식

$$\det\begin{bmatrix}a\end{bmatrix}=a$$

2×2 행렬의 행렬식
$$\det\begin{bmatrix}a&b\c&d\end{bmatrix}=ad-bc$$

3×3 행렬의 행렬식
$$\det\begin{bmatrix}a&b&c\d&e&f\g&h&i\end{bmatrix}=aei+bfg+cdh-ceg-bdi-afh$$

NumPy에서는 det 명령으로 행렬식의 값을 구할 수 있다.
Can you write Python code for it?

np.random.seed(0)
A = np.random.randn(3, 3)
A

np.linalg.det(A)


I am working on the file "06. 기초 선형대수/06. 연립방정식과 역행렬.ipynb".
The first task is:
행렬식과 역행렬 사이에는 다음의 관계가 있다.
 행렬식의 값이 0이 아니면 역행렬이 존재한다. 반대로 역행렬이 존재하면 행렬식의 값은 0이 아니다.
최소 자승 문제
연립 방정식은 다음과 같은 세 종류가 있다.

미지수의 수가 방정식의 수와 같다. ($N = M$)
미지수의 수가 방정식의 수보다 적다. ($N < M$)
미지수의 수가 방정식의 수보다 많다. ($N > M$)

1번의 경우는 앞에서 다루었다. 2번의 경우에는 너무 많은 해가 존재할 수 있다. 3번의 경우에는 2번과 반대로 모든 조건을 만족하는 해가 하나도 존재할 수 없을 수도 있다.
그런데 데이터 분석 문제에서는 $A$ 를 feature matrix, $x$ 를 가중치 벡터 $w$ 라고 보았을 때 데이터의 수가 가중치의 갯수보다 많은 경우가 일반적이다. 다만 이 때는 방정식이 정확하게 등호를 이루기를 바라지는 않는다. 즉, 대략적으로만 좌변과 우변이 비슷하면 되는 경우이다.
$$ Ax \approx b $$
이 경우에는 좌변과 우변의 차이를 최소하하는 문제로 바꾸어 풀 수 있다. (오차 측정)
$$ e = Ax-b $$
$$ e^Te = (Ax-b)^T(Ax-b) $$
$$ x^* = \text{arg} \min_x e^Te = \text{arg} \min_x  \; (Ax-b)^T(Ax-b) $$
이러한 문제를 최소 자승(Least Square) 문제라고 한다. 그러나 정방행렬이 아님
최소 자승 문제의 답은 $A^TA$ 는 항상 정방행렬이 된다는 점을 사용하여  다음과 같이 풀 수 있다.
$$ Ax = b $$
$$ A^TAx = A^Tb $$
$$ (A^TA)x = A^Tb $$
$$ x = (A^TA)^{-1}A^T b $$
$$ x = ((A^TA)^{-1}A^T) b $$
이 값이 최소 자승 문제의 답이 된다는 것은 행렬의 미분을 사용하여 증명할 수 있다. 여기에서 행렬 $(A^TA)^{-1}A^T$ 를 행렬 $A$ 의 의사 역행렬(pseudo inverse)라고 하며 다음과 같이 $ A^{+}$ 로 표기하기도 한다.
$$ A^{+} = (A^TA)^{-1}A^T $$
NumPy의 lstsq 명령은 사실 이러한 최소 자승 문제를 푸는 명령이다.
Can you write Python code for it?

A = np.array([[2, 0], [-1, 1], [0, 2]])
A

b = np.array([[1], [0], [-1]])
b

Apinv = np.dot(np.linalg.inv(np.dot(A.T, A)), A.T) # p.inverse() ? 이런 명령
Apinv

x = np.dot(Apinv, b)
x

np.dot(A, x) - b

x, resid, rank, s = np.linalg.lstsq(A, b) # 정방행렬이 아닌 경우도 사용이 가능함. resid = 에러, rank
x


I am working on the file "06. 기초 선형대수/07. 벡터 공간.ipynb".
The first task is:
벡터의 길이
벡터 $a$ 의 길이를 놈(norm) $\| a \|$ 이라고 하며 다음과 같이 계산할 수 있다.
$$ \| a \| = \sqrt{a^T a } = \sqrt{a_1^2 + \cdots + a_K^2} $$
numpy의 linalg 서브 패키지의 norm 명령으로 벡터의 길이를 계산할 수 있다.
Can you write Python code for it?


I am working on the file "06. 기초 선형대수/07. 벡터 공간.ipynb".
The first task is:
벡터의 합
벡터와 벡터의 합은 벡터가 된다.
$$
a = \begin{bmatrix}1 \ 2\end{bmatrix} ,\;\;
b = \begin{bmatrix}2 \ 1\end{bmatrix} \;\;\; \rightarrow \;\;\;
c = a + b = \begin{bmatrix}3 \ 3\end{bmatrix} \;\;
$$
Can you write Python code for it?

a = np.array([1, 2])
b = np.array([2, 1])
c = a + b

plt.annotate('', xy=a, xytext=(0,0), arrowprops=dict(facecolor='gray'))
plt.annotate('', xy=b, xytext=(0,0), arrowprops=dict(facecolor='gray'))
plt.annotate('', xy=c, xytext=(0,0), arrowprops=dict(facecolor='black'))

plt.plot(0, 0, 'ro', ms=10)
plt.plot(a[0], a[1], 'ro', ms=10)
plt.plot(b[0], b[1], 'ro', ms=10)
plt.plot(c[0], c[1], 'ro', ms=10)
plt.plot([a[0], c[0]], [a[1], c[1]], 'k--')
plt.plot([b[0], c[0]], [b[1], c[1]], 'k--')

plt.text(0.35, 1.15, "$a$", fontdict={"size": 18})
plt.text(1.15, 0.25, "$b$", fontdict={"size": 18})
plt.text(1.25, 1.45, "$c$", fontdict={"size": 18})

plt.xticks(np.arange(-2, 4))
plt.yticks(np.arange(-1, 4))
plt.xlim(-1.4, 4.4)
plt.ylim(-0.6, 3.8)
plt.show()


I am working on the file "06. 기초 선형대수/07. 벡터 공간.ipynb".
The first task is:
좌표 변환
새로운 기저 벡터를에 대해 벡터 투영을 계산하는 것을 좌표 변환(coordinate transform)이라고 한다.
좌표 변환은 새로운 기저 벡터로 이루어진 변환 행렬(transform matrix) $A$ 와의 내적으로 계산한다.
$$ Aa' = a $$
$$ a' = A^{-1}a $$
예를 들어, 기존의 기저 벡터가
$$
e_1 = \begin{bmatrix}1 \ 0\end{bmatrix} ,\;\;
e_2 = \begin{bmatrix}0 \ 1\end{bmatrix} \;\;
$$
이면 벡터 $a$는 사실
$$
a = \begin{bmatrix}2 \ 2\end{bmatrix} = 2 \begin{bmatrix}1 \ 0\end{bmatrix} + 2 \begin{bmatrix}0 \ 1 \end{bmatrix} = 2 e_1 + 2 e_2
$$
새로운 기저 벡터가
$$
g_1 = \begin{bmatrix} \dfrac{1}{\sqrt{2}} \ \dfrac{1}{\sqrt{2}} \end{bmatrix} ,\;\;
g_2 = \begin{bmatrix} -\dfrac{1}{\sqrt{2}} \ \dfrac{1}{\sqrt{2}} \end{bmatrix} ,\;\;
$$
이면 벡터 $a$의 좌표는 다음과 같이 바뀐다.
$$
a = \begin{bmatrix}2 \ 2\end{bmatrix} \;\;\;\; \rightarrow \;\;\;\;
a' = A^{-1}a =
\begin{bmatrix}
e'_1 & e'_2
\end{bmatrix}
a
=
\begin{bmatrix}
\dfrac{1}{\sqrt{2}} & -\dfrac{1}{\sqrt{2}} \
\dfrac{1}{\sqrt{2}} &  \dfrac{1}{\sqrt{2}}
\end{bmatrix}^{-1}
\begin{bmatrix}2 \ 2\end{bmatrix}
=
\begin{bmatrix}
\dfrac{1}{\sqrt{2}} & \dfrac{1}{\sqrt{2}} \
-\dfrac{1}{\sqrt{2}} & \dfrac{1}{\sqrt{2}}
\end{bmatrix}
\begin{bmatrix}2 \ 2\end{bmatrix}
= \begin{bmatrix}2\sqrt{2}\0\end{bmatrix}
$$
Can you write Python code for it?

e1 = np.array([1, 0])
e2 = np.array([0, 1])
a = np.array([2, 2])
g1 = np.array([1, 1])/np.sqrt(2)
g2 = np.array([-1, 1])/np.sqrt(2)

plt.annotate('', xy=e1, xytext=(0,0), arrowprops=dict(facecolor='green'))
plt.annotate('', xy=e2, xytext=(0,0), arrowprops=dict(facecolor='green'))
plt.annotate('', xy=g1, xytext=(0,0), arrowprops=dict(facecolor='red'))
plt.annotate('', xy=g2, xytext=(0,0), arrowprops=dict(facecolor='red'))
plt.annotate('', xy=a, xytext=(0,0), arrowprops=dict(facecolor='gray', alpha=0.5))

plt.plot(0, 0, 'ro', ms=10)
plt.plot(a[0], a[1], 'ro', ms=10)

plt.text(1.05, 1.35, "$a$", fontdict={"size": 18})
plt.text(-0.2, 0.5, "$e_1$", fontdict={"size": 18})
plt.text(0.5, -0.2, "$e_2$", fontdict={"size": 18})
plt.text(0.2, 0.5, "$g_1$", fontdict={"size": 18})
plt.text(-0.6, 0.2, "$g_2$", fontdict={"size": 18})

plt.xticks(np.arange(-2, 4))
plt.yticks(np.arange(-1, 4))
plt.xlim(-1.5, 3.5)
plt.ylim(-0.5, 3)
plt.show()

A = np.vstack([g1, g2]).T
A

Ainv = np.linalg.inv(A)
Ainv

Ainv.dot(a)


I am working on the file "06. 기초 선형대수/07. 벡터 공간.ipynb".
The first task is:
직선
벡터 공간에서 직선은 다음과 같은 함수로 표현할 수 있다.
$$
f(x) = w^T(x - w) = w^Tx - w^Tw = w^Tx - \| w \|^2 = w^Tx - w_0 = 0
$$
$x$는 직선 상의 점을 나타내는 벡터이고 $w$는 원점으로부터 직선까지 이어지는 수직선을 나타내는 벡터이다.
$x-w$ 벡터가 $w$ 벡터와 수직이라는 것은 $x$가 가리키는 점과 $w$가 가리키는 점을 이은 선이 $w$와 수직이라는 뜻이다.
예를 들어
$$
w = \begin{bmatrix}1 \ 2\end{bmatrix} ,\;\;
w_0 = 5
$$
일 때
$$
\begin{bmatrix}1 & 2\end{bmatrix} \begin{bmatrix}x_1 \ x_2 \end{bmatrix} - 5 = x_1 + 2x_2 - 5 = 0
$$
이면 벡터 $w$가 가리키는 점 (1, 2)를 지나면서 벡터 $w$에 수직인 선을 뜻한다.
Can you write Python code for it?

w = np.array([1, 2])
x1 = np.array([3, 1])
x2 = np.array([-1, 3])
w0 = 5

plt.annotate('', xy=w, xytext=(0,0), arrowprops=dict(facecolor='red'))
plt.annotate('', xy=x1, xytext=(0,0), arrowprops=dict(facecolor='gray'))
plt.annotate('', xy=x2, xytext=(0,0), arrowprops=dict(facecolor='gray'))

plt.plot(0, 0, 'ro', ms=10)
plt.plot(w[0], w[1], 'ro', ms=10)
plt.plot(x1[0], x1[1], 'ro', ms=10)
plt.plot(x2[0], x2[1], 'ro', ms=10)
plt.plot([-3, 5], [4, 0], 'r-', lw=5)

plt.text(0.35, 1.15, "$w$", fontdict={"size": 18})
plt.text(1.55, 0.25, "$x_1$", fontdict={"size": 18})
plt.text(-0.9, 1.40, "$x_2$", fontdict={"size": 18})

plt.xticks(np.arange(-2, 4))
plt.yticks(np.arange(-1, 4))
plt.xlim(-1.7, 4.2)
plt.ylim(-0.5, 3.5)
plt.show()


I am working on the file "06. 기초 선형대수/07. 벡터 공간.ipynb".
The first task is:
직선과 점의 거리
직선 $ w^Tx - w_0 = 0 $ 과 이 직선 위에 있지 않은 점 $x'$의 거리는 단위 벡터 $\dfrac{w}{\|w\|}$에 대한 $x'$의 투영에서 $\|w\|$를 뺀 값의 절대값이다. 따라서 다음과 같이 정리할 수 있다.
$$
\left| \dfrac{w^Tx'}{\|w\|} - \|w\| \right| = \dfrac{\left|w^Tx' - \|w\|^2 \right|}{\|w\|}= \dfrac{\left|w^Tx' - w_0 \right|}{\|w\|}
$$
벡터의 선형 종속과 선형 독립
벡터들의 선형 조합이 0이 되는 모두 0이 아닌 스칼라값들이 존재하면 그 벡터들은 선형 종속(linearly dependent)이라고 한다.
$$
a = \begin{bmatrix}1 \ 2\end{bmatrix} ,\;\;
b = \begin{bmatrix}3 \ 3\end{bmatrix} \;\;
c = \begin{bmatrix}10 \ 14\end{bmatrix} \;\;
$$
$$
2a  + b - \frac{1}{2}c = 0
$$
Can you write Python code for it?


I am working on the file "06.List_it_out.ipynb".
The first task is:
But wait, there's more!

set_a.add(x): add a value to a set
set_a.remove(x): remove a value from a set
set_a - set_b: return values in a but not in b.
set_a.difference(set_b): same as set_a - set_b
set_a | set_b: elements in a or b. Equivalent to set_a.union(set_b)
set_a & set_b: elements in both a and b. Equivalent to set_a.intersection(set_b)
set_a ^ set_b: elements in a or b but not both. Equivalent to set_a.symmetric_difference(set_b)
set_a <= set_b: tests whether every element in set_a is in set_b. Equivalent to set_a.issubset(set_b)
Can you write Python code for it?

set_b = {1,2,3}
print(set_a - set_b)
print(set_a.difference(set_b))


I am working on the file "06.List_it_out.ipynb".
The first task is:
Common Dictionary Operations
Can you write Python code for it?

dict_1 = {"a":1, "b":2, "c":3, "d":4}
print(dict_1)

dict_1.keys()

dict_1.values()

dict_1.pop("d")
print(dict_1)

fav_book.pop("awesome")
fav_book


I am working on the file "06.List_it_out.ipynb".
The first task is:
Exercise

Convert the passage below into a list after replacing all punctuation
Who is mentioned more times - Sherlock or Moriarty?
How many times does the author refer to himself? (Hint: Count the use of the word 'my')
Can you write Python code for it?

passage = """It is with a heavy heart that I take up my pen to write these the last words in which I shall ever record the singular gifts by which my friend Mr. Sherlock Holmes was distinguished. In an incoherent and, as I deeply feel, an entirely inadequate fashion, I have endeavored to give some account of my strange experiences in his company from the chance which first brought us together at the period of the “Study in Scarlet,” up to the time of his interference in the matter of the “Naval Treaty”—an interference which had the unquestionable effect of preventing a serious international complication. It was my intention to have stopped there, and to have said nothing of that event which has created a void in my life which the lapse of two years has done little to fill. My hand has been forced, however, by the recent letters in which Colonel James Moriarty defends the memory of his brother, and I have no choice but to lay the facts before the public exactly as they occurred. I alone know the absolute truth of the matter, and I am satisfied that the time has come when no good purpose is to be served by its suppression. As far as I know, there have been only three accounts in the public press: that in the Journal de Geneve on May 6th, 1891, the Reuter’s despatch in the English papers on May 7th, and finally the recent letter to which I have alluded. Of these the first and second were extremely condensed, while the last is, as I shall now show, an absolute perversion of the facts. It lies with me to tell for the first time what really took place between Professor Moriarty and Mr. Sherlock Holmes.
It may be remembered that after my marriage, and my subsequent start in private practice, the very intimate relations which had existed between Holmes and myself became to some extent modified. He still came to me from time to time when he desired a companion in his investigation, but these occasions grew more and more seldom, until I find that in the year 1890 there were only three cases of which I retain any...


I am working on the file "06.List_it_out.ipynb".
The first task is:
Exercise
An analyst is looking at two portfolios, and wants to identify the unique ones.

pf1 = {"AA", "AAC", "AAP", "ABB", "AC", "ACCO", "AAPL", "AZO", "ZEN", "PX", "GS"}
pf2 = {"AA", "GRUB", "AAC", "GWR", "AAP", "C", "AC", "CVS"}

Write code for the following:
* Find the stocks in either pf1 or pf2, but not in both. (Hint: Symmetric Difference)
* Find the stocks in both portfolios (Hint: Intersection)
* Create a third portfolio named pf3, which has pf1 and pf2 combined (Hint: Union)
* Market conditions have changed, let's drop GRUB and CVS from pf3 and add IBM (Hint: set_a.remove(x) and set_a.add(x) )
Can you write Python code for it?

pf1 = {"AA", "AAC", "AAP", "ABB", "AC", "ACCO", "AAPL", "AZO", "ZEN", "PX", "GS"}
pf2 = {"AA", "GRUB", "AAC", "GWR", "AAP", "C", "AC", "CVS"}

# Find the stocks in either pf1 or pf2, but not in both.

# Find the stocks in both portfolios

# Create a third portfolio named pf3, which has pf1 and pf2 combined

# Market conditions have changed, let's drop GRUB and CVS from pf3 and add IBM


I am working on the file "06.List_it_out.ipynb".
The first task is:
Exercise
Print out the second and last items of the list within the list more_info

all_info = ["Sherlock", True, 42]
more_info = ["Watson", "Hooley", all_info]
Can you write Python code for it?


I am working on the file "06.List_it_out.ipynb".
The first task is:
Exercise
list_a = [21,14,7,19,15,47,42,55,97,92]
* Find the average of list_a
* Find the median of list_a
If you need a refresher on how to find the average (or mean) and median, we will cover that later.
Can you write Python code for it?