def __init__(self, X_train, Y_train, Net='LeNet5', opti='SGDMomentum'):
    # Prepare Data: Load, Shuffle, Normalization, Batching, Preprocessing
    self.X_train = X_train
    self.Y_train = Y_train

    self.batch_size = 64
    # D_in: input depth of network, 784, 28*28 input grayscale image
    self.D_in = 784
    # D_out: output depth of network = 10, the 10 digits
    self.D_out = 10

    print ('  Net: ' + str(Net))
    print ('  batch_size: ' + str(self.batch_size))
    print ('  D_in: ' + str(self.D_in))
    print ('  D_out: ' + str(self.D_out))
    print ('  Optimizer: ' + opti)

    # =======================
    if Net == 'TwoLayerNet':
      # H is the size of the one hidden layer.
      H=400
      self.model = ANN.TwoLayerNet (self.D_in, H, self.D_out)
    elif Net == 'ThreeLayerNet':
      # H1, H2 are the size of the two hidden layers.
      H1=300
      H2=100
      self.model = ANN.ThreeLayerNet (self.D_in, H1, H2, self.D_out)
      
    elif Net == 'LeNet5':
      self.model = CNN.LeNet5()

    # store training loss over iterations, for later visualization
    self.losses = []

    if opti == 'SGD':
      self.opti = optimizer.SGD (self.model.get_params(), lr=0.0001, reg=0)
    else:
      self.opti = optimizer.SGDMomentum (self.model.get_params(), lr=0.0001, momentum=0.80, reg=0.00003)

    self.criterion = loss.CrossEntropyLoss()