Skip to content

Homework 3

Main Part

Code

Coursera Q10

from math import exp
import numpy as np

def E_uv(u, v):
    return -2.0

def E_uu(u, v):
    return exp(u) + v * v * exp(u * v) + 2

def E_vv(u, v):
    return 4 * exp(2 * v) + 4

def E_u(u, v):
    return exp(u) + exp(u * v) * v + 2 * u - 2 * v - 3

def E_v(u, v):
    return 2 * exp(2 * v) - 2 * u + 4 * v - 2

def E(u, v):
    return exp(u) + exp(2 * v) + exp(u * v) + u * u - 2 * u * v + 2 * v * v - 3 * u - 2 * v

x = [0, 0]
for _ in range(5):
    print(E(x[0], x[1]))
    u = x[0]
    v = x[1]
    H = np.array([[E_uu(u, v), E_uv(u, v)], [E_uv(u, v), E_vv(u, v)]])
    G = np.array([[E_u(u, v),], [E_v(u, v),]])
    X = np.linalg.inv(H) @ G
    x[0] -= X[0][0]
    x[1] -= X[1][0]

print(E(x[0], x[1]))

Coursera Q13

import random
import numpy as np

N = 1000
T = 1000

def sign(x):
    return 1 if x > 0.0 else -1

def f(x1, x2):
    return sign(x1 ** 2 + x2 ** 2 - 0.6)

def gen_data():
    X = []
    Y = []
    for _ in range(N):
        X.append([1.0, ] + [np.random.uniform(-1.0, 1.0) for i in range(2)])

    for x in X:
        y = f(x[1], x[2])
        Y.append([y if random.random() >= 0.1 else -y, ])

    return np.array(X), np.array(Y)

def calc_ein(X, Y, W):
    P = X @ W
    err = 0
    for y, y_hat in zip(Y, P):
        if sign(y_hat[0]) != y[0]:
            err += 1
    return err / N

def main():
    avg = 0.0
    for t in range(T):
        X, Y = gen_data()
        W = np.linalg.pinv(X) @ Y
        E_in = calc_ein(X, Y, W)
        avg += E_in / T
    print(avg)

if __name__ == '__main__':
    main()

Coursera Q14

import random
import numpy as np

N = 1000
T = 1000

G = [_ for _ in range(5)]

G[0] = np.array([[-1,], [-0.05,], [0.08,], [0.13,], [1.5,], [15.0,]])
G[1] = np.array([[-1,], [-0.05,], [0.08,], [0.13,], [1.5,], [1.5,]])
G[2] = np.array([[-1,], [-1.5,], [0.08,], [0.13,], [0.05,], [1.5,]])
G[3] = np.array([[-1,], [-1.5,], [0.08,], [0.13,], [0.05,], [0.05,]])
G[4] = np.array([[-1,], [-0.05,], [0.08,], [0.13,], [15.0,], [1.5,]])

def sign(x):
    return 1 if x > 0.0 else -1

def f(x1, x2):
    return sign(x1 ** 2 + x2 ** 2 - 0.6)

def gen_data():
    X = []
    Y = []
    for _ in range(N):
        X.append([1.0, ] + [np.random.uniform(-1.0, 1.0) for i in range(2)])

    for x in X:
        y = f(x[1], x[2])
        Y.append([y if random.random() >= 0.1 else -y, ])

    return np.array(X), np.array(Y)

def transform(X):
    Z = []
    for x in X:
        Z.append([1.0, x[1], x[2], x[1] * x[2], x[1] ** 2, x[2] ** 2])
    return np.array(Z)

def calc_ein(Z, Y, W):
    P = Z @ W
    err = 0
    for y, y_hat in zip(Y, P):
        if sign(y_hat[0]) != y[0]:
            err += 1
    return err / N

def main():
    X, Y = gen_data()
    Z = transform(X)
    W = np.linalg.pinv(Z) @ Y
    E_in = calc_ein(Z, Y, W)
    print(E_in)
    for i, g in enumerate(G):
        print(i, calc_ein(Z, Y, g))

if __name__ == '__main__':
    main()

Coursera Q15

import random
import numpy as np

N = 1000
T = 1000

G = [_ for _ in range(5)]

G[0] = np.array([[-1,], [-0.05,], [0.08,], [0.13,], [1.5,], [15.0,]])
G[1] = np.array([[-1,], [-0.05,], [0.08,], [0.13,], [1.5,], [1.5,]])
G[2] = np.array([[-1,], [-1.5,], [0.08,], [0.13,], [0.05,], [1.5,]])
G[3] = np.array([[-1,], [-1.5,], [0.08,], [0.13,], [0.05,], [0.05,]])
G[4] = np.array([[-1,], [-0.05,], [0.08,], [0.13,], [15.0,], [1.5,]])

def sign(x):
    return 1 if x > 0.0 else -1

def f(x1, x2):
    return sign(x1 ** 2 + x2 ** 2 - 0.6)

def gen_data():
    X = []
    Y = []
    for _ in range(N):
        X.append([1.0, ] + [np.random.uniform(-1.0, 1.0) for i in range(2)])

    for x in X:
        y = f(x[1], x[2])
        Y.append([y if random.random() >= 0.1 else -y, ])

    return np.array(X), np.array(Y)

def transform(X):
    Z = []
    for x in X:
        Z.append([1.0, x[1], x[2], x[1] * x[2], x[1] ** 2, x[2] ** 2])
    return np.array(Z)

def calc_err(Z, Y, W):
    P = Z @ W
    err = 0
    for y, y_hat in zip(Y, P):
        if sign(y_hat[0]) != y[0]:
            err += 1
    return err / N

def main():
    avg = 0.0
    for i in range(T):
        X, Y = gen_data()
        Z = transform(X)
        W = np.linalg.pinv(Z) @ Y
        Xtest, Ytest = gen_data()
        Ztest = transform(Xtest)
        avg += calc_err(Ztest, Ytest, W) / T
    print(avg)

if __name__ == '__main__':
    main()

Coursera Q18

import numpy as np

training_data_file_name = "hw3_train.dat"
test_data_file_name = "hw3_test.dat"

eta = 0.001
T = 2000
N = 0
dim = 20

def read_data(fname):
    X = []
    Y = []
    with open(fname, "r") as f:
        for ln in f.readlines():
            ln = ln.split()
            X.append([1.0,] + [ float(x) for x in ln[:-1] ])
            Y.append([int(ln[-1]),])
    global N
    N = len(X)
    return np.array(X), np.array(Y)

def theta(s):
    return 1.0 / (1.0 + np.exp(-s))

def train(X, Y):
    w = np.zeros(dim + 1)
    for _ in range(T):
        grad = np.zeros(dim + 1)
        for x, y in zip(X, Y):
            grad += -1.0 / N * theta(-y * np.dot(w, x)) * (y * x)
        w -= eta * grad
    return w

def calc_err(X, Y, W):
    P = X @ W
    err = 0
    for y, p in zip(Y, P):
        p = theta(p)
        yp = 1 if p > 0.5 else -1
        if yp != y:
            err += 1
    return err / N

def main():
    X, Y = read_data(training_data_file_name)
    W = train(X, Y)
    X, Y = read_data(test_data_file_name)
    E_out = calc_err(X, Y, W)
    print(E_out)

if __name__ == '__main__':
    main()

Coursera Q19

import numpy as np

training_data_file_name = "hw3_train.dat"
test_data_file_name = "hw3_test.dat"

eta = 0.01
T = 2000
N = 0
dim = 20

def read_data(fname):
    X = []
    Y = []
    with open(fname, "r") as f:
        for ln in f.readlines():
            ln = ln.split()
            X.append([1.0,] + [ float(x) for x in ln[:-1] ])
            Y.append([int(ln[-1]),])
    global N
    N = len(X)
    return np.array(X), np.array(Y)

def theta(s):
    return 1.0 / (1.0 + np.exp(-s))

def train(X, Y):
    w = np.zeros(dim + 1)
    for _ in range(T):
        grad = np.zeros(dim + 1)
        for x, y in zip(X, Y):
            grad += -1.0 / N * theta(-y * np.dot(w, x)) * (y * x)
        w -= eta * grad
    return w

def calc_err(X, Y, W):
    P = X @ W
    err = 0
    for y, p in zip(Y, P):
        p = theta(p)
        yp = 1 if p > 0.5 else -1
        if yp != y:
            err += 1
    return err / N

def main():
    X, Y = read_data(training_data_file_name)
    W = train(X, Y)
    Xtest, Ytest = read_data(test_data_file_name)
    E_out = calc_err(Xtest, Ytest, W)
    print(E_out)

if __name__ == '__main__':
    main()

Coursera Q20

import numpy as np

training_data_file_name = "hw3_train.dat"
test_data_file_name = "hw3_test.dat"

eta = 0.001
T = 2000
N = 0
dim = 20

def read_data(fname):
    X = []
    Y = []
    with open(fname, "r") as f:
        for ln in f.readlines():
            ln = ln.split()
            X.append([1.0,] + [ float(x) for x in ln[:-1] ])
            Y.append([int(ln[-1]),])
    global N
    N = len(X)
    return np.array(X), np.array(Y)

def theta(s):
    return 1.0 / (1.0 + np.exp(-s))

def train(X, Y):
    w = np.zeros(dim + 1)
    samples = [n % N for n in range(T)]
    for t, n in enumerate(samples):
        grad = -theta(-Y[n] * np.dot(w, X[n])) * (Y[n] * X[n])
        w -= eta * grad
    return w

def calc_err(X, Y, W):
    P = X @ W
    err = 0
    for y, p in zip(Y, P):
        p = theta(p)
        yp = 1 if p > 0.5 else -1
        if yp != y:
            err += 1
    return err / N

def main():
    X, Y = read_data(training_data_file_name)
    W = train(X, Y)
    Xtest, Ytest = read_data(test_data_file_name)
    E_out = calc_err(Xtest, Ytest, W)
    print(E_out)

if __name__ == '__main__':
    main()

Problem 7

import numpy as np
import matplotlib.pyplot as plt

training_data_file_name = "hw3_train.dat"
test_data_file_name = "hw3_test.dat"

T = 2000
dim = 20

class Problem7:
    def __init__(self):
        self.N = 0
        self.X = None
        self.Y = None
        self.Ntest = 0
        self.Xtest = None
        self.Ytest = None

    @staticmethod
    def read(fname, X, Y):
        with open(fname, "r") as f:
            for ln in f.readlines():
                ln = ln.split()
                X.append([1.0,] + [ float(x) for x in ln[:-1] ])
                Y.append([int(ln[-1]),])

    def read_data(self):
        self.X = []
        self.Y = []
        self.read(training_data_file_name, self.X, self.Y)
        self.N = len(self.X)
        self.X = np.array(self.X)
        self.Y = np.array(self.Y)

        self.Xtest = []
        self.Ytest = []
        self.read(test_data_file_name, self.Xtest, self.Ytest)
        self.Ntest = len(self.Xtest)
        self.Xtest = np.array(self.Xtest)
        self.Ytest = np.array(self.Ytest)

    @staticmethod
    def theta(s):
        return 1.0 / (1.0 + np.exp(-s))

    def calc_err(self, X, Y, W):
        P = X @ W
        err = 0
        for y, p in zip(Y, P):
            p = self.theta(p)
            yp = 1 if p > 0.5 else -1
            if yp != y:
                err += 1
        return err / self.N

    def trainGD(self):
        w = np.zeros(dim + 1)
        record = []
        for _ in range(T):
            grad = np.zeros(dim + 1)
            for x, y in zip(self.X, self.Y):
                grad += -1.0 / self.N * self.theta(-y * np.dot(w, x)) * (y * x)
            w -= 0.01 * grad
            record.append(self.calc_err(self.X, self.Y, w))
        self.GD_Ein = np.array(record)

    def trainSGD(self):
        w = np.zeros(dim + 1)
        record = []
        samples = [n % self.N for n in range(T)]
        for n in samples:
            grad = -self.theta(-self.Y[n] * np.dot(w, self.X[n])) * (self.Y[n] * self.X[n])
            w -= 0.001 * grad
            record.append(self.calc_err(self.X, self.Y, w))
        self.SGD_Ein = np.array(record)

    def plot(self):
        time = np.array([t for t in range(1, T+1)])
        #np.save("t_axis.npy", time)
        #np.save("gd_ein.npy", self.GD_Ein)
        #np.save("sgd_ein.npy", self.SGD_Ein)
        fig, ax = plt.subplots()
        ax.plot(time, self.GD_Ein, label=r"GD  ($\eta=0.01$)", color="steelblue", alpha=0.7, linewidth=2)
        ax.plot(time, self.SGD_Ein, label=r"SGD($\eta=0.001$)", color="skyblue", alpha=0.7, linewidth=2)
        plt.title(r"Comparison of $E_{in}(\mathbf{w}_t): $Gradient Descent(GD) v.s. Stochastic Gradient Descent(SGD)")
        plt.xlabel(r"$t$")
        plt.ylabel(r"$E_{in}(\mathbf{w}_t)$")
        plt.legend()
        plt.show()

def main():
    trainer = Problem7()
    trainer.read_data()
    trainer.trainGD()
    trainer.trainSGD()
    trainer.plot()

if __name__ == '__main__':
    main()

Problem 8

import numpy as np
import matplotlib.pyplot as plt

training_data_file_name = "hw3_train.dat"
test_data_file_name = "hw3_test.dat"

T = 2000
dim = 20

class Problem8:
    def __init__(self):
        self.N = 0
        self.X = None
        self.Y = None
        self.Ntest = 0
        self.Xtest = None
        self.Ytest = None

    @staticmethod
    def read(fname, X, Y):
        with open(fname, "r") as f:
            for ln in f.readlines():
                ln = ln.split()
                X.append([1.0,] + [ float(x) for x in ln[:-1] ])
                Y.append([int(ln[-1]),])

    def read_data(self):
        self.X = []
        self.Y = []
        self.read(training_data_file_name, self.X, self.Y)
        self.N = len(self.X)
        self.X = np.array(self.X)
        self.Y = np.array(self.Y)

        self.Xtest = []
        self.Ytest = []
        self.read(test_data_file_name, self.Xtest, self.Ytest)
        self.Ntest = len(self.Xtest)
        self.Xtest = np.array(self.Xtest)
        self.Ytest = np.array(self.Ytest)

    @staticmethod
    def theta(s):
        return 1.0 / (1.0 + np.exp(-s))

    def calc_err(self, X, Y, W):
        P = X @ W
        err = 0
        for y, p in zip(Y, P):
            p = self.theta(p)
            yp = 1 if p > 0.5 else -1
            if yp != y:
                err += 1
        return err / self.Ntest

    def trainGD(self):
        w = np.zeros(dim + 1)
        record = []
        for _ in range(T):
            grad = np.zeros(dim + 1)
            for x, y in zip(self.X, self.Y):
                grad += -1.0 / self.N * self.theta(-y * np.dot(w, x)) * (y * x)
            w -= 0.01 * grad
            record.append(self.calc_err(self.Xtest, self.Ytest, w))
        self.GD_Eout = np.array(record)

    def trainSGD(self):
        w = np.zeros(dim + 1)
        record = []
        samples = [n % self.N for n in range(T)]
        for n in samples:
            grad = -self.theta(-self.Y[n] * np.dot(w, self.X[n])) * (self.Y[n] * self.X[n])
            w -= 0.001 * grad
            record.append(self.calc_err(self.Xtest, self.Ytest, w))
        self.SGD_Eout = np.array(record)

    def plot(self):
        time = np.array([t for t in range(1, T+1)])
        #np.save("t_axis.npy", time)
        #np.save("gd_eout.npy", self.GD_Eout)
        #np.save("sgd_eout.npy", self.SGD_Eout)
        fig, ax = plt.subplots()
        ax.plot(time, self.GD_Eout, label=r"GD  ($\eta=0.01$)", color="purple", alpha=0.7, linewidth=2)
        ax.plot(time, self.SGD_Eout, label=r"SGD($\eta=0.001$)", color="orchid", alpha=0.7, linewidth=2)
        plt.title(r"Comparison of $E_{out}(\mathbf{w}_t): $Gradient Descent(GD) v.s. Stochastic Gradient Descent(SGD)")
        plt.xlabel(r"$t$")
        plt.ylabel(r"$E_{out}(\mathbf{w}_t)$")
        plt.legend()
        plt.show()

def main():
    trainer = Problem8()
    trainer.read_data()
    trainer.trainGD()
    trainer.trainSGD()
    trainer.plot()

if __name__ == '__main__':
    main()