<jupyter_start><jupyter_text>Imports<jupyter_code>import numpy as np
from scipy.optimize import minimize
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from IPython.display import HTML, Image
plt.style.use('ggplot')
params = {'legend.fontsize': '18',
          'axes.labelsize': '20',
          'axes.labelweight': 'bold',
          'axes.titlesize':'20',
          'xtick.labelsize':'18',
          'ytick.labelsize':'18'}
plt.rcParams.update(params)<jupyter_output><empty_output><jupyter_text>Functions<jupyter_code>def loss_lr(w, X, y):
    return np.sum(np.log(1 + np.exp(-y*(X@w))))

def loss_lr_grad(w, X, y):
    return -X.T @ (y/(1+np.exp(y*(X@w))))

def mk_fig():
    """
    Convenience function to plot figure canvas

    Returns
    -------
    fig, axes
        Figure and axes objects
    """
    fig, axes = plt.subplots(1, 1, figsize=(7, 7))
    axes.set_xlim(-1, 21)
    axes.set_ylim(-1.5, 1.5)
    axes.set_xlabel('x')
    axes.set_ylabel('y')

    return fig, axes<jupyter_output><empty_output><jupyter_text>Data<jupyter_code>np.random.seed(1)
x = np.concatenate((np.random.randint(0, 12, 10),
                    np.random.randint(8, 20, 10))
                  )
y = np.concatenate((np.ones((10,)) * -1,
                    np.ones(10,))
                  )
fig, axes = mk_fig()
mask = y == -1
colors = ['#E24A33', '#348ABD']

axes.scatter(x[mask], y[mask], s=100, label='Class 0', zorder=2)
axes.scatter(x[~mask], y[~mask], s=100, label='Class 1', zorder=2)

w0 = np.array([0])
w = minimize(lambda w: loss_lr(w, x[:, None], y), w0, jac=lambda w: loss_lr_grad(w, x[:, None], y)).x 
p = 1 / (1+np.exp(-w*x))
axes.plot(x, p, '-k')
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression(C=1e8)
lr.fit(x[:, None], y);
lr.coef_
lr.predict(x[:, None])
lr.predict_proba(x[:, None])<jupyter_output><empty_output><jupyter_text>Create and save animations<jupyter_code>fig, axes = mk_fig()
mask = y == 0
colors = ['#E24A33', '#348ABD']

def init():
    axes.scatter(X[mask, 0], X[mask, 1], s=100, c='#E24A33', label='Class 0', zorder=2)
    axes.scatter(X[~mask, 0], X[~mask, 1], s=100, c='#348ABD', label='Class 1', zorder=2)
    axes.scatter(xq[0], xq[1], s=200, facecolor='None', edgecolor='k', lw=2, label='Unknown', zorder=2)
    axes.legend(facecolor='#F0F0F0', framealpha=1)

def animate(i):
    if i == 0:
        axes.scatter(xq[0], xq[1], s=200, facecolor='None', edgecolor='k', lw=2, label='Unknown', zorder=2)
    if i == 1:
        k = closest_node(xq, X, i)
        axes.plot([xq[0], X[k,0]],
                  [xq[1], X[k,1]],
                  'k-', zorder=1)
        axes.scatter(xq[0], xq[1]+0.01, s=200, facecolor=colors[y[k[0]]], edgecolor='k', lw=2, zorder=2)
    elif i % 2 == 1:
        k = closest_node(xq, X, i)
        axes.plot([np.repeat(xq[0], 2), X[k[-2:],0]],
                  [np.repeat(xq[1], 2), X[k[-2:],1]],
                  'k-', zorder=1)
        if sum(y[k] == 0) > sum(y[k] == 1):
            axes.scatter(xq[0], xq[1]+0.01, s=200, facecolor=colors[0], edgecolor='k', lw=2, zorder=2)
        elif sum(y[k] == 1) > sum(y[k] == 0):
            axes.scatter(xq[0], xq[1]+0.01, s=200, facecolor=colors[1], edgecolor='k', lw=2, zorder=2)
        else:  # if equal counts, set to closest point's color
            axes.scatter(xq[0], xq[1]+0.01, s=200, facecolor=colors[y[k[0]]], edgecolor='k', lw=2, zorder=2)
            
plt.close(fig)
ani = animation.FuncAnimation(fig,
                              animate,
                              init_func=init,
                              frames=10,
                              interval=600)
ani.save('../gif/knn/knn.gif', writer='imagemagick', fps=1, dpi=75)
# HTML(ani.to_jshtml())<jupyter_output><empty_output><jupyter_text>View animations<jupyter_code>Image(url='../gif/knn/knn.gif')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.19963749352667012, 'fraction_numerical': 0.0479026411185914, 'mean_word_length': 2.9865841073271415, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '639643', 'license': 'MIT', 'n_tokens_mistral': 1682, 'n_tokens_neox': 1556, 'n_words': 287, 'path': 'ml-animations/notebooks/logistic_regression.ipynb', 'repo_name': 'TomasBeuzen/machine-learning-tutorials', 'size': '3862'}