<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 <a href="http
Step1:  The class <code>plot_error_surfaces</code> is just to help you visualize the data space and the parameter space during training and has nothing to do with PyTorch.
Step2:  Set the random seed
Step3:  <!--Empty Space for separating topics-->
<h2 id="Makeup_Data">Get Some Data</h2>
Create the <code>Data</code> class
Step4:  Make <code>Data</code> object
Step5:  <!--Empty Space for separating topics-->
<h2 id="Model_Cost">Create the Model and Total Loss Function (Cost)</h2>
Create a custom module for logistic regression
Step6:  Create a logistic regression object and print the parameters
Step7:  Create a <code>plot_error_surfaces</code> object to visualize the data space and the parameter space during training
Step8:  Create <code>DataLoader</code> object, cost or criterion function and <code>optimizer</code>
Step9:  <!--Empty Space for separating topics-->
<h2 id="BGD">Train the Model via Batch Gradient Descent</h2>
Train the model
Step10:  Get the actual class of each sample and calculate the accuracy on the test data.
<ASSISTANT_TASK:>
Python Code:
# Import the libraries we need for this lab
import numpy as np
import matplotlib.pyplot as plt 
from mpl_toolkits import mplot3d
import torch
from torch.utils.data import Dataset, DataLoader
import torch.nn as nn
Explanation: <a href="http://cocl.us/pytorch_link_top">
    <img src="https://cocl.us/Pytorch_top" width="750" alt="IBM 10TB Storage" />
</a> 
<img src="https://ibm.box.com/shared/static/ugcqz6ohbvff804xp84y4kqnvvk3bq1g.png" width="200" alt="cognitiveclass.ai logo" />
<h1>Logistic Regression Training Mean Square Error</h1>
<h2>Table of Contents</h2>
<p>In this lab, you will see what happens when you use the root mean square error cost or total loss function using random initialization for a parameter value.</p>
<ul>
    <li><a href="#Makeup_Data">Make Some Data</a></li>
    <li><a href="#Model_Cost">Create the Model and Cost Function the PyTorch way</a></li>
    <li><a href="#BGD">Train the Model: Batch Gradient Descent</a></li>
</ul>
<p>Estimated Time Needed: <strong>30 min</strong></p>
<hr>
<h2>Preparation</h2>
We'll need the following libraries:
End of explanation
# Create class for plotting and the function for plotting
class plot_error_surfaces(object):
    
    # Construstor
    def __init__(self, w_range, b_range, X, Y, n_samples = 30, go = True):
        W = np.linspace(-w_range, w_range, n_samples)
        B = np.linspace(-b_range, b_range, n_samples)
        w, b = np.meshgrid(W, B)    
        Z = np.zeros((30, 30))
        count1 = 0
        self.y = Y.numpy()
        self.x = X.numpy()
        for w1, b1 in zip(w, b):
            count2 = 0
            for w2, b2 in zip(w1, b1):
                Z[count1, count2] = np.mean((self.y - (1 / (1 + np.exp(-1 * (w2 * self.x + b2))))) ** 2)
                count2 += 1   
            count1 += 1
        self.Z = Z
        self.w = w
        self.b = b
        self.W = []
        self.B = []
        self.LOSS = []
        self.n = 0
        if go == True:
            plt.figure()
            plt.figure(figsize = (7.5, 5))
            plt.axes(projection = '3d').plot_surface(self.w, self.b, self.Z, rstride = 1, cstride = 1, cmap = 'viridis', edgecolor = 'none')
            plt.title('Loss Surface')
            plt.xlabel('w')
            plt.ylabel('b')
            plt.show()
            plt.figure()
            plt.title('Loss Surface Contour')
            plt.xlabel('w')
            plt.ylabel('b')
            plt.contour(self.w, self.b, self.Z)
            plt.show()
            
     # Setter
    def set_para_loss(self, model, loss):
        self.n = self.n + 1
        self.W.append(list(model.parameters())[0].item())
        self.B.append(list(model.parameters())[1].item())
        self.LOSS.append(loss)
    
    # Plot diagram
    def final_plot(self): 
        ax = plt.axes(projection = '3d')
        ax.plot_wireframe(self.w, self.b, self.Z)
        ax.scatter(self.W, self.B, self.LOSS, c = 'r', marker = 'x', s = 200, alpha = 1)
        plt.figure()
        plt.contour(self.w, self.b, self.Z)
        plt.scatter(self.W, self.B, c = 'r', marker = 'x')
        plt.xlabel('w')
        plt.ylabel('b')
        plt.show()
        
    # Plot diagram
    def plot_ps(self):
        plt.subplot(121)
        plt.ylim
        plt.plot(self.x, self.y, 'ro', label = "training points")
        plt.plot(self.x, self.W[-1] * self.x + self.B[-1], label = "estimated line")
        plt.plot(self.x, 1 / (1 + np.exp(-1 * (self.W[-1] * self.x + self.B[-1]))), label = 'sigmoid')
        plt.xlabel('x')
        plt.ylabel('y')
        plt.ylim((-0.1, 2))
        plt.title('Data Space Iteration: ' + str(self.n))
        plt.show()
        plt.subplot(122)
        plt.contour(self.w, self.b, self.Z)
        plt.scatter(self.W, self.B, c = 'r', marker = 'x')
        plt.title('Loss Surface Contour Iteration' + str(self.n))
        plt.xlabel('w')
        plt.ylabel('b')
        
# Plot the diagram
def PlotStuff(X, Y, model, epoch, leg = True):
    plt.plot(X.numpy(), model(X).detach().numpy(), label = 'epoch ' + str(epoch))
    plt.plot(X.numpy(), Y.numpy(), 'r')
    if leg == True:
        plt.legend()
    else:
        pass
Explanation: The class <code>plot_error_surfaces</code> is just to help you visualize the data space and the parameter space during training and has nothing to do with PyTorch.
End of explanation
# Set random seed
torch.manual_seed(0)
Explanation: Set the random seed:
End of explanation
# Create the data class
class Data(Dataset):
    
    # Constructor
    def __init__(self):
        self.x = torch.arange(-1, 1, 0.1).view(-1, 1)
        self.y = torch.zeros(self.x.shape[0], 1)
        self.y[self.x[:, 0] > 0.2] = 1
        self.len = self.x.shape[0]
        
    # Getter
    def __getitem__(self, index):      
        return self.x[index], self.y[index]
    
    # Get items
    def __len__(self):
        return self.len
Explanation: <!--Empty Space for separating topics-->
<h2 id="Makeup_Data">Get Some Data</h2>
Create the <code>Data</code> class
End of explanation
# Create Data object
data_set = Data()
Explanation: Make <code>Data</code> object
End of explanation
# Create logistic_regression class
class logistic_regression(nn.Module):
    
    # Construstor
    def __init__(self,n_inputs):
        super(logistic_regression, self).__init__()
        self.linear = nn.Linear(n_inputs, 1)
        
    # Prediction    
    def forward(self, x):
        yhat = torch.sigmoid(self.linear(x))
        return yhat
Explanation: <!--Empty Space for separating topics-->
<h2 id="Model_Cost">Create the Model and Total Loss Function (Cost)</h2>
Create a custom module for logistic regression:
End of explanation
# Create model object and print parameter
model = logistic_regression(1)
print("The parameters: ", model.state_dict())
Explanation: Create a logistic regression object and print the parameters:
End of explanation
# Create plot_error_surfaces object
get_surface = plot_error_surfaces(15, 13, data_set[:][0], data_set[:][1], 30)
Explanation: Create a <code>plot_error_surfaces</code> object to visualize the data space and the parameter space during training:
End of explanation
# Create DataLoader, Cost Function, Optimizer
trainloader = DataLoader(dataset = data_set, batch_size = 3)
criterion_rms = nn.MSELoss()
learning_rate = 2
optimizer = torch.optim.SGD(model.parameters(), lr = learning_rate)
Explanation: Create <code>DataLoader</code> object, cost or criterion function and <code>optimizer</code>:
End of explanation
# Train the model
def train_model(epochs):
    for epoch in range(epochs):  
        for x, y in trainloader:
            yhat = model(x)
            loss = criterion_rms(yhat, y)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            get_surface.set_para_loss(model, loss.tolist())
        if epoch % 20 == 0:
            get_surface.plot_ps()
train_model(100)
Explanation: <!--Empty Space for separating topics-->
<h2 id="BGD">Train the Model via Batch Gradient Descent</h2>
Train the model
End of explanation
# Make the Prediction
yhat = model(data_set.x)
label = yhat > 0.5
print("The accuracy: ", torch.mean((label == data_set.y.type(torch.ByteTensor)).type(torch.float)))
Explanation: Get the actual class of each sample and calculate the accuracy on the test data.
End of explanation
<END_TASK>