<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
Step2:  Making Python faster
This homework provides practice in making Python code faster. Note that we start with functions that already use idiomatic numpy (which are about two orders of magnitude faster than the pure Python versions).
Functions to optimize
Step3:  Data set for classification
Step4:  Using gradient descent for classification by logistic regression
Step5:  1. Rewrite the logistic function so it only makes one np.exp call. Compare the time of both versions with the input x given below using the @timeit magic. (10 points)
<ASSISTANT_TASK:>
Python Code:
def logistic(x):
    Logistic function.
    return np.exp(x)/(1 + np.exp(x))
def gd(X, y, beta, alpha, niter):
    Gradient descent algorihtm.
    n, p = X.shape
    Xt = X.T
    for i in range(niter):
        y_pred = logistic(X @ beta)
        epsilon = y - y_pred
        grad = Xt @ epsilon / n
        beta += alpha * grad
    return beta
x = np.linspace(-6, 6, 100)
plt.plot(x, logistic(x))
pass
Explanation: Making Python faster
This homework provides practice in making Python code faster. Note that we start with functions that already use idiomatic numpy (which are about two orders of magnitude faster than the pure Python versions).
Functions to optimize
End of explanation
n = 10000
p = 2
X, y = make_blobs(n_samples=n, n_features=p, centers=2, cluster_std=1.05, random_state=23)
X = np.c_[np.ones(len(X)), X]
y = y.astype('float')
Explanation: Data set for classification
End of explanation
# initial parameters
niter = 1000
α = 0.01
β = np.zeros(p+1)
# call gradient descent
β = gd(X, y, β, α, niter)
# assign labels to points based on prediction
y_pred = logistic(X @ β)
labels = y_pred > 0.5
# calculate separating plane
sep = (-β[0] - β[1] * X)/β[2]
plt.scatter(X[:, 1], X[:, 2], c=labels, cmap='winter')
plt.plot(X, sep, 'r-')
pass
Explanation: Using gradient descent for classification by logistic regression
End of explanation
np.random.seed(123)
n = int(1e7)
x = np.random.normal(0, 1, n)
Explanation: 1. Rewrite the logistic function so it only makes one np.exp call. Compare the time of both versions with the input x given below using the @timeit magic. (10 points)
End of explanation
<END_TASK>