Exemple #1
0
def test5():
    print("\n\nTest 5 - Algorithm Tweaks (Bias & Variance)")
    print("Expected / Actual:")

    print("\nRegularized Linear Regression: ")
    X, y = ut.read_mat('mat/ex5data1.mat')
    X = ut.create_design(X)
    theta = np.array([1, 1])
    print("303.993 / ", alg.SSD(theta, X, y, 1))
    grad = alg.SSD_gradient(theta, X, y, 1)
    print("-15.30 / ", grad[0])
    print("598.250 / ", grad[1])

    print("\nLearning Curve:")
    raw = ut.read_mat_raw('mat/ex5data1.mat')
    X = raw['X']
    y = raw['y'].reshape(-1)

    Xval = raw['Xval']
    yval = raw['yval'].reshape(-1)
    print("Check plot")
    # pt.plot_learning_curve(ut.create_design(X), y, ut.create_design(Xval), yval, 0)

    print("\nFitting polynomial regression:")
    p = 8
    X_poly = ut.poly_features(X, p)
    X_poly, mu, sigma = ut.normalize_features(X_poly)
    X_poly = ut.create_design(X_poly)

    Xval = ut.poly_features(Xval, p)
    Xval -= mu
    Xval /= sigma
    Xval = ut.create_design(Xval)

    l = 0.01
    theta = alg.parametrize_linear(X_poly, y, l)

    print("Check plot, l =", l)
    pt.fit_plot(X, y, mu, sigma, theta, p)
    pt.plot_learning_curve(X_poly, y, Xval, yval, l)

    print("\nOptimize regularization:")
    print("Check plot")

    l = pt.plot_validation_curve(X_poly, y, Xval, yval)

    Xtest = raw['Xtest']
    ytest = raw['ytest'].reshape(-1)
    Xtest = ut.poly_features(Xtest, p)
    Xtest -= mu
    Xtest /= sigma
    Xtest = ut.create_design(Xtest)

    theta = alg.parametrize_linear(X_poly, y, l)
    print("3.8599 / ", alg.SSD(theta, Xtest, ytest, 0))

    print("\nRandomized learning curve:")
    print("Check plot")
    pt.plot_randomized_learning_curve(X_poly, y, Xval, yval, 0.01)
    return
Exemple #2
0
def test3neuralnet(theta1, theta2, a_1):
    # sizes - layer 1: 400, layer 2: 25, layer 3: 10
    a_1 = ut.create_design(a_1)
    a_2 = alg.sigmoid(a_1 @ theta1.T)
    a_2 = ut.create_design(a_2)
    a_3 = alg.sigmoid(theta2 @ a_2.T)
    p = np.argmax(a_3, axis=0) + 1
    return p
    return a_3
def main(subject, test=False):
    N_RUNS = 3

    h = np.arange(1, 9)
    fractions = 2**(h / 4)
    if test:
        print("TEST")
        base = np.array([5, 10])
        prob1 = [1.]
        prob2 = [.55]
    else:
        base = np.array([5, 7, 10, 14, 20, 28])
        prob1 = [1., .55]
        prob2 = [.55, 1.]

    df = create_design(prob1, prob2, fractions, base=base)

    n_trials = len(df)

    calibrate_settings_folder = op.abspath(op.join('settings', 'calibration'))
    if not op.exists(calibrate_settings_folder):
        os.makedirs(calibrate_settings_folder)

    fn = op.abspath(
        op.join(calibrate_settings_folder, f'sub-{subject}_ses-calibrate.tsv'))
    df.to_csv(fn, sep='\t')

    print(f'Wrote {n_trials} trials to {fn}')
Exemple #4
0
def fit_plot( X, y, mu, sigma, theta, p ):
  pt.plot(X, y, 'rx')
  x = np.arange(X.min() - 10, X.max() + 20, 0.05).reshape(-1, 1)
  X_poly = ut.poly_features(x, p)
  X_poly -= mu
  X_poly = np.divide(X_poly, sigma)
  X_poly = ut.create_design(X_poly)
  pt.plot(x, X_poly @ theta.reshape(-1, 1),  'c--')
  pt.show()
  return
def multiclass_logreg( X, y, l, degree ):
  X = ut.create_design(X)
  theta = np.zeros((degree, X.shape[1]))
  for i in range(degree):
    res = opt.minimize(cross_ent, theta[i, :], 
                    (X, y == i, l), jac=cross_ent_gradient,
                    method='L-BFGS-B',
                    options={'maxiter': 50})
    # print(res)
    theta[i, :] = res.x
  return theta
def main(subject, session=None, run=None):

    log_file = op.abspath(op.join('logs', f'sub-{subject}'))

    if session:
        log_file = op.join(log_file, f'ses-{session}')

    log_file = op.join(log_file, f'sub-{subject}')

    if session:
        log_file += f'_ses-{session}'

    log_file += '_task-calibration'

    if run:
        log_file += f'_run-{run}'

    log_file += '_events.tsv'

    x_lower, x_upper = fit_psychometric_curve(log_file, plot=True)

    print(log_file)

    print(x_lower, x_upper)
    fractions = np.exp(np.linspace(np.log(x_lower), np.log(x_upper), 8))
    base = np.array([5, 7, 10, 14, 20, 28])
    prob1 = [1., .55]
    prob2 = [.55, 1.]
    repetition = (1, 2)

    task_settings_folder = op.abspath(op.join('settings', 'task'))
    if not op.exists(task_settings_folder):
        os.makedirs(task_settings_folder)

    fn = op.abspath(
        op.join(task_settings_folder, f'sub-{subject}_ses-task.tsv'))

    df = create_design(prob1, prob2, fractions, repetitions=2, n_runs=8)

    df.to_csv(fn, sep='\t')
    plt.show()
Exemple #7
0
def test3():
    print("\n\nTest 3 - Multiclass Logistic Regression & Neural Networks")
    print("Expected / Actual:")

    print("\nMulticlass LR:")
    X, y = ut.read_mat('mat/ex3data1.mat')
    for i in range(y.shape[0]):
        if (y[i] == 10): y[i] = 0

    theta = np.array([-2, -1, 1, 2])
    X_t = ut.create_design(np.arange(1, 16, 1).reshape(3, 5).T / 10)
    y_t = np.array(([1, 0, 1, 0, 1]))
    l_t = 3
    cost = alg.cross_ent(theta, X_t, y_t, l_t)
    grad = alg.cross_ent_gradient(theta, X_t, y_t, l_t)
    print("2.534819 / %f" % cost)
    print("0.146561 / %f" % grad[0])
    print("-0.548558 / %f" % grad[1])
    print("0.724722 / %f" % grad[2])
    print("1.398003 / %f" % grad[3])

    degree = 10
    l = 0.1
    theta = alg.multiclass_logreg(X, y, l, degree)
    p = ut.multiclass_prediction(theta, X)
    print(">= 95 / %f" % (np.mean(p == y) * 100))

    print("\nNeural Networks (Forward Propagation): ")
    data = ut.read_mat_raw('mat/ex3weights.mat')
    theta1 = data['Theta1']
    theta2 = data['Theta2']

    X, y = ut.read_mat('mat/ex3data1.mat')
    p = test3neuralnet(theta1, theta2, X)
    print("Predicted: ", p)
    print("Actual: ", y)
    print("Expected vs. Actual Accuracy: 97.52 / %f" % (np.mean(p == y) * 100))
    return
def make_trial_design(subject, x_lower, x_upper, limit=None):
    import numpy as np

    fractions = np.exp(np.linspace(np.log(x_lower), np.log(x_upper), 8))
    base = np.array([5, 7, 10, 14, 20, 28])
    prob1 = [1., .55]
    prob2 = [.55, 1.]
    repetition = (1, 2)

    task_settings_folder = op.abspath(op.join('settings', 'task'))
    if not op.exists(task_settings_folder):
        os.makedirs(task_settings_folder)

    fn = op.abspath(
        op.join(task_settings_folder, f'sub-{subject}_ses-task.tsv'))

    df = create_design(prob1, prob2, fractions, repetitions=2)

    if limit is not None:
        df = df.iloc[:limit]

    df.to_csv(fn, sep='\t')
    logging.warning(f'Task settings written to {fn}')
Exemple #9
0
    def create_trials(self):
        self.trials = []

        txt = """
        Hi!

        Welcome to the instruction part of the experiment. During this part, we will explain what a single trial in this experiment looks like, and what choices you can make.

        First of all, during the experiment, you will always have 4 buttons that you can press.

        On this computer, these are:
        * the j-key (index finger)
        * the k-key (middle finger)
        * the l-key (ring finger)
        * the ;-key (pinky)

        TIP: let your index-/middle-/ring-finger and pinky lie down on these keys during the experiment. Note that, on the computer, key 1 (j) has a little bar on top that you can feel.

        In the scanner, there will be a red, blue, yellow, and green key.

        From now on, we will call them key 1 (index finger), key 2 (middle finger), key 3 (ring finger), and key 4 (pinky).

        Press key 1 to continue.
        """

        self.trials.append(InstructionTrial(self, 1,
                                            txt=txt, keys=[self.buttons[0]]))

        for key in [2, 3, 4]:
            txt = f"""
            Press key {key} to continue.
            """

            self.trials.append(InstructionTrial(self, key,
                                                txt=txt, keys=[self.buttons[key-1]]))
        txt = """
        In this experiment, your task is to make choices between (i) getting a fixed amount of money or (ii) to participate in a lottery where you have 55% chance to win a substantially larger amount of money.

        During the course of the experiment, you will make many different choices. After each session, we will randomly select one such choice you made during the task. When you selected the 55%-lottery option, we will perform a digital lottery that determines whether you win the offered amount.

        *** WE WILL ADD UP THE AMOUNTS YOU COLLECTED ACROSS THE FOUR SESSIONS AND YOU WILL BE PAID OUT THE AVERAGE OF THOSE AMOUNTS AFTER THE FOURTH SESSION. ***

        Press key 1 to continue
        """

        self.trials.append(InstructionTrial(self, 5,
                                            txt=txt, keys=[self.buttons[0]]))

        txt = """

        Let's say you won 0 CHF on the first session, 100 CHF in the second session, 0 CHF in the third session and 100 CHF in the fourth session. How much actual money will you be paid out at the end of the fourth session, on top of your hourly 30CHF/hour rate?

        1. 100CHF
        2. 50CHF
        3. 0CHF

        Press the key that corresponds to the correct answer.
        """

        self.trials.append(InstructionTrial(self, 6,
                                            txt=txt, keys=[self.buttons[1]]))

        txt = """
        Please note that if you do not respond to a trial in time, you will earn 0 CHF if that trial gets selected. So be sure to always indicate a choice in time.

        Press key 1 to continue
        """

        self.trials.append(InstructionTrial(self, 7,
                                            txt=txt, keys=[self.buttons[0]]))

        txt = """

        Let's say that the first choice was a 55% probability to win 5CHF and the second option 100% probability to win 1CHF. You *do not respond within 3 seconds*. Now this trial gets selected after the experiment. How much money will you earn?

        1. I have a 55% probability of winning 5CHF
        2. I win 1 CHF
        3. I win 0 CHF

        Press the key that corresponds to the correct answer.
        """

        self.trials.append(InstructionTrial(self, 7,
                                            txt=txt, keys=[self.buttons[2]]))

        txt = """
        We will now take you through all the steps of a trial.

        Press key 1 to continue
        """

        self.trials.append(InstructionTrial(self, 8,
                                            txt=txt, keys=[self.buttons[0]]))

        txt = "A new trial always starts with a green fixation cross"

        self.trials.append(GambleInstructTrial(
            self, 9, txt, show_phase=0))

        txt = "After the fixation cross, you will see the probability of winning the offered amount for the FIRST option. In this case, this option offers a 100% probability of gaining the following amount in CHF."

        self.trials.append(GambleInstructTrial(
            self, 10, txt, prob1=1.0, show_phase=2))

        txt = "Now you will see the amount of money that you can potentially win when you choose the FIRST option (5 CHF), represented as the number of coins on the screen."

        self.trials.append(GambleInstructTrial(
            self, 11, txt, num1=5, show_phase=4))

        txt = "Now you will see a red cross for a while. Try to remember the amount of money that was offered in the first option!"

        self.trials.append(GambleInstructTrial(
            self, 12, txt, show_phase=5))

        txt = "Now you will see the probability of winning the offered amount for the SECOND option. In this case, this option offers a 55% probability of gaining the offered amount in CHF."

        self.trials.append(GambleInstructTrial(
            self, 13, txt, prob2=0.55, show_phase=6))

        txt = "Now you will see the amount of money that you can potentially win when you choose the SECOND option (10 CHF), represented as the number of coins on the screen"

        self.trials.append(GambleInstructTrial(
            self, 14, txt, num2=10, show_phase=8))

        txt = """
        Now it is your task to choose one of the two options.
        You can press key 1 to choose the first option or key 2 to choose the second option.
        """

        bottom_txt = "Press key 2 to choose the second option"

        self.trials.append(GambleInstructTrial(
            self, 15, txt, num2=10, show_phase=8, bottom_txt=bottom_txt, keys=[self.buttons[1]]))

        txt = "After you made your choice, you get reminded what you've chosen."

        trial16 = GambleInstructTrial(
            self, 16, txt, show_phase=10)
        trial16.choice = 2
        trial16.choice_stim.text = f'You chose pile {trial16.choice}'
        self.trials.append(trial16)

        txt = "after your choice, you should also indicate from a scale of one to four how certain you were about your choice."
        bottom_txt = "Press key 1 to indicate you were very certain of your choice"

        self.trials.append(GambleInstructTrial(
            self, 17, txt, show_phase=11, bottom_txt=bottom_txt, keys=[self.buttons[0]]))

        txt = "You now can see which certainty you've indicated"
        trial18 = GambleInstructTrial(
            self, 18, txt, show_phase=11)
        trial18.certainty = 1
        trial18.certainty_stim.rectangles[0].opacity = 1.0
        self.trials.append(trial18)

        txt = """
        We will now go through a trial again and we will ask you some questions about it at the end. So pay close attention!

        Press key 2 to continue.
        """

        self.trials.append(InstructionTrial(self, 19,
                                            txt=txt, keys=[self.buttons[1]]))

        for phase in range(8):
            txt = ''
            self.trials.append(GambleInstructTrial(
                self, 20+phase, txt, show_phase=phase, prob1=1., num1=2, prob2=.55, num2=4))

            
        txt = 'Choose the 1st option'
        bottom_txt = '(so press key 1)'
        self.trials.append(GambleInstructTrial(
            self, 28, txt, show_phase=8, prob1=1., num1=2, prob2=.55, num2=4, bottom_txt=bottom_txt, keys=self.buttons[0]))

        txt = ''
        trial29 = GambleInstructTrial(
            self, 29, txt, show_phase=10)
        trial29.choice = 1
        trial29.choice_stim.text = f'You chose pile {trial29.choice}'
        self.trials.append(trial29)


        bottom_txt = "Press key 2 to indicate you were somewhat certain of your choice"

        self.trials.append(GambleInstructTrial(
            self, 30, txt, show_phase=11, bottom_txt=bottom_txt, keys=[self.buttons[1]]))

        trial31 = GambleInstructTrial(
            self, 31, txt, show_phase=11)
        trial31.certainty = 2
        trial31.certainty_stim.rectangles[1].opacity = 1.0
        self.trials.append(trial31)


        txt = """
        Pick the correct answer:

        1. I had to choose between 4 CHF for sure,
        or a lottery with a 55% probability to win 4 CHF.

        2. I had to choose between 2 CHF for sure,
        or a lottery with a 55% probability to win 4 CHF.

        3. I had to choose between 4 CHF for sure,
        or 2 CHF for sure.

        Press the key that corresponds to the correct answer.
        """

        self.trials.append(InstructionTrial(self, 32,
                                            txt=txt, keys=[self.buttons[1]]))


        txt = """
        Pick the correct answer:

        I answered the certainty question with 2, this means that ...

        1. I was very certain about the choice I made.

        2. I was somewhat certain about the choice I made.

        3. I was very uncertain about the choice I made.

        Press the key that corresponds to the correct answer.
        """

        self.trials.append(InstructionTrial(self, 32,
                                            txt=txt, keys=[self.buttons[1]]))

        txt = """
        Well done!!

        You will now do 10 practice trials. Note that the trial now automatically goes forwad.

        You only have to respond twice:
        Once to indicate your choice between the two options and once to indicate how certain you were about your choice. 
        """

        self.trials.append(InstructionTrial(self, 33,
                                            txt=txt))



        h = np.arange(1, 9)
        fractions = 2**(h/4)
        trial_settings = create_design([.55, 1.], [1., .55], fractions=fractions, n_runs=1)
        trial_settings = trial_settings.sample(n=10)

        jitter1 = self.settings['calibrate'].get('jitter1')
        jitter2 = self.settings['calibrate'].get('jitter2')

        trial_nr = 34

        for (p1, p2), d2 in trial_settings.groupby(['p1', 'p2'], sort=False):
            n_trials_in_miniblock = len(d2)
            self.trials.append(IntroBlockTrial(session=self, trial_nr=trial_nr,
                                               n_trials=n_trials_in_miniblock,
                                               prob1=p1,
                                               prob2=p2))

            trial_nr += 1

            for ix, row in d2.iterrows():
                self.trials.append(GambleTrial(self, trial_nr,
                                               prob1=row.p1, prob2=row.p2,
                                               num1=int(row.n1),
                                               num2=int(row.n2),
                                               jitter1=jitter1,
                                               jitter2=jitter2))
                trial_nr += 1

        txt = f"""
        Well done!

        You now finished the training for the first part of the experiment.

        There is also a much simpler task that you will have to perform in the scanner
        as well.


        Press any button to continue...
        """

        self.trials.append(InstructionTrial(self, trial_nr=trial_nr, txt=txt))
        trial_nr += 1

        txt = f"""
        In this second "detection task", your job is to press KEY 1 every time that
        you see DARK coins. When you see the standard LIGHT coins, do not press
        any button.

        We will now practice this for some time...

        Press any button to continue...

        """

        self.trials.append(InstructionTrial(self, trial_nr=trial_nr, txt=txt))
        trial_nr += 1

        design = [5, 7, 10, 20, 28, 56, 28, 20, 10, 7, 5]
        n_blocks = 1
        block_length = len(design)
        n_repeats_stimulus = 6

        colors = sample_isis(n_blocks * block_length * n_repeats_stimulus)

        for block in range(n_blocks):
            for ix, n_dots in enumerate(design):
                ix += block*block_length + 1

                color_ix = (ix-1) * \
                    n_repeats_stimulus, ix*n_repeats_stimulus
                self.trials.append(
                    MapperTrial(session=self,
                               trial_nr=trial_nr,
                               phase_durations=[],
                               n_dots=n_dots,
                               colors=colors[color_ix[0]:color_ix[1]],
                               verbose=True,)
                )
                trial_nr += 1

        txt = f"""
        Well done!

        You came to the end of the instruction part of the experiment.

        You will now do the two tasks (the "gamble task" and the "detection task") in the scanner.

        In case anything is unclear. Please do not hesitate to ask the experimenters anything!

        """

        self.trials.append(InstructionTrial(self, trial_nr=trial_nr, txt=txt))
Exemple #10
0
def test2():
    print("\n\nTest 2 - Logistic Regression & Regularization")
    print("Expected / Actual:")

    print("\nCost & Gradient:")
    X, y = ut.read_csv('csv/ex2data1.csv')
    X = ut.create_design(X)
    theta = np.zeros((X.shape[1], ))
    cost = alg.cross_ent(theta, X, y)
    grad = alg.cross_ent_gradient(theta, X, y)
    print("0.693147 / ", cost)
    print("-0.1000 / ", grad[0])
    print("-12.0092 / ", grad[1])
    print("-11.2628 / ", grad[2])
    res = opt.minimize(alg.cross_ent,
                       theta, (X, y),
                       method='BFGS',
                       jac=alg.cross_ent_gradient,
                       options={'maxiter': 400})
    print("0.203498 / ", res.fun)
    theta = res.x
    print("-25.1613 / ", theta[0])
    print("0.2062 / ", theta[1])
    print("0.2015 / ", theta[2])
    p = alg.sigmoid(ut.predict(np.array([[45, 85]]), theta)[0])
    print("0.776291 /", p)
    p = np.mean(np.round(alg.sigmoid(X @ theta)) == y) * 100
    print(">= 89.000000 /", p)

    print("\nRegularization:")
    X, y = ut.read_csv('csv/ex2data2.csv')
    X = ut.add_features(X[:, 0], X[:, 1], 6)
    print("118 / ", X.shape[0])
    print("28 /", X.shape[1])
    print("8.2291e-10 / ", X[117, 27])
    print("0.2914 / ", X[99, 9])
    theta = np.zeros((X.shape[1], ))
    l = 1
    print("0.693147 / ", alg.cross_ent(theta, X, y, l))
    grad = alg.cross_ent_gradient(theta, X, y, l)
    print("(28,) / ", grad.shape)
    print("0.0085 / ", grad[0])
    print("0.0129 / ", grad[12])
    print("0.0388 / ", grad[27])
    l = 0
    res = opt.minimize(alg.cross_ent,
                       theta, (X, y, l),
                       method='BFGS',
                       jac=alg.cross_ent_gradient,
                       options={'maxiter': 1000})
    theta = res.x
    p = np.mean(np.round(alg.sigmoid(X @ theta)) == y) * 100
    print(">= 88.983051 / ", p)

    theta = np.zeros((X.shape[1], ))
    l = 1
    res = opt.minimize(alg.cross_ent,
                       theta, (X, y, l),
                       method='BFGS',
                       jac=alg.cross_ent_gradient,
                       options={'maxiter': 1000})
    theta = res.x
    p = np.mean(np.round(alg.sigmoid(X @ theta)) == y) * 100
    print(">= 83.050847 / ", p)

    theta = np.zeros((X.shape[1], ))
    l = 10
    res = opt.minimize(alg.cross_ent,
                       theta, (X, y, l),
                       method='BFGS',
                       jac=alg.cross_ent_gradient,
                       options={'maxiter': 1000})
    theta = res.x
    p = np.mean(np.round(alg.sigmoid(X @ theta)) == y) * 100
    print(">= 74.576271 / ", p)

    theta = np.zeros((X.shape[1], ))
    l = 100
    res = opt.minimize(alg.cross_ent,
                       theta, (X, y, l),
                       method='BFGS',
                       jac=alg.cross_ent_gradient,
                       options={'maxiter': 1000})
    theta = res.x
    p = np.mean(np.round(alg.sigmoid(X @ theta)) == y) * 100
    print(">= 61.016949 / ", p)
Exemple #11
0
def test1():
    print("\n\nTest 1 - Linear Regression")
    print("Expected / Actual:")

    print("\nBatch gradient descent: ")
    X, y = ut.read_csv('csv/ex1data1.csv')
    X = ut.create_design(X)
    theta = np.zeros((X.shape[1], ))
    iterations = 1500
    alpha = 0.01
    print("32.0727 / ", alg.SSD(theta, X, y))
    print("52.2425 / ", alg.SSD(np.array([-1, 2]), X, y))
    alg.batch_gd(X, y, theta, alpha, iterations, alg.SSD_gradient)
    print("-3.630291 / ", theta[0])
    print("1.166362 / ", theta[1])
    print("34962.991574 / ",
          ut.predict(np.array([[6.1101]]), theta)[0] * 10**4)
    print("45342.450129 / ", ut.predict(np.array([[7]]), theta)[0] * 10**4)

    print("\nWith optimization: ")
    theta = np.zeros((X.shape[1]), )
    res = opt.minimize(alg.SSD,
                       theta, (X, y),
                       jac=alg.SSD_gradient,
                       method='Newton-CG',
                       options={"maxiter": 1500})
    theta = res.x
    print("-3.630291 / ", theta[0])
    print("1.166362 / ", theta[1])
    print("34962.991574 / ",
          ut.predict(np.array([[6.1101]]), theta)[0] * 10**4)
    print("45342.450129 / ", ut.predict(np.array([[7]]), theta)[0] * 10**4)

    print("\nNormalized batch gradient descent:")
    X, y = ut.read_csv('csv/ex1data2.csv')
    X, mu, sigma = ut.normalize_features(X)
    X = ut.create_design(X)
    alpha = 0.1
    iterations = 400
    theta = np.zeros((X.shape[1], ))
    alg.batch_gd(X, y, theta, alpha, iterations, alg.SSD_gradient)
    print("2000.680851 / ", mu[0])
    print("3.170213 / ", mu[1])
    print("794.7024 / ", sigma[0])
    print("0.7610 / ", sigma[1])
    print("340412.659574 / ", theta[0])
    print("110631.048958 / ", theta[1])
    print("-6649.472950 / ", theta[2])

    print("\nNormal equation:")
    X, y, = ut.read_csv('csv/ex1data2.csv')
    X = ut.create_design(X)
    alg.normal_eqn(X, y)
    print("340412.659574 / ", theta[0])
    print("110631.048958 / ", theta[1])
    print("-6649.472950 / ", theta[2])

    print("\nNormalized prediction:")
    print("293081.464622 / ",
          ut.predict(np.array([[1650, 3]]), theta, mu, sigma)[0])
    print("284343.447245 / ",
          ut.predict(np.array([[1650, 4]]), theta, mu, sigma)[0])

    return