├── .gitignore ├── 0_1_python_introduction_exercise ├── 0_1_python_introduction.ipynb └── ipython.png ├── 0_2_python_intro_applications ├── ex_0_2_python_tutorial.pdf ├── linear_regression │ ├── DataSaver.py │ ├── Features.py │ ├── LinearRegressionModel.py │ ├── NoiseModel.py │ ├── data │ │ └── data_samples.pkl │ └── linear_regression.py ├── scipy_optimization │ └── optimization_example.py └── solution │ ├── .gitignore │ ├── linear_regression │ ├── DataGenerator.py │ ├── DataSaver.py │ ├── Features.py │ ├── LinearRegressionModel.py │ ├── NoiseModel.py │ ├── data │ │ └── data_samples.pkl │ ├── generate_data.py │ └── linear_regression.py │ └── scipy_optimization │ └── optimization_example.py ├── 1_0_probability_ml_basics ├── bayes_filter │ ├── BayesianFiltering.py │ ├── data_1.pkl │ ├── data_2.pkl │ └── main.py ├── ex_1_0_probability_ml_basics.pdf ├── regression │ ├── DataSaver.py │ ├── Features.py │ ├── LinearRegressionModel.py │ ├── data │ │ ├── data_samples.pkl │ │ └── submission_data.pkl │ └── linear_regression.py ├── sampling │ ├── SamplePdf.py │ └── main.py └── solution │ ├── bayes_filter │ ├── BayesianFiltering.py │ ├── data_1.pkl │ ├── data_2.pkl │ └── main.py │ ├── regression │ ├── DataGenerator.py │ ├── DataSaver.py │ ├── Features.py │ ├── LinearRegressionModel.py │ ├── NoiseModel.py │ ├── data │ │ ├── data_samples.pkl │ │ └── submission_data.pkl │ ├── generate_data.py │ └── linear_regression.py │ └── sampling │ ├── SamplePdf.py │ └── main.py ├── 2_0_regression_pgm ├── ex_2_0_regression_pgm.pdf ├── logistic_regression │ ├── XtestIMG.txt │ ├── XtrainIMG.txt │ ├── Ytrain.txt │ └── main.py ├── markov_random_field │ ├── MarkovRandomField.py │ ├── data_1.pkl │ ├── data_2.pkl │ └── main.py └── solution │ ├── logistic_regression │ ├── XtestIMG.txt │ ├── XtrainIMG.txt │ ├── Ytest.txt │ ├── Ytrain.txt │ └── main.py │ └── markov_random_field │ ├── MarkovRandomField.py │ ├── data_1.pkl │ ├── data_2.pkl │ └── main.py ├── 3_0_pgo_icp ├── ex_3_0_pgo_icp.pdf ├── iterative_closest_point │ ├── assignment_II_1 │ │ ├── alignment_synthetic.py │ │ ├── synthetic_source.xyz │ │ └── synthetic_target.xyz │ └── assignment_II_2 │ │ ├── alignment_real_world.py │ │ ├── laser_target.xyz │ │ └── vision_source.xyz ├── pose_graph_optimization │ ├── assignment_I_1 │ │ ├── data_1D.txt │ │ └── pgo_1D.py │ └── assignment_I_2 │ │ ├── edges.dat │ │ ├── loop_closures.dat │ │ ├── pgo_2D.py │ │ └── vertices.dat └── solution │ ├── 3_0_pgo_icp_reference_solution_score_sheet.pdf │ ├── README.md │ ├── iterative_closest_point │ ├── assignment_II_1 │ │ ├── alignment_synthetic.py │ │ ├── groundtruth_alignment_synthetic.txt │ │ └── results_alignment_synthetic.txt │ └── assignment_II_2 │ │ ├── alignment_real_world.py │ │ ├── reference_alignment_real_world.txt │ │ └── results_alignment_real_world.txt │ └── pose_graph_optimization │ ├── assignment_I_1 │ ├── ground_truth.txt │ ├── pgo_1D.py │ ├── results_1D.txt │ ├── solution_odometry.txt │ └── solution_optimizer.txt │ └── assignment_I_2 │ ├── ground_truth.txt │ ├── pgo_2D.py │ ├── results_2D.txt │ ├── solution_odometry.txt │ └── solution_optimizer_olsen.txt ├── 4_0_pca_kmeans_svm ├── ex_4_0_pca_kmeans_svm.pdf ├── k_means │ ├── features_k_means.txt │ └── k_means_main.py ├── principal_component_analysis │ ├── orb_features.txt │ └── pca_main.py ├── solution │ ├── k_means │ │ ├── features_k_means.txt │ │ ├── k_means_main.py │ │ └── results_k_means.txt │ ├── principal_component_analysis │ │ ├── orb_features.txt │ │ ├── pca_main.py │ │ └── results_pca.txt │ └── support_vector_machines │ │ ├── features_evaluation.txt │ │ ├── features_svm.txt │ │ ├── labels_svm.txt │ │ ├── results_svm_P_g_perfect.txt │ │ ├── results_svm_P_g_slack.txt │ │ ├── results_svm_P_linear.txt │ │ ├── results_svm_Z_g_perfect.txt │ │ ├── results_svm_Z_g_slack.txt │ │ ├── results_svm_Z_linear.txt │ │ └── svm_main.py └── support_vector_machines │ ├── features_evaluation.txt │ ├── features_svm.txt │ ├── labels_svm.txt │ ├── results_svm_Y_linear.txt │ └── svm_main.py ├── 5_deep_learning ├── 01_DL_framework │ ├── ActivationFunction.py │ ├── FCLayer.py │ ├── FCNetwork.py │ ├── GradientDescentOptimizer.py │ ├── LossFunction.py │ ├── Makefile │ ├── ModelWrapper.py │ ├── Support.py │ ├── data │ │ └── data_train.pkl │ ├── train_classification.py │ └── unit_tests.py ├── 02_CNN │ ├── batchmaker.py │ ├── cnn_model.py │ ├── load_cifar10_and_extract_trucks_and_deers.py │ ├── test_cnn.py │ ├── tf_helpers.py │ ├── train_cnn.py │ └── utilities.py ├── 03_Deep_RL │ ├── NNModel.py │ ├── Support.py │ └── train_reinforcement_cart_pole.py ├── ex_5_0_dl.pdf └── solution │ ├── 01_DL_framework │ ├── ActivationFunction.py │ ├── FCLayer.py │ ├── FCNetwork.py │ ├── GradientDescentOptimizer.py │ ├── LossFunction.py │ ├── Makefile │ ├── ModelWrapper.py │ ├── README.md │ ├── Support.py │ ├── data │ │ ├── data_test.pkl │ │ └── data_train.pkl │ ├── generate_data.py │ ├── models │ │ └── trained.pkl │ ├── private_unit_tests.py │ ├── test_classification.py │ ├── train_classification.py │ └── unit_tests.py │ ├── 02_CNN │ ├── batchmaker.py │ ├── cnn_model.py │ ├── load_cifar10_and_extract_trucks_and_deers.py │ ├── test_cnn.py │ ├── tf_helpers.py │ ├── train_cnn.py │ └── utilities.py │ └── 03_Deep_RL │ ├── NNModel.py │ ├── Support.py │ ├── model │ ├── checkpoint │ ├── model-final.ckpt.data-00000-of-00001 │ ├── model-final.ckpt.index │ └── model-final.ckpt.meta │ ├── test_reinforcement_cart_pole.py │ └── train_reinforcement_cart_pole.py ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # IPython Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # dotenv 79 | .env 80 | 81 | # virtualenv 82 | venv/ 83 | ENV/ 84 | 85 | # Spyder project settings 86 | .spyderproject 87 | 88 | # Rope project settings 89 | .ropeproject 90 | 91 | # Misc 92 | *~ 93 | 94 | .DS_Store 95 | 5_deep_learning/02_CNN/data 96 | 5_deep_learning/02_CNN/model 97 | 98 | *~ 99 | 100 | -------------------------------------------------------------------------------- /0_1_python_introduction_exercise/ipython.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethz-asl/ai_for_robotics/03bb66bae99bac3acd79bc1ec6d3b9c0eeabcdf8/0_1_python_introduction_exercise/ipython.png -------------------------------------------------------------------------------- /0_2_python_intro_applications/ex_0_2_python_tutorial.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethz-asl/ai_for_robotics/03bb66bae99bac3acd79bc1ec6d3b9c0eeabcdf8/0_2_python_intro_applications/ex_0_2_python_tutorial.pdf -------------------------------------------------------------------------------- /0_2_python_intro_applications/linear_regression/DataSaver.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pickle as pkl 3 | import os 4 | 5 | 6 | class DataSaver(): 7 | 8 | directory = '' 9 | filename = '' 10 | path = '' 11 | 12 | def __init__(self, directory, filename): 13 | self.directory = directory 14 | self.filename = filename 15 | self.path = os.path.join(self.directory, self.filename) 16 | if not os.path.exists(self.directory): 17 | os.mkdir(self.directory) 18 | 19 | def save_to_file(self, input_data, output_data): 20 | data = np.hstack([input_data, output_data]) 21 | print('Saving data to relative path {}'.format(self.path)) 22 | pkl.dump(data, open(self.path, 'wb')) 23 | 24 | def restore_from_file(self): 25 | #TODO: input_data: np array of the size [n_samples, 2], output_data: size [n_samples, 1] 26 | return input_data, output_data 27 | -------------------------------------------------------------------------------- /0_2_python_intro_applications/linear_regression/Features.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from abc import ABCMeta, abstractmethod 3 | 4 | 5 | class Feature(): 6 | """ 7 | Feature base class. 8 | """ 9 | __metaClass__ = ABCMeta 10 | 11 | @abstractmethod 12 | def evaluate(self, x1, x2): 13 | pass 14 | 15 | 16 | # Feature classes 17 | class LinearX1(Feature): 18 | 19 | def evaluate(self, x1, x2): 20 | #TODO 21 | 22 | 23 | class Identity(Feature): 24 | 25 | def evaluate(self, x1, x2): 26 | return 1 27 | -------------------------------------------------------------------------------- /0_2_python_intro_applications/linear_regression/LinearRegressionModel.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | class ProgrammaticError(Exception): 5 | """Exception raised when method gets called at a wrong time instance. 6 | 7 | Attributes: 8 | msg -- The error message to be displayed. 9 | """ 10 | 11 | def __init__(self, msg): 12 | self.msg = msg 13 | print("\033[91mERROR: \x1b[0m {}".format(msg)) 14 | 15 | 16 | class LinearRegressionModel(): 17 | """ 18 | Class for linear regression model. 19 | """ 20 | 21 | # Members 22 | # Vector in equation: y = F(x,y) * beta, where F(x,y) is the feature vector 23 | beta = None 24 | feature_vec = [] 25 | fitting_done = False 26 | 27 | def __init__(self): 28 | self.feature_vec = [] 29 | self.fitting_done = False 30 | 31 | def error_function(self, predictions, target_values): 32 | return (predictions - target_values)**2 33 | 34 | def set_feature_vector(self, feature_vec): 35 | self.feature_vec = feature_vec 36 | 37 | def compute_feature_matrix(self, input_data): 38 | n_samples = input_data.shape[0] 39 | n_features = len(self.feature_vec) 40 | X = np.zeros([n_samples, n_features]) 41 | #TODO 42 | return X 43 | 44 | def fit(self, input_data, output_data): 45 | n_features = len(self.feature_vec) 46 | assert(n_features > 0, 'Please set the feature vector first.') 47 | # In general don't use assertions in deployment code, use hard checks, as 48 | # assertions get compiled away when optimization is used. 49 | if (n_features < 1): 50 | raise ProgrammaticError("Please set the feature vector first.") 51 | #TODO 52 | print('Done with fitting of the model.') 53 | 54 | def predict(self, input_data): 55 | #TODO 56 | 57 | 58 | def validate(self, validation_input, validation_output): 59 | return np.mean(self.error_function(self.predict(validation_input), 60 | validation_output)) 61 | -------------------------------------------------------------------------------- /0_2_python_intro_applications/linear_regression/NoiseModel.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | class NoiseModel(): 5 | 6 | mu = 0 7 | sigma = 0 8 | 9 | def __init__(self, mu=0, sigma=1): 10 | self.mu = mu 11 | self.sigma = sigma 12 | 13 | def sample(self): 14 | #TODO: return Gaussian noise sample 15 | -------------------------------------------------------------------------------- /0_2_python_intro_applications/linear_regression/linear_regression.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import numpy as np 4 | import NoiseModel as noise 5 | import Features as features 6 | import LinearRegressionModel as model 7 | import DataSaver as saver 8 | import pylab as pl 9 | from mpl_toolkits.mplot3d import Axes3D 10 | from sklearn.linear_model import LinearRegression 11 | 12 | # Remove lapack warning on OSX (https://github.com/scipy/scipy/issues/5998). 13 | import warnings 14 | warnings.filterwarnings(action="ignore", module="scipy", 15 | message="^internal gelsd") 16 | 17 | pl.close('all') 18 | 19 | # data_generator = data.DataGenerator() 20 | data_saver = saver.DataSaver('data', 'data_samples.pkl') 21 | input_data, output_data = data_saver.restore_from_file() 22 | n_samples = input_data.shape[0] 23 | 24 | # Split data into training and validation 25 | ratio_train_validate = 0.8 26 | idx_switch = int(n_samples * ratio_train_validate) 27 | training_input = input_data[:idx_switch, :] 28 | training_output = output_data[:idx_switch, :] 29 | validation_input = input_data[idx_switch:, :] 30 | validation_output = output_data[idx_switch:, :] 31 | 32 | # Fit model 33 | lm = model.LinearRegressionModel() 34 | lm.set_feature_vector([features.LinearX1(), #TODO ]) 35 | lm.fit(training_input, training_output) 36 | 37 | # sklearn 38 | #TODO 39 | 40 | # Validation 41 | mse = lm.validate(validation_input, validation_output) 42 | print('MSE: {}'.format(mse)) 43 | print(' ') 44 | print('feature weights \n{}'.format(lm.beta)) 45 | validation_predictions = lm.predict(validation_input) 46 | feature_matrix_validation = lm.compute_feature_matrix(validation_input) 47 | validation_predictions_sk = linear_regression_sk.predict( 48 | feature_matrix_validation) 49 | 50 | # Visualization 51 | fig = pl.figure() 52 | ax = fig.add_subplot(121, projection='3d') 53 | ax.scatter(training_input[:, 0], training_input[:, 1], training_output, 54 | alpha=1) 55 | ax.set_xlabel('x1') 56 | ax.set_ylabel('x2') 57 | ax.set_zlabel('y') 58 | ax.set_title('Training data') 59 | 60 | ax = fig.add_subplot(122, projection='3d') 61 | ax.scatter(validation_input[:, 0], validation_input[:, 1], 62 | validation_output, alpha=0.5, c='b') 63 | ax.scatter(validation_input[:, 0], validation_input[:, 1], 64 | validation_predictions, alpha=0.5, c='r') 65 | # ax.scatter(validation_input[:, 0], validation_input[:, 1], 66 | # validation_predictions_sk, alpha=0.5, c='g') 67 | ax.set_xlabel('x1') 68 | ax.set_ylabel('x2') 69 | ax.set_zlabel('y') 70 | ax.set_title('Validation results') 71 | 72 | pl.show() 73 | -------------------------------------------------------------------------------- /0_2_python_intro_applications/scipy_optimization/optimization_example.py: -------------------------------------------------------------------------------- 1 | from scipy.optimize import minimize 2 | import numpy as np 3 | import pylab as pl 4 | from mpl_toolkits.mplot3d import Axes3D 5 | import math 6 | 7 | 8 | def f(x): 9 | """ Function that returns x_0^2 + e^{0.5*x_0} + 10*sin(x_1) + x_1^2. """ 10 | return x[0] ** 2 + math.exp(0.5 * x[0]) + 10 * math.sin(x[1]) + x[1] ** 2 11 | 12 | def fprime(x): 13 | #TODO 14 | 15 | 16 | opt_out = #TODO 17 | 18 | # Plotting 19 | pl.close('all') 20 | r = 6 21 | x_range = np.linspace(-r, r) 22 | y_range = np.linspace(-r, r) 23 | X, Y = np.meshgrid(x_range, y_range) 24 | Z = np.zeros(X.shape) 25 | for i in range(X.shape[0]): 26 | for j in range(X.shape[1]): 27 | Z[i, j] = f(np.array([X[i, j], Y[i, j]])) 28 | 29 | fig = pl.figure('Cost function') 30 | ax = fig.add_subplot(111, projection='3d') 31 | surf = ax.plot_surface(X, Y, Z, cmap=pl.cm.coolwarm, alpha=0.6) 32 | ax.scatter(opt_out.x[0], opt_out.x[1], f(opt_out.x), c='r', s=50) 33 | 34 | pl.show(block=False) 35 | -------------------------------------------------------------------------------- /0_2_python_intro_applications/solution/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore autogenerated latex files 2 | *.aux 3 | *.bbl 4 | *.blg 5 | *.dvi 6 | *.out 7 | *.pdf 8 | 9 | -------------------------------------------------------------------------------- /0_2_python_intro_applications/solution/linear_regression/DataGenerator.py: -------------------------------------------------------------------------------- 1 | import NoiseModel as noise 2 | import Features as features 3 | import DataSaver as saver 4 | 5 | import numpy as np 6 | import pickle as pkl 7 | import os 8 | 9 | 10 | class DataGenerator(): 11 | """ 12 | Data generation for linear regression example. 13 | """ 14 | 15 | feature_vec = [] 16 | feature_weights = [] 17 | noise_model = None 18 | input_data = np.zeros([0, 2]) 19 | output_data = np.zeros([0, 1]) 20 | max_x1 = 0 21 | max_x2 = 0 22 | saver = None 23 | 24 | def __init__(self): 25 | self.feature_vec = [features.LinearX1(), features.LinearX2(), 26 | features.SquareX1(), features.ExpX2(), 27 | features.LogX1(), features.Identity()] 28 | self.feature_weights = [1, 2, 1, 0.1, 10, 40] 29 | self.noise_model = noise.NoiseModel() 30 | self.max_x1 = 10 31 | self.max_x2 = 10 32 | self.saver = saver.DataSaver('data', 'data_samples.pkl') 33 | 34 | def __generate_samples__(self, n_samples): 35 | input_x1 = np.random.rand(n_samples) * self.max_x1 36 | input_x2 = np.random.rand(n_samples) * self.max_x2 37 | self.input_data = np.array([input_x1, input_x2]).T 38 | self.output_data = np.zeros([n_samples, 1]) 39 | 40 | for i in range(n_samples): 41 | out_value = 0 42 | for f, w in zip(self.feature_vec, self.feature_weights): 43 | out_value += w * \ 44 | f.evaluate(self.input_data[i, 0], self.input_data[i, 1]) 45 | out_value += self.noise_model.sample() 46 | self.output_data[i] = out_value 47 | 48 | return self.input_data, self.output_data 49 | 50 | def sample(self, n_samples): 51 | if self.output_data.shape[0] == n_samples: 52 | print('Returning pre-generated samples.') 53 | return self.input_data, self.output_data 54 | else: 55 | print('Generating new samples.') 56 | return self.__generate_samples__(n_samples) 57 | 58 | def save(self): 59 | self.saver.save_to_file(self.input_data, self.output_data) 60 | -------------------------------------------------------------------------------- /0_2_python_intro_applications/solution/linear_regression/DataSaver.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pickle as pkl 3 | import os 4 | 5 | 6 | class DataSaver(): 7 | 8 | directory = '' 9 | filename = '' 10 | path = '' 11 | 12 | def __init__(self, directory, filename): 13 | self.directory = directory 14 | self.filename = filename 15 | self.path = os.path.join(self.directory, self.filename) 16 | if not os.path.exists(self.directory): 17 | os.mkdir(self.directory) 18 | 19 | def save_to_file(self, input_data, output_data): 20 | data = np.hstack([input_data, output_data]) 21 | print('Saving data to relative path {}'.format(self.path)) 22 | pkl.dump(data, open(self.path, 'wb')) 23 | 24 | def restore_from_file(self): 25 | data = pkl.load(open(self.path, 'rb')) 26 | input_data = data[:, 0:2] 27 | output_data = np.reshape(data[:, 2], [data[:, 2].shape[0], 1]) 28 | return input_data, output_data 29 | -------------------------------------------------------------------------------- /0_2_python_intro_applications/solution/linear_regression/Features.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | import math 3 | 4 | class Feature(): 5 | """ 6 | Feature base class. 7 | """ 8 | __metaClass__ = ABCMeta 9 | 10 | @abstractmethod 11 | def evaluate(self, x1, x2): 12 | pass 13 | 14 | 15 | # Feature classes 16 | class LinearX1(Feature): 17 | 18 | def evaluate(self, x1, x2): 19 | return x1 20 | 21 | 22 | class LinearX2(Feature): 23 | 24 | def evaluate(self, x1, x2): 25 | return x2 26 | 27 | 28 | class SquareX1(Feature): 29 | 30 | def evaluate(self, x1, x2): 31 | return x1**2 32 | 33 | 34 | class SquareX2(Feature): 35 | 36 | def evaluate(self, x1, x2): 37 | return x2**2 38 | 39 | 40 | class CrossTermX1X2(Feature): 41 | 42 | def evaluate(self, x1, x2): 43 | return x1 * x2 44 | 45 | class ExpX1(Feature): 46 | 47 | def evaluate(self, x1, x2): 48 | return math.exp(x1) 49 | 50 | class ExpX2(Feature): 51 | 52 | def evaluate(self, x1, x2): 53 | return math.exp(x2) 54 | 55 | class LogX1(Feature): 56 | 57 | def evaluate(self, x1, x2): 58 | return math.log(x1) 59 | 60 | class LogX2(Feature): 61 | 62 | def evaluate(self, x1, x2): 63 | return math.log(x2) 64 | 65 | class Identity(Feature): 66 | 67 | def evaluate(self, x1, x2): 68 | return 1 69 | -------------------------------------------------------------------------------- /0_2_python_intro_applications/solution/linear_regression/LinearRegressionModel.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | class ProgrammaticError(Exception): 5 | """Exception raised when method gets called at a wrong time instance. 6 | 7 | Attributes: 8 | msg -- The error message to be displayed. 9 | """ 10 | 11 | def __init__(self, msg): 12 | self.msg = msg 13 | print("\033[91mERROR: \x1b[0m {}".format(msg)) 14 | 15 | 16 | class LinearRegressionModel(): 17 | """ 18 | Class for linear regression model. 19 | """ 20 | 21 | # Members 22 | # Vector in equation: y = F(x,y) * beta, where F(x,y) is the feature vector 23 | beta = None 24 | feature_vec = [] 25 | fitting_done = False 26 | 27 | def __init__(self): 28 | self.feature_vec = [] 29 | self.fitting_done = False 30 | 31 | def error_function(self, predictions, target_values): 32 | return (predictions - target_values)**2 33 | 34 | def set_feature_vector(self, feature_vec): 35 | self.feature_vec = feature_vec 36 | 37 | def compute_feature_matrix(self, input_data): 38 | n_samples = input_data.shape[0] 39 | n_features = len(self.feature_vec) 40 | X = np.zeros([n_samples, n_features]) 41 | for i in range(n_samples): 42 | for j in range(n_features): 43 | X[i, j] = self.feature_vec[j].evaluate( 44 | input_data[i, 0], input_data[i, 1]) 45 | return X 46 | 47 | def fit(self, input_data, output_data): 48 | n_features = len(self.feature_vec) 49 | assert n_features > 0, 'Please set the feature vector first.' 50 | # In general don't use assertions in deployment code, use hard checks, as 51 | # assertions get compiled away when optimization is used. 52 | if (n_features < 1): 53 | raise ProgrammaticError("Please set the feature vector first.") 54 | n_samples = input_data.shape[0] 55 | X = self.compute_feature_matrix(input_data) 56 | # Least squares parameter estimation 57 | self.beta = np.dot(np.dot(np.linalg.inv(np.dot(X.T, X)), X.T), output_data) 58 | self.fitting_done = True 59 | print('Done with fitting of the model.') 60 | 61 | def predict(self, input_data): 62 | # In general don't use assertions in deployment code, use hard checks, as 63 | # assertions get compiled away when optimization is used. 64 | if not self.fitting_done: 65 | raise ProgrammaticError("Before you use the model for query, you have " 66 | "to set the feature vector and fit it.") 67 | n_features = len(self.feature_vec) 68 | n_data = input_data.shape[0] 69 | X = self.compute_feature_matrix(input_data) 70 | return np.dot(X, self.beta) 71 | 72 | def validate(self, validation_input, validation_output): 73 | return np.mean(self.error_function(self.predict(validation_input), 74 | validation_output)) 75 | -------------------------------------------------------------------------------- /0_2_python_intro_applications/solution/linear_regression/NoiseModel.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | class NoiseModel(): 5 | 6 | mu = 0 7 | sigma = 0 8 | 9 | def __init__(self, mu=0, sigma=1): 10 | self.mu = mu 11 | self.sigma = sigma 12 | 13 | def sample(self): 14 | return self.sigma * np.random.randn() + self.mu 15 | -------------------------------------------------------------------------------- /0_2_python_intro_applications/solution/linear_regression/generate_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import NoiseModel as noise 4 | import Features as features 5 | import DataGenerator as data 6 | 7 | # Remove lapack warning on OSX (https://github.com/scipy/scipy/issues/5998). 8 | import warnings 9 | warnings.filterwarnings(action="ignore", module="scipy", 10 | message="^internal gelsd") 11 | 12 | 13 | n_samples = 10000 14 | data_generator = data.DataGenerator() 15 | input_data, output_data = data_generator.sample(n_samples) 16 | data_generator.save() 17 | 18 | -------------------------------------------------------------------------------- /0_2_python_intro_applications/solution/linear_regression/linear_regression.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import NoiseModel as noise 4 | import Features as features 5 | import DataGenerator as data 6 | import LinearRegressionModel as model 7 | import DataSaver as saver 8 | import pylab as pl 9 | from mpl_toolkits.mplot3d import Axes3D 10 | from sklearn.linear_model import LinearRegression 11 | 12 | # Remove lapack warning on OSX (https://github.com/scipy/scipy/issues/5998). 13 | import warnings 14 | warnings.filterwarnings(action="ignore", module="scipy", 15 | message="^internal gelsd") 16 | 17 | pl.close('all') 18 | 19 | # data_generator = data.DataGenerator() 20 | data_saver = saver.DataSaver('data', 'data_samples.pkl') 21 | input_data, output_data = data_saver.restore_from_file() 22 | n_samples = input_data.shape[0] 23 | 24 | # Split data into training and validation 25 | ratio_train_validate = 0.8 26 | idx_switch = int(n_samples * ratio_train_validate) 27 | training_input = input_data[:idx_switch, :] 28 | training_output = output_data[:idx_switch, :] 29 | validation_input = input_data[idx_switch:, :] 30 | validation_output = output_data[idx_switch:, :] 31 | 32 | # Fit model 33 | lm = model.LinearRegressionModel() 34 | lm.set_feature_vector([features.LinearX1(), features.LinearX2(), 35 | features.SquareX1(), features.ExpX2(), 36 | features.LogX1(), features.Identity()]) 37 | lm.fit(training_input, training_output) 38 | 39 | # sklearn 40 | linear_regression_sk = LinearRegression() 41 | feature_matrix = lm.compute_feature_matrix(training_input) 42 | linear_regression_sk.fit(feature_matrix, training_output) 43 | 44 | # Validation 45 | mse = lm.validate(validation_input, validation_output) 46 | print('MSE: {}'.format(mse)) 47 | print(' ') 48 | print('feature weights \n{}'.format(lm.beta)) 49 | validation_predictions = lm.predict(validation_input) 50 | feature_matrix_validation = lm.compute_feature_matrix(validation_input) 51 | validation_predictions_sk = linear_regression_sk.predict( 52 | feature_matrix_validation) 53 | 54 | # Visualization 55 | fig = pl.figure() 56 | ax = fig.add_subplot(121, projection='3d') 57 | ax.scatter(training_input[:, 0], training_input[:, 1], training_output, 58 | alpha=1) 59 | ax.set_xlabel('x1') 60 | ax.set_ylabel('x2') 61 | ax.set_zlabel('y') 62 | ax.set_title('Training data') 63 | 64 | ax = fig.add_subplot(122, projection='3d') 65 | ax.scatter(validation_input[:, 0], validation_input[:, 1], 66 | validation_output, alpha=0.5, c='b') 67 | ax.scatter(validation_input[:, 0], validation_input[:, 1], 68 | validation_predictions, alpha=0.5, c='r') 69 | ax.scatter(validation_input[:, 0], validation_input[:, 1], 70 | validation_predictions_sk, alpha=0.5, c='g') 71 | ax.set_xlabel('x1') 72 | ax.set_ylabel('x2') 73 | ax.set_zlabel('y') 74 | ax.set_title('Validation results') 75 | 76 | pl.show() 77 | -------------------------------------------------------------------------------- /0_2_python_intro_applications/solution/scipy_optimization/optimization_example.py: -------------------------------------------------------------------------------- 1 | from scipy.optimize import minimize 2 | import numpy as np 3 | import pylab as pl 4 | from mpl_toolkits.mplot3d import Axes3D 5 | import math 6 | 7 | 8 | def f(x): 9 | """ Function that returns x_0^2 + e^{0.5*x_0} + 10*sin(x_1) + x_1^2. """ 10 | return x[0] ** 2 + math.exp(0.5 * x[0]) + 10 * math.sin(x[1]) + x[1] ** 2 11 | 12 | 13 | def fprime(x): 14 | """ The derivative of f. """ 15 | ddx0 = 2 * x[0] + 0.5 * math.exp(0.5 * x[0]) 16 | ddx1 = 10 * math.cos(x[1]) + 2 * x[1] 17 | return np.array([ddx0, ddx1]) 18 | 19 | 20 | opt_out = minimize(f, x0=np.array( 21 | [10, 10]), jac=fprime, tol=1e-8, method='BFGS', options={'disp': True}) 22 | 23 | # Plotting 24 | pl.close('all') 25 | r = 6 26 | x_range = np.linspace(-r, r) 27 | y_range = np.linspace(-r, r) 28 | X, Y = np.meshgrid(x_range, y_range) 29 | Z = np.zeros(X.shape) 30 | for i in range(X.shape[0]): 31 | for j in range(X.shape[1]): 32 | Z[i, j] = f(np.array([X[i, j], Y[i, j]])) 33 | 34 | fig = pl.figure('Cost function') 35 | ax = fig.add_subplot(111, projection='3d') 36 | surf = ax.plot_surface(X, Y, Z, cmap=pl.cm.coolwarm, alpha=0.6) 37 | ax.scatter(opt_out.x[0], opt_out.x[1], f(opt_out.x), c='r', s=50) 38 | 39 | pl.show(block=False) 40 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/bayes_filter/BayesianFiltering.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.ndimage.filters as filters 3 | import matplotlib.pyplot as plt 4 | import time 5 | 6 | 7 | def histogram_plot(pos, title=None, c='b'): 8 | axis = plt.gca() 9 | x = np.arange(len(pos)) 10 | axis.bar(x, pos, color=c) 11 | plt.ylim((0, 1)) 12 | plt.xticks(np.asarray(x) + 0.4, x) 13 | if title is not None: 14 | plt.title(title) 15 | 16 | 17 | def normalize(input): 18 | normalized_value = np.ones(len(input)) 19 | # TODO: Implement the normalization function 20 | return normalized_value 21 | 22 | 23 | def compute_likelihood(map, measurement, prob_correct_measurement): 24 | likelihood = np.ones(len(map)) 25 | # TODO: compute the likelihood 26 | return likelihood 27 | 28 | 29 | def measurement_update(prior, likelihood): 30 | # TODO: compute posterior, use function normalize 31 | return np.ones(len(prior)) # TODO: change this line to return posterior 32 | 33 | 34 | def prior_update(posterior, movement, movement_noise_kernel): 35 | # TODO: compute the new prior 36 | # HINT: be careful with the movement direction and noise kernel! 37 | return np.ones( 38 | len(posterior)) # TODO: change this line to return new prior 39 | 40 | 41 | def run_bayes_filter(measurements, motions, plot_histogram=False): 42 | map = np.array([0] * 20) # TODO: define the map 43 | sensor_prob_correct_measure = 1 # TODO: define the probability of correct measurement 44 | movement_noise_kernel = 1 # TODO: define noise kernel of the movement command 45 | 46 | # Assume uniform distribution since you do not know the starting position 47 | prior = np.array([1. / 20] * 20) 48 | likelihood = np.zeros(len(prior)) 49 | 50 | number_of_iterations = len(measurements) 51 | if plot_histogram: 52 | fig = plt.figure("Bayes Filter") 53 | for iteration in range(number_of_iterations): 54 | # Compute the likelihood 55 | likelihood = compute_likelihood(map, measurements[iteration], 56 | sensor_prob_correct_measure) 57 | # Compute posterior 58 | posterior = measurement_update(prior, likelihood) 59 | if plot_histogram: 60 | plt.cla() 61 | histogram_plot(map, title="Measurement update", c='k') 62 | histogram_plot(posterior, title="Measurement update", c='y') 63 | fig.canvas.draw() 64 | plt.show(block=False) 65 | time.sleep(.5) 66 | 67 | # Update prior 68 | prior = prior_update(posterior, motions[iteration], 69 | movement_noise_kernel) 70 | if plot_histogram: 71 | plt.cla() 72 | histogram_plot(map, title="Prior update", c='k') 73 | histogram_plot(prior, title="Prior update") 74 | fig.canvas.draw() 75 | plt.show(block=False) 76 | time.sleep(.5) 77 | plt.show() 78 | return prior 79 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/bayes_filter/data_1.pkl: -------------------------------------------------------------------------------- 1 | cnumpy.core.multiarray 2 | _reconstruct 3 | p0 4 | (cnumpy 5 | ndarray 6 | p1 7 | (I0 8 | tp2 9 | S'b' 10 | p3 11 | tp4 12 | Rp5 13 | (I1 14 | (I2 15 | I30 16 | tp6 17 | cnumpy 18 | dtype 19 | p7 20 | (S'i8' 21 | p8 22 | I0 23 | I1 24 | tp9 25 | Rp10 26 | (I3 27 | S'<' 28 | p11 29 | NNNI-1 30 | I-1 31 | I0 32 | tp12 33 | bI00 34 | S'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xfd\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff' 35 | p13 36 | tp14 37 | b. -------------------------------------------------------------------------------- /1_0_probability_ml_basics/bayes_filter/data_2.pkl: -------------------------------------------------------------------------------- 1 | cnumpy.core.multiarray 2 | _reconstruct 3 | p0 4 | (cnumpy 5 | ndarray 6 | p1 7 | (I0 8 | tp2 9 | S'b' 10 | p3 11 | tp4 12 | Rp5 13 | (I1 14 | (I2 15 | I30 16 | tp6 17 | cnumpy 18 | dtype 19 | p7 20 | (S'i8' 21 | p8 22 | I0 23 | I1 24 | tp9 25 | Rp10 26 | (I3 27 | S'<' 28 | p11 29 | NNNI-1 30 | I-1 31 | I0 32 | tp12 33 | bI00 34 | S'\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xfd\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff\xff\xff\xff\xff\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xff\xff\xff\xff\xff\xff\xff\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00' 35 | p13 36 | tp14 37 | b. -------------------------------------------------------------------------------- /1_0_probability_ml_basics/bayes_filter/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import pickle as pkl 4 | import numpy as np 5 | import BayesianFiltering 6 | 7 | 8 | class ProgrammaticError(Exception): 9 | """Exception raised when method gets called at a wrong time instance. 10 | Attributes: 11 | msg -- The error message to be displayed. 12 | """ 13 | 14 | def __init__(self, msg): 15 | self.msg = msg 16 | print("\033[91mERROR: \x1b[0m {}".format(msg)) 17 | 18 | 19 | data = pkl.load(open("data_1.pkl", 'rb')) 20 | measurements = data[0, :] 21 | motions = data[1, :] 22 | 23 | if (len(measurements) != len(motions)): 24 | raise ProgrammaticError( 25 | 'Size of the measurements and motions needs to be the same!') 26 | 27 | result = BayesianFiltering.run_bayes_filter( 28 | measurements, motions, plot_histogram=True) 29 | pkl.dump(result, open("result_bayes_1.pkl", 'wb')) 30 | 31 | data = pkl.load(open("data_2.pkl", 'rb')) 32 | measurements = data[0, :] 33 | motions = data[1, :] 34 | 35 | if (len(measurements) != len(motions)): 36 | raise ProgrammaticError( 37 | 'Size of the measurements and motions needs to be the same!') 38 | 39 | result = BayesianFiltering.run_bayes_filter( 40 | measurements, motions, plot_histogram=True) 41 | pkl.dump(result, open("result_bayes_2.pkl", 'wb')) 42 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/ex_1_0_probability_ml_basics.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethz-asl/ai_for_robotics/03bb66bae99bac3acd79bc1ec6d3b9c0eeabcdf8/1_0_probability_ml_basics/ex_1_0_probability_ml_basics.pdf -------------------------------------------------------------------------------- /1_0_probability_ml_basics/regression/DataSaver.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pickle as pkl 3 | import os 4 | 5 | 6 | class DataSaver(): 7 | 8 | directory = '' 9 | filename = '' 10 | path = '' 11 | 12 | def __init__(self, directory, filename): 13 | self.directory = directory 14 | self.filename = filename 15 | self.path = os.path.join(self.directory, self.filename) 16 | if not os.path.exists(self.directory): 17 | os.mkdir(self.directory) 18 | 19 | def save_to_file(self, input_data, output_data): 20 | data = np.hstack([input_data, output_data]) 21 | print('Saving data to relative path {}'.format(self.path)) 22 | pkl.dump(data, open(self.path, 'wb')) 23 | 24 | def restore_from_file(self): 25 | data = pkl.load(open(self.path, 'rb')) 26 | # TODO adapt the following two lines, such that it works for the 4dimensional input 27 | input_data = data[:, 0:2] 28 | output_data = np.reshape(data[:, 2], [data[:, 2].shape[0], 1]) 29 | return input_data, output_data 30 | 31 | def load_submission(self): 32 | data = pkl.load(open(self.path, 'rb')) 33 | input_data = data[:, 0:4] 34 | return input_data 35 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/regression/Features.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | import math 3 | import numpy as np 4 | 5 | 6 | class Feature(): 7 | """ 8 | Feature base class. 9 | """ 10 | __metaClass__ = ABCMeta 11 | 12 | @abstractmethod 13 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 14 | pass 15 | 16 | 17 | # Feature classes 18 | class LinearX1(Feature): 19 | 20 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 21 | return x1 22 | 23 | 24 | class LinearX2(Feature): 25 | 26 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 27 | return x2 28 | 29 | 30 | class SquareX1(Feature): 31 | 32 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 33 | return x1**2 34 | 35 | 36 | class SquareX2(Feature): 37 | 38 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 39 | return x2**2 40 | 41 | 42 | class CrossTermX1X2(Feature): 43 | 44 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 45 | return x1 * x2 46 | 47 | 48 | class ExpX1(Feature): 49 | 50 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 51 | return math.exp(x1) 52 | 53 | 54 | class ExpX2(Feature): 55 | 56 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 57 | return math.exp(x2) 58 | 59 | 60 | class LogX1(Feature): 61 | 62 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 63 | return math.log(x1) 64 | 65 | 66 | class LogX2(Feature): 67 | 68 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 69 | return math.log(x2) 70 | 71 | 72 | class Identity(Feature): 73 | 74 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 75 | return 1 76 | 77 | # TODO add the new features 78 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/regression/LinearRegressionModel.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | class ProgrammaticError(Exception): 5 | """Exception raised when method gets called at a wrong time instance. 6 | 7 | Attributes: 8 | msg -- The error message to be displayed. 9 | """ 10 | 11 | def __init__(self, msg): 12 | self.msg = msg 13 | print("\033[91mERROR: \x1b[0m {}".format(msg)) 14 | 15 | 16 | class LinearRegressionModel(): 17 | """ 18 | Class for linear regression model. 19 | """ 20 | 21 | # Members 22 | # Vector in equation: y = F(x,y) * beta, where F(x,y) is the feature vector 23 | beta = None 24 | feature_vec = [] 25 | fitting_done = False 26 | 27 | def __init__(self): 28 | self.feature_vec = [] 29 | self.fitting_done = False 30 | 31 | def error_function(self, predictions, target_values): 32 | return (predictions - target_values)**2 33 | 34 | def set_feature_vector(self, feature_vec): 35 | self.feature_vec = feature_vec 36 | 37 | def compute_feature_matrix(self, input_data): 38 | n_samples = input_data.shape[0] 39 | n_features = len(self.feature_vec) 40 | X = np.zeros([n_samples, n_features]) 41 | for i in range(n_samples): 42 | for j in range(n_features): 43 | X[i, j] = self.feature_vec[j].evaluate( 44 | # TODO use all input dimensions 45 | input_data[i, 0], input_data[i, 1]) # modify this line 46 | return X 47 | 48 | def fit(self, input_data, output_data): 49 | n_features = len(self.feature_vec) 50 | assert n_features > 0, 'Please set the feature vector first.' 51 | # In general don't use assertions in deployment code, use hard checks, as 52 | # assertions get compiled away when optimization is used. 53 | if (n_features < 1): 54 | raise ProgrammaticError("Please set the feature vector first.") 55 | n_samples = input_data.shape[0] 56 | X = self.compute_feature_matrix(input_data) 57 | # Least squares parameter estimation 58 | self.beta = np.dot(np.dot(np.linalg.inv(np.dot(X.T, X)), X.T), output_data) 59 | self.fitting_done = True 60 | print('Done with fitting of the model.') 61 | 62 | def predict(self, input_data): 63 | # In general don't use assertions in deployment code, use hard checks, as 64 | # assertions get compiled away when optimization is used. 65 | if not self.fitting_done: 66 | raise ProgrammaticError("Before you use the model for query, you have " 67 | "to set the feature vector and fit it.") 68 | n_features = len(self.feature_vec) 69 | n_data = input_data.shape[0] 70 | X = self.compute_feature_matrix(input_data) 71 | return np.dot(X, self.beta) 72 | 73 | def validate(self, validation_input, validation_output): 74 | return np.mean(self.error_function(self.predict(validation_input), 75 | validation_output)) 76 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/regression/linear_regression.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import Features as features 4 | import LinearRegressionModel as model 5 | import DataSaver as saver 6 | import matplotlib.pyplot as plt 7 | import pickle as pkl 8 | 9 | # Remove lapack warning on OSX (https://github.com/scipy/scipy/issues/5998). 10 | import warnings 11 | warnings.filterwarnings(action="ignore", module="scipy", 12 | message="^internal gelsd") 13 | 14 | plt.close('all') 15 | 16 | # TODO decide if you want to show the plots to compare input and output data 17 | show_plots = False 18 | 19 | # data_generator = data.DataGenerator() 20 | data_saver = saver.DataSaver('data', 'data_samples.pkl') 21 | input_data, output_data = data_saver.restore_from_file() 22 | n_samples = input_data.shape[0] 23 | if(show_plots): 24 | plt.figure(0) 25 | plt.scatter(input_data[:, 0], output_data[:, 0]) 26 | plt.xlabel("x1") 27 | plt.ylabel("y") 28 | plt.figure(1) 29 | plt.scatter(input_data[:, 1], output_data[:, 0]) 30 | plt.xlabel("x2") 31 | plt.ylabel("y") 32 | if (input_data.shape[1] > 2): 33 | plt.figure(2) 34 | plt.scatter(input_data[:, 2], output_data[:, 0]) 35 | plt.xlabel("x3") 36 | plt.ylabel("y") 37 | plt.figure(3) 38 | plt.scatter(input_data[:, 3], output_data[:, 0]) 39 | plt.xlabel("x4") 40 | plt.ylabel("y") 41 | 42 | 43 | # Split data into training and validation 44 | # TODO Overcome the problem of differently biased data 45 | ratio_train_validate = 0.8 46 | idx_switch = int(n_samples * ratio_train_validate) 47 | training_input = input_data[:idx_switch, :] 48 | training_output = output_data[:idx_switch, :] 49 | validation_input = input_data[idx_switch:, :] 50 | validation_output = output_data[idx_switch:, :] 51 | 52 | # Fit model 53 | lm = model.LinearRegressionModel() 54 | # TODO use and select the new features 55 | lm.set_feature_vector([features.LinearX1(), features.LinearX2(), 56 | features.SquareX1(), features.ExpX2(), 57 | features.LogX1(), features.Identity()]) 58 | lm.fit(training_input, training_output) 59 | 60 | 61 | # Validation 62 | mse = lm.validate(validation_input, validation_output) 63 | print('MSE: {}'.format(mse)) 64 | print(' ') 65 | print('feature weights \n{}'.format(lm.beta)) 66 | 67 | # load submission data 68 | submission_loader = saver.DataSaver('data', 'submission_data.pkl') 69 | submission_input = submission_loader.load_submission() 70 | 71 | # predict output 72 | submission_output = lm.predict(submission_input) 73 | 74 | #save output 75 | pkl.dump(submission_output, open("results.pkl", 'wb')) 76 | 77 | plt.show() 78 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/sampling/SamplePdf.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import scipy.optimize 4 | 5 | 6 | class SamplePdf(): 7 | 8 | k = 0 # number of samples 9 | uni_sample = np.array([]) # array containing the uniform samples 10 | pdf_sample = np.array([]) # array containing the new samples of the pdf 11 | 12 | # function that is called by the root function 13 | def cdf_root(self, x, sample): 14 | # TODO: add the correct function here, note that we can not formulate the solving in terms of F(x)=y but rather F(x,y)=0 (solved for x) 15 | root = x - sample # modify this line 16 | return root 17 | 18 | def __init__(self, k=1000): 19 | self.k = k 20 | self.uni_sample.resize(k) 21 | self.pdf_sample.resize(k) 22 | 23 | def sample_pdf(self, uni_sample): 24 | self.uni_sample = uni_sample 25 | # loop through all samples 26 | for i in range(self.uni_sample.size): 27 | # We have to invert the CDF function to get the new sample. 28 | # As there is no analytical solution we can use the scipy.optimize function root 29 | # Generally the root function looks for the root of the input function F(x), i.e. F(x) = 0 is solved for x 30 | # if we want to have an additional argument to the function that is not optimized for we pass it using the 'args' setting we can set 31 | # so passing y to the args setting of the root function we can solve F(x,y) = 0 for x 32 | 33 | # TODO add the correct call of the scipy.optimize.root(...) function 34 | root = 0 # modify this line 35 | 36 | self.pdf_sample[i] = root.x 37 | 38 | # plot the results in a histogram 39 | def plot_result(self): 40 | if self.pdf_sample.size == 0: 41 | print("First sample_pdf needs to be called") 42 | return 43 | # for a nicer plot only show the values between -5 and 10 44 | cond1 = self.pdf_sample >= 10 45 | cond2 = self.pdf_sample <= -5 46 | # get index for elements statisfying condition 1 or 2 47 | index = [i for i, v in enumerate((cond1 | cond2)) if v] 48 | 49 | # remove elements with the given index and plot as histogram 50 | plt.hist(np.delete(self.pdf_sample, index), bins=100, normed=True) 51 | 52 | # plot the reference plot 53 | x = np.arange(-5.0, 10.0, 0.01) 54 | # TODO: calculate the values of f(x) 55 | y = x # modify this line 56 | plt.plot(x, y) 57 | 58 | plt.show() 59 | return 60 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/sampling/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import SamplePdf 4 | import numpy as np 5 | import os 6 | 7 | num_samples = 5000 8 | 9 | uni_samples = np.zeros(num_samples) 10 | 11 | # TODO: draw uniform samples 12 | # uni_samples = XXX 13 | 14 | # create instance of our new PDF sampler 15 | my_pdf_sampler = SamplePdf.SamplePdf(num_samples) 16 | 17 | # feed the uniform samples and create our custom ones 18 | # TODO this function needs to be implemented in SamplePdf.py 19 | new_samples = my_pdf_sampler.sample_pdf(uni_samples) 20 | 21 | my_pdf_sampler.plot_result() 22 | 23 | # safe the result in a struct 24 | pkl.dump(new_samples, open("results.pkl", 'wb')) 25 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/solution/bayes_filter/BayesianFiltering.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import scipy.ndimage.filters as filters 3 | import matplotlib.pyplot as plt 4 | import time 5 | 6 | 7 | def histogram_plot(pos, title=None, c='b'): 8 | axis = plt.gca() 9 | x = np.arange(len(pos)) 10 | axis.bar(x, pos, color=c) 11 | plt.ylim((0, 1)) 12 | plt.xticks(np.asarray(x) + 0.4, x) 13 | if title is not None: 14 | plt.title(title) 15 | 16 | 17 | def normalize(input): 18 | return input / np.sum(input) 19 | 20 | 21 | def compute_likelihood(map, measurement, prob_correct_measurement): 22 | likelihood = np.ones(len(map)) 23 | likelihood[map == measurement] *= prob_correct_measurement 24 | likelihood[map != measurement] *= (1 - prob_correct_measurement) 25 | return likelihood 26 | 27 | 28 | def measurement_update(prior, likelihood): 29 | posterior = prior * likelihood 30 | return normalize(posterior) 31 | 32 | 33 | def prior_update(posterior, movement, movement_noise_kernel): 34 | kernel = movement_noise_kernel 35 | if movement < 0: 36 | kernel = np.flip(kernel, 0) 37 | return filters.convolve(np.roll(posterior, movement), kernel, mode='wrap') 38 | 39 | 40 | def run_bayes_filter(measurements, motions, plot_histogram=False): 41 | map = np.array( 42 | [0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0]) 43 | sensor_prob_correct_measure = 0.9 44 | movement_noise_kernel = np.array([0.15, 0.8, 0.05]) 45 | 46 | # Assume uniform distribution since you do not know the starting position 47 | prior = np.array([1. / 20] * 20) 48 | likelihood = np.zeros(len(prior)) 49 | 50 | number_of_iterations = len(measurements) 51 | if plot_histogram: 52 | fig = plt.figure("Bayes Filter") 53 | for iteration in range(number_of_iterations): 54 | # Compute the likelihood 55 | likelihood = compute_likelihood(map, measurements[iteration], 56 | sensor_prob_correct_measure) 57 | 58 | # Compute posterior 59 | posterior = measurement_update(prior, likelihood) 60 | if plot_histogram: 61 | plt.cla() 62 | histogram_plot(map, title="Measurement update", c='k') 63 | histogram_plot(posterior, title="Measurement update", c='y') 64 | fig.canvas.draw() 65 | plt.show(block=False) 66 | time.sleep(.5) 67 | 68 | # Update prior 69 | prior = prior_update(posterior, motions[iteration], 70 | movement_noise_kernel) 71 | if plot_histogram: 72 | plt.cla() 73 | histogram_plot(map, title="Prior update", c='k') 74 | histogram_plot(prior, title="Prior update") 75 | fig.canvas.draw() 76 | plt.show(block=False) 77 | time.sleep(.5) 78 | plt.show() 79 | return prior 80 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/solution/bayes_filter/data_1.pkl: -------------------------------------------------------------------------------- 1 | cnumpy.core.multiarray 2 | _reconstruct 3 | p0 4 | (cnumpy 5 | ndarray 6 | p1 7 | (I0 8 | tp2 9 | S'b' 10 | p3 11 | tp4 12 | Rp5 13 | (I1 14 | (I2 15 | I30 16 | tp6 17 | cnumpy 18 | dtype 19 | p7 20 | (S'i8' 21 | p8 22 | I0 23 | I1 24 | tp9 25 | Rp10 26 | (I3 27 | S'<' 28 | p11 29 | NNNI-1 30 | I-1 31 | I0 32 | tp12 33 | bI00 34 | S'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xfd\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff' 35 | p13 36 | tp14 37 | b. -------------------------------------------------------------------------------- /1_0_probability_ml_basics/solution/bayes_filter/data_2.pkl: -------------------------------------------------------------------------------- 1 | cnumpy.core.multiarray 2 | _reconstruct 3 | p0 4 | (cnumpy 5 | ndarray 6 | p1 7 | (I0 8 | tp2 9 | S'b' 10 | p3 11 | tp4 12 | Rp5 13 | (I1 14 | (I2 15 | I30 16 | tp6 17 | cnumpy 18 | dtype 19 | p7 20 | (S'i8' 21 | p8 22 | I0 23 | I1 24 | tp9 25 | Rp10 26 | (I3 27 | S'<' 28 | p11 29 | NNNI-1 30 | I-1 31 | I0 32 | tp12 33 | bI00 34 | S'\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xfd\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff\xff\xff\xff\xff\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xff\xff\xff\xff\xff\xff\xff\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00' 35 | p13 36 | tp14 37 | b. -------------------------------------------------------------------------------- /1_0_probability_ml_basics/solution/bayes_filter/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import pickle as pkl 4 | import numpy as np 5 | import BayesianFiltering 6 | 7 | 8 | class ProgrammaticError(Exception): 9 | """Exception raised when method gets called at a wrong time instance. 10 | Attributes: 11 | msg -- The error message to be displayed. 12 | """ 13 | 14 | def __init__(self, msg): 15 | self.msg = msg 16 | print("\033[91mERROR: \x1b[0m {}".format(msg)) 17 | 18 | 19 | data = pkl.load(open("data_1.pkl", 'rb')) 20 | measurements = data[0, :] 21 | motions = data[1, :] 22 | 23 | if (len(measurements) != len(motions)): 24 | raise ProgrammaticError( 25 | 'Size of the measurements and motions needs to be the same!') 26 | 27 | result = BayesianFiltering.run_bayes_filter( 28 | measurements, motions, plot_histogram=True) 29 | pkl.dump(result, open("result_bayes_1.pkl", 'wb')) 30 | 31 | data = pkl.load(open("data_2.pkl", 'rb')) 32 | measurements = data[0, :] 33 | motions = data[1, :] 34 | 35 | if (len(measurements) != len(motions)): 36 | raise ProgrammaticError( 37 | 'Size of the measurements and motions needs to be the same!') 38 | 39 | result = BayesianFiltering.run_bayes_filter( 40 | measurements, motions, plot_histogram=True) 41 | pkl.dump(result, open("result_bayes_2.pkl", 'wb')) 42 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/solution/regression/DataGenerator.py: -------------------------------------------------------------------------------- 1 | import NoiseModel as noise 2 | import Features as features 3 | import DataSaver as saver 4 | 5 | import numpy as np 6 | import pickle as pkl 7 | import os 8 | 9 | 10 | class DataGenerator(): 11 | """ 12 | Data generation for linear regression example. 13 | """ 14 | 15 | feature_vec = [] 16 | feature_weights = [] 17 | noise_model = noise.NoiseModel(0, 8) 18 | input_data = np.zeros([0, 5]) 19 | output_data = np.zeros([0, 1]) 20 | max_x1 = 0 21 | max_x2 = 0 22 | max_x3 = 0 23 | max_x4 = 0 24 | 25 | saver = None 26 | 27 | def __init__(self): 28 | self.feature_vec = [features.CrossTermX1X3(), features.SinX2(), 29 | features.SquareX4(), features.Identity()] 30 | self.feature_weights = [0.1, -2, -0.3, 3] 31 | self.noise_model = noise.NoiseModel() 32 | self.max_x1 = 10 33 | self.max_x2 = 10 34 | self.max_x3 = 10 35 | self.max_x4 = 10 36 | self.saver = saver.DataSaver('data', 'submission_data.pkl') 37 | 38 | def __generate_samples__(self, n_samples): 39 | input_x1 = np.random.rand(n_samples) * self.max_x1 40 | input_x2 = np.random.rand(n_samples) * self.max_x2 41 | input_x3 = np.random.rand(n_samples) * self.max_x3 42 | input_x4 = np.random.rand(n_samples) * self.max_x4 43 | self.input_data = np.array([input_x1, input_x2, input_x3, input_x4]).T 44 | self.output_data = np.zeros([n_samples, 1]) 45 | 46 | for i in range(n_samples): 47 | out_value = 0 48 | for f, w in zip(self.feature_vec, self.feature_weights): 49 | out_value += w * \ 50 | f.evaluate(self.input_data[i, 0], self.input_data[i, 1], self.input_data[i, 2], self.input_data[i, 3]) 51 | 52 | out_value += self.noise_model.sample() 53 | self.output_data[i] = out_value 54 | 55 | return self.input_data, self.output_data 56 | 57 | def sample(self, n_samples): 58 | if self.output_data.shape[0] == n_samples: 59 | print('Returning pre-generated samples.') 60 | return self.input_data, self.output_data 61 | else: 62 | print('Generating new samples.') 63 | return self.__generate_samples__(n_samples) 64 | 65 | def save(self): 66 | self.saver.save_to_file(self.input_data), self.output_data) 67 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/solution/regression/DataSaver.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pickle as pkl 3 | import os 4 | 5 | 6 | class DataSaver(): 7 | 8 | directory = '' 9 | filename = '' 10 | path = '' 11 | 12 | def __init__(self, directory, filename): 13 | self.directory = directory 14 | self.filename = filename 15 | self.path = os.path.join(self.directory, self.filename) 16 | if not os.path.exists(self.directory): 17 | os.mkdir(self.directory) 18 | 19 | def save_to_file(self, input_data, output_data): 20 | data = np.hstack([input_data, output_data]) 21 | print('Saving data to relative path {}'.format(self.path)) 22 | pkl.dump(data, open(self.path, 'wb')) 23 | 24 | def restore_from_file(self): 25 | data = pkl.load(open(self.path, 'rb')) 26 | input_data = data[:, 0:4] 27 | output_data = np.reshape(data[:, 4], [data[:, 2].shape[0], 1]) 28 | return input_data, output_data 29 | 30 | def load_submission(self): 31 | data = pkl.load(open(self.path, 'rb')) 32 | input_data = data[:, 0:4] 33 | return input_data 34 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/solution/regression/Features.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | import math 3 | import numpy as np 4 | 5 | 6 | class Feature(): 7 | """ 8 | Feature base class. 9 | """ 10 | __metaClass__ = ABCMeta 11 | 12 | @abstractmethod 13 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 14 | pass 15 | 16 | 17 | # Feature classes 18 | class LinearX1(Feature): 19 | 20 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 21 | return x1 22 | 23 | 24 | class LinearX2(Feature): 25 | 26 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 27 | return x2 28 | 29 | 30 | class CrossTermX1X3(Feature): 31 | 32 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 33 | return x1 * x3 34 | 35 | 36 | class SinX2(Feature): 37 | 38 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 39 | return np.sin(x2) 40 | 41 | 42 | class SquareX4(Feature): 43 | 44 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 45 | return x4**2 46 | 47 | 48 | class SquareX1(Feature): 49 | 50 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 51 | return x1**2 52 | 53 | 54 | class SquareX2(Feature): 55 | 56 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 57 | return x2**2 58 | 59 | 60 | class CrossTermX1X2(Feature): 61 | 62 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 63 | return x1 * x2 64 | 65 | 66 | class ExpX1(Feature): 67 | 68 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 69 | return math.exp(x1) 70 | 71 | 72 | class ExpX2(Feature): 73 | 74 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 75 | return math.exp(x2) 76 | 77 | 78 | class LogX1(Feature): 79 | 80 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 81 | return math.log(x1) 82 | 83 | 84 | class LogX2(Feature): 85 | 86 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 87 | return math.log(x2) 88 | 89 | 90 | class Identity(Feature): 91 | 92 | def evaluate(self, x1, x2, x3 = 0, x4 = 0): 93 | return 1 94 | 95 | # TODO add the new features 96 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/solution/regression/LinearRegressionModel.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | class ProgrammaticError(Exception): 5 | """Exception raised when method gets called at a wrong time instance. 6 | 7 | Attributes: 8 | msg -- The error message to be displayed. 9 | """ 10 | 11 | def __init__(self, msg): 12 | self.msg = msg 13 | print("\033[91mERROR: \x1b[0m {}".format(msg)) 14 | 15 | 16 | class LinearRegressionModel(): 17 | """ 18 | Class for linear regression model. 19 | """ 20 | 21 | # Members 22 | # Vector in equation: y = F(x,y) * beta, where F(x,y) is the feature vector 23 | beta = None 24 | feature_vec = [] 25 | fitting_done = False 26 | 27 | def __init__(self): 28 | self.feature_vec = [] 29 | self.fitting_done = False 30 | 31 | def error_function(self, predictions, target_values): 32 | return (predictions - target_values)**2 33 | 34 | def set_feature_vector(self, feature_vec): 35 | self.feature_vec = feature_vec 36 | 37 | def compute_feature_matrix(self, input_data): 38 | n_samples = input_data.shape[0] 39 | n_features = len(self.feature_vec) 40 | X = np.zeros([n_samples, n_features]) 41 | for i in range(n_samples): 42 | for j in range(n_features): 43 | X[i, j] = self.feature_vec[j].evaluate( 44 | # TODO use all input dimensions 45 | input_data[i, 0], input_data[i, 1], input_data[i, 2], 46 | input_data[i, 3]) 47 | return X 48 | 49 | def fit(self, input_data, output_data): 50 | n_features = len(self.feature_vec) 51 | assert n_features > 0, 'Please set the feature vector first.' 52 | # In general don't use assertions in deployment code, use hard checks, as 53 | # assertions get compiled away when optimization is used. 54 | if (n_features < 1): 55 | raise ProgrammaticError("Please set the feature vector first.") 56 | n_samples = input_data.shape[0] 57 | X = self.compute_feature_matrix(input_data) 58 | # Least squares parameter estimation 59 | self.beta = np.dot(np.dot(np.linalg.inv(np.dot(X.T, X)), X.T), output_data) 60 | self.fitting_done = True 61 | print('Done with fitting of the model.') 62 | 63 | def predict(self, input_data): 64 | # In general don't use assertions in deployment code, use hard checks, as 65 | # assertions get compiled away when optimization is used. 66 | if not self.fitting_done: 67 | raise ProgrammaticError("Before you use the model for query, you have " 68 | "to set the feature vector and fit it.") 69 | n_features = len(self.feature_vec) 70 | n_data = input_data.shape[0] 71 | X = self.compute_feature_matrix(input_data) 72 | return np.dot(X, self.beta) 73 | 74 | def validate(self, validation_input, validation_output): 75 | return np.mean(self.error_function(self.predict(validation_input), 76 | validation_output)) 77 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/solution/regression/NoiseModel.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | class NoiseModel(): 5 | 6 | mu = 0 7 | sigma = 0 8 | 9 | def __init__(self, mu=0, sigma=1): 10 | self.mu = mu 11 | self.sigma = sigma 12 | 13 | def sample(self, sigma = -1, mu = -1): 14 | if sigma == -1: 15 | sigma = self.sigma 16 | 17 | if mu == -1: 18 | mu = self.mu 19 | 20 | return sigma * np.random.randn() + mu 21 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/solution/regression/generate_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import NoiseModel as noise 4 | import Features as features 5 | import DataGenerator as data 6 | 7 | # Remove lapack warning on OSX (https://github.com/scipy/scipy/issues/5998). 8 | import warnings 9 | warnings.filterwarnings(action="ignore", module="scipy", 10 | message="^internal gelsd") 11 | 12 | 13 | n_samples = 400 14 | data_generator = data.DataGenerator() 15 | data_generator.sample(n_samples) 16 | data_generator.save() 17 | 18 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/solution/regression/linear_regression.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import Features as features 4 | import LinearRegressionModel as model 5 | import DataSaver as saver 6 | import matplotlib.pyplot as plt 7 | import pickle as pkl 8 | import numpy as np 9 | 10 | # Remove lapack warning on OSX (https://github.com/scipy/scipy/issues/5998). 11 | import warnings 12 | warnings.filterwarnings(action="ignore", module="scipy", 13 | message="^internal gelsd") 14 | 15 | # definition of the shuffle function 16 | def shuffle_data(input_data, output_data): 17 | data = np.hstack([input_data, output_data]) 18 | np.random.shuffle(data) 19 | input_data = data[:, 0:4] 20 | output_data = data[:, 4][:, None] 21 | return input_data, output_data 22 | 23 | 24 | # Close all open plots 25 | plt.close('all') 26 | 27 | # TODO decide if you want to show the plots to compare input and output data 28 | show_plots = False 29 | 30 | # data_generator = data.DataGenerator() 31 | data_saver = saver.DataSaver('data', 'data_samples.pkl') 32 | input_data, output_data = data_saver.restore_from_file() 33 | n_samples = input_data.shape[0] 34 | if(show_plots): 35 | plt.figure(0) 36 | plt.scatter(input_data[:, 0], output_data[:, 0]) 37 | plt.xlabel("x1") 38 | plt.ylabel("y") 39 | plt.figure(1) 40 | plt.scatter(input_data[:, 1], output_data[:, 0]) 41 | plt.xlabel("x2") 42 | plt.ylabel("y") 43 | if (input_data.shape[1] > 2): 44 | plt.figure(2) 45 | plt.scatter(input_data[:, 2], output_data[:, 0]) 46 | plt.xlabel("x3") 47 | plt.ylabel("y") 48 | plt.figure(3) 49 | plt.scatter(input_data[:, 3], output_data[:, 0]) 50 | plt.xlabel("x4") 51 | plt.ylabel("y") 52 | 53 | 54 | # Split data into training and validation 55 | # TODO Overcome the problem of differently biased data 56 | ratio_train_validate = 0.8 57 | idx_switch = int(n_samples * ratio_train_validate) 58 | 59 | #randomly shuffle input and output data 60 | input_data, output_data = shuffle_data(input_data, output_data) 61 | 62 | training_input = input_data[:idx_switch, :] 63 | training_output = output_data[:idx_switch, :] 64 | validation_input = input_data[idx_switch:, :] 65 | validation_output = output_data[idx_switch:, :] 66 | 67 | # Fit model 68 | lm = model.LinearRegressionModel() 69 | # TODO use and select the new features 70 | lm.set_feature_vector([features.CrossTermX1X3(), features.SinX2(), 71 | features.SquareX4(), features.Identity()]) 72 | lm.fit(training_input, training_output) 73 | 74 | 75 | # Validation 76 | mse = lm.validate(validation_input, validation_output) 77 | print('MSE: {}'.format(mse)) 78 | print(' ') 79 | print('feature weights \n{}'.format(lm.beta)) 80 | 81 | # load submission data 82 | submission_loader = saver.DataSaver('data', 'submission_data.pkl') 83 | submission_input = submission_loader.load_submission() 84 | 85 | # predict output 86 | submission_output = lm.predict(submission_input) 87 | 88 | #save output 89 | pkl.dump(submission_output, open("results.pkl", 'wb')) 90 | 91 | plt.show() 92 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/solution/sampling/SamplePdf.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import scipy.optimize 4 | 5 | 6 | class SamplePdf(): 7 | 8 | k = 0 # number of samples 9 | uni_sample = np.array([]) # array containing the uniform samples 10 | pdf_sample = np.array([]) # array containing the new samples of the pdf 11 | 12 | # function that is called by the root function 13 | def cdf_root(self, x, sample): 14 | root = 0.5 / np.pi * (np.arctan2((x - 0), 0.3) + np.arctan2((x - 3), 15 | 0.1)) + 0.5 - sample # modify this line 16 | return root 17 | 18 | def __init__(self, k=1000): 19 | self.k = k 20 | self.uni_sample.resize(k) 21 | self.pdf_sample.resize(k) 22 | 23 | def sample_pdf(self, uni_sample): 24 | self.uni_sample = uni_sample 25 | # loop through all samples 26 | for i in range(self.uni_sample.size): 27 | # We have to invert the CDF function to get the new sample. 28 | # As there is no analytical solution we can use the scipy.optimize function root 29 | # Generally the root function looks for the root of the input function F(x), i.e. F(x) = 0 is solved for x 30 | # if we want to have an additional argument to the function that is not optimized for we pass it using the 'args' setting we can set 31 | # so passing y to the args setting of the root function we can solve F(x,y) = 0 for x 32 | 33 | root = scipy.optimize.root(self.cdf_root, x0=0, args=self.uni_sample[i]) 34 | 35 | self.pdf_sample[i] = root.x 36 | 37 | # plot the results in a histogram 38 | def plot_result(self): 39 | if self.pdf_sample.size == 0: 40 | print("First sample_pdf needs to be called") 41 | return 42 | plt.figure(0) 43 | # for a nicer plot only show the values between -5 and 10 44 | cond1 = self.pdf_sample >= 10 45 | cond2 = self.pdf_sample <= -5 46 | # get index for elements statisfying condition 1 or 2 47 | index = [i for i, v in enumerate((cond1 | cond2)) if v] 48 | 49 | # remove elements with the given index and plot as histogram 50 | plt.hist(np.delete(self.pdf_sample, index), bins=100, normed=True) 51 | 52 | # plot the reference plot 53 | x = np.arange(-5.0, 10.0, 0.01) 54 | y = 0.5 / (np.pi * 0.3 * (1 + ((x - 0.0) / 0.3)**2)) + \ 55 | 0.5 / (np.pi * 0.1 * (1.0 + ((x - 3.0) / 0.1)**2)) 56 | plt.plot(x, y) 57 | 58 | plt.show() 59 | return 60 | -------------------------------------------------------------------------------- /1_0_probability_ml_basics/solution/sampling/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import SamplePdf 4 | import numpy as np 5 | import os 6 | import pickle as pkl 7 | 8 | 9 | num_samples = 5000 10 | 11 | uni_samples = np.zeros(num_samples) 12 | 13 | uni_samples = np.random.rand(num_samples) 14 | 15 | # create instance of our new PDF sampler 16 | my_pdf_sampler = SamplePdf.SamplePdf(num_samples) 17 | 18 | # feed the uniform samples and create our custom ones 19 | new_samples = my_pdf_sampler.sample_pdf(uni_samples) 20 | 21 | my_pdf_sampler.plot_result() 22 | 23 | # safe the result in a struct 24 | pkl.dump(new_samples, open("results.pkl", 'wb')) 25 | -------------------------------------------------------------------------------- /2_0_regression_pgm/ex_2_0_regression_pgm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethz-asl/ai_for_robotics/03bb66bae99bac3acd79bc1ec6d3b9c0eeabcdf8/2_0_regression_pgm/ex_2_0_regression_pgm.pdf -------------------------------------------------------------------------------- /2_0_regression_pgm/logistic_regression/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sun Mar 26 12:13:01 2017 5 | 6 | @author: sebastian 7 | """ 8 | import numpy as np 9 | import matplotlib.pyplot as plt 10 | 11 | 12 | def logistic_function(w, x): 13 | # TODO implement the logistic function 14 | return np.dot(w.transpose(), x.transpose()) # change this line 15 | 16 | 17 | # To make it easier the 24x24 pixels have been reshaped to a vector of 576 pixels. the value corrsponds to the greyscale intensity of the pixel 18 | input_data = np.genfromtxt(open("XtrainIMG.txt")) # This is an array that has the features (all 576 pixel intensities) in the columns and all the available pictures in the rows 19 | output_data = np.genfromtxt(open("Ytrain.txt")) # This is a vector that has the classification (1 for open eye 0 for closed eye) in the rows 20 | 21 | n_samples = input_data.shape[0] 22 | n_features = input_data.shape[1] 23 | 24 | 25 | ratio_train_validate = 0.8 26 | idx_switch = int(n_samples * ratio_train_validate) 27 | training_input = input_data[:idx_switch, :] 28 | training_output = output_data[:idx_switch][:,None] 29 | validation_input = input_data[idx_switch:, :] 30 | validation_output = output_data[idx_switch:][:,None] 31 | 32 | #TODO initialise w 33 | w = 0 # change this line 34 | 35 | #TODO implement the iterative calculation of w 36 | #TODO2: modify the algorithm to account for regularization as well to improve the classifier 37 | 38 | #validation 39 | h = logistic_function(w,validation_input) 40 | output = np.round(h).transpose() 41 | 42 | error = np.abs(output-validation_output).sum() 43 | 44 | print 'wrong classification of ',(error/output.shape[0]*100),'% of the cases in the validation set' 45 | 46 | 47 | # classify test data for evaluation 48 | test_input = np.genfromtxt(open("XtestIMG.txt")) 49 | h = logistic_function(w,test_input) 50 | test_output = np.round(h).transpose() 51 | np.savetxt('results.txt', test_output) 52 | -------------------------------------------------------------------------------- /2_0_regression_pgm/markov_random_field/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import pickle as pkl 4 | import numpy as np 5 | import MarkovRandomField 6 | import cv2 7 | 8 | image1 = pkl.load(open("data_1.pkl", 'rb')) 9 | image2 = pkl.load(open("data_2.pkl", 'rb')) 10 | features1 = cv2.cvtColor(image1, cv2.COLOR_BGR2LAB) 11 | features2 = cv2.cvtColor(image2, cv2.COLOR_BGR2LAB) 12 | 13 | # TODO: Tune the parameters 14 | beta = 1 # strength of the second order clique criteria 15 | threshold = 0 # convergence threshold 16 | max_iterations = 10 # maximum number of iterations 17 | temperature_init = 5 # initial temperature 18 | discount = 1 # temperature scheduler's factor 19 | 20 | number_of_labels = 6 # number of labels in the image 21 | size_ratio = 4 # increases the image by size_ratio, just for displaying 22 | 23 | image_segmentation1 = MarkovRandomField.ImageSegmenter( 24 | beta, threshold, max_iterations, temperature_init, discount, 25 | number_of_labels, size_ratio, features1, image1) 26 | result1 = image_segmentation1.segmentImage() 27 | pkl.dump(result1, open("result_mrf_1.pkl", 'wb')) 28 | 29 | # TODO: Tune the parameters 30 | beta = 1 # strength of the second order clique criteria 31 | threshold = 0 # convergence threshold 32 | max_iterations = 10 # maximum number of iterations 33 | temperature_init = 5 # initial temperature 34 | discount = 1 # temperature scheduler's factor 35 | 36 | number_of_labels = 3 # number of labels in the image 37 | size_ratio = 4 # increases the image by size_ratio, just for displaying 38 | 39 | image_segmentation2 = MarkovRandomField.ImageSegmenter( 40 | beta, threshold, max_iterations, temperature_init, discount, 41 | number_of_labels, size_ratio, features2, image2) 42 | result2 = image_segmentation2.segmentImage() 43 | pkl.dump(result2, open("result_mrf_2.pkl", 'wb')) 44 | -------------------------------------------------------------------------------- /2_0_regression_pgm/solution/logistic_regression/Ytest.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 1 3 | 1 4 | 0 5 | 0 6 | 0 7 | 0 8 | 0 9 | 1 10 | 1 11 | 0 12 | 0 13 | 0 14 | 0 15 | 1 16 | 0 17 | 1 18 | 0 19 | 0 20 | 1 21 | 1 22 | 1 23 | 1 24 | 0 25 | 1 26 | 1 27 | 0 28 | 0 29 | 1 30 | 1 31 | 1 32 | 1 33 | 0 34 | 1 35 | 1 36 | 0 37 | 1 38 | 0 39 | 0 40 | 1 41 | 0 42 | 0 43 | 0 44 | 0 45 | 0 46 | 0 47 | 1 48 | 1 49 | 0 50 | 1 51 | 1 52 | 0 53 | 0 54 | 1 55 | 1 56 | 1 57 | 1 58 | 0 59 | 1 60 | 1 61 | 1 62 | 1 63 | 0 64 | 1 65 | 0 66 | 1 67 | 0 68 | 1 69 | 0 70 | 1 71 | 1 72 | 1 73 | 0 74 | 0 75 | 0 76 | 0 77 | 0 78 | 0 79 | 0 80 | 0 81 | 0 82 | 0 83 | 1 84 | 1 85 | 1 86 | 0 87 | 0 88 | 1 89 | 1 90 | 1 91 | 0 92 | 1 93 | 0 94 | 0 95 | 1 96 | 1 97 | 1 98 | 0 99 | 0 100 | 0 101 | 1 102 | 1 103 | 1 104 | 0 105 | 0 106 | 0 107 | 1 108 | 0 109 | 1 110 | 0 111 | 1 112 | 0 113 | 1 114 | 1 115 | 0 116 | 1 117 | 1 118 | 0 119 | 0 120 | 1 121 | 0 122 | 0 123 | 0 124 | 0 125 | 0 126 | 1 127 | 0 128 | 1 129 | 0 130 | 0 131 | 1 132 | 0 133 | 1 134 | 0 135 | 1 136 | 0 137 | 1 138 | 1 139 | 1 140 | 0 141 | 1 142 | 1 143 | 0 144 | 1 145 | 1 146 | 0 147 | 0 148 | 0 149 | 1 150 | 0 151 | -------------------------------------------------------------------------------- /2_0_regression_pgm/solution/logistic_regression/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sun Mar 26 12:13:01 2017 5 | 6 | @author: sebastian 7 | """ 8 | import numpy as np 9 | import matplotlib.pyplot as plt 10 | 11 | 12 | def logistic_function(w, x): 13 | # TODO implement the logistic function 14 | return 1/(1+np.exp(-np.dot(w.transpose(), x.transpose()))) 15 | 16 | 17 | # To make it easier the 24x24 pixels have been reshaped to a vector of 576 pixels. the value corrsponds to the greyscale intensity of the pixel 18 | input_data = np.genfromtxt(open("XtrainIMG.txt")) # This is an array that has the features (all 576 pixel intensities) in the columns and all the available pictures in the rows 19 | output_data = np.genfromtxt(open("Ytrain.txt")) # This is a vector that has the classification (1 for open eye 0 for closed eye) in the rows 20 | 21 | n_samples = input_data.shape[0] 22 | n_features = input_data.shape[1] 23 | 24 | # split data into training and validation data 25 | ratio_train_validate = 0.8 26 | idx_switch = int(n_samples * ratio_train_validate) 27 | training_input = input_data[:idx_switch, :] 28 | training_output = output_data[:idx_switch][:,None] 29 | validation_input = input_data[idx_switch:, :] 30 | validation_output = output_data[idx_switch:][:,None] 31 | 32 | #TODO initialise w 33 | w = 0.01*np.random.normal(size = [n_features, 1]) 34 | 35 | #TODO implement the iterative calculation of w 36 | #TODO2: modify the algorithm to account for regularization as well to improve the classifier 37 | lambda_v = 0.1 38 | X= training_input 39 | y = training_output 40 | q=np.zeros([X.shape[0], 1]) 41 | mu = np.zeros([X.shape[0], 1]) 42 | 43 | 44 | for j in range(0,9): 45 | for i in range(0,X.shape[0]): 46 | q[i]=logistic_function(w,X[i,:])*(1-logistic_function(w,X[i,:])) 47 | mu[i]=logistic_function(w,X[i,:]) 48 | helper1 = np.linalg.inv(np.dot(np.dot(X.transpose(),np.diag(q[:,0])),X)+lambda_v*np.eye(X.shape[1])) 49 | #helper2 = np.dot(np.dot(np.diag(q[:,0]),X),w) + y - mu + lambda_v*np.linalg.norm(w) 50 | helper2 = np.dot(X.transpose(), (mu - y)) + lambda_v*w 51 | w_new = w - np.dot(helper1,helper2) 52 | print np.linalg.norm(y-mu) 53 | w = w_new 54 | 55 | #validation 56 | h = logistic_function(w,validation_input) 57 | output = np.round(h).transpose() 58 | 59 | error = np.abs(output-validation_output).sum() 60 | 61 | print 'wrong classification of ',(error/output.shape[0]*100),'% of the cases in the validation set' 62 | 63 | 64 | # classify test data for evaluation 65 | test_input = np.genfromtxt(open("XtestIMG.txt")) 66 | h = logistic_function(w,test_input) 67 | test_output = np.round(h).transpose() 68 | np.savetxt('results.txt', test_output) 69 | -------------------------------------------------------------------------------- /2_0_regression_pgm/solution/markov_random_field/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import pickle as pkl 4 | import numpy as np 5 | import MarkovRandomField 6 | import cv2 7 | 8 | image1 = pkl.load(open("data_1.pkl", 'rb')) 9 | image2 = pkl.load(open("data_2.pkl", 'rb')) 10 | features1 = cv2.cvtColor(image1, cv2.COLOR_BGR2LAB) 11 | features2 = cv2.cvtColor(image2, cv2.COLOR_BGR2LAB) 12 | 13 | beta = 1 # strength of the second order clique criteria 14 | threshold = 1 # convergence threshold 15 | max_iterations = 100 # maximum number of iterations 16 | temperature_init = 5 # initial temperature 17 | discount = 0.2 # temperature scheduler's factor 18 | number_of_labels = 6 # number of labels in the image 19 | size_ratio = 4 # increases the image by size_ratio, just for displaying 20 | 21 | image_segmentation1 = MarkovRandomField.ImageSegmenter( 22 | beta, threshold, max_iterations, temperature_init, discount, 23 | number_of_labels, size_ratio, features1, image1) 24 | result1 = image_segmentation1.segmentImage() 25 | pkl.dump(result1, open("result_mrf_1.pkl", 'wb')) 26 | 27 | beta = 1 # strength of the second order clique criteria 28 | threshold = 1 # convergence threshold 29 | max_iterations = 100 # maximum number of iterations 30 | temperature_init = 5 # initial temperature 31 | discount = 0.2 # temperature scheduler's factor 32 | number_of_labels = 3 # number of labels in the image 33 | size_ratio = 4 # increases the image by size_ratio, just for displaying 34 | 35 | image_segmentation2 = MarkovRandomField.ImageSegmenter( 36 | beta, threshold, max_iterations, temperature_init, discount, 37 | number_of_labels, size_ratio, features2, image2) 38 | result2 = image_segmentation2.segmentImage() 39 | pkl.dump(result2, open("result_mrf_2.pkl", 'wb')) 40 | -------------------------------------------------------------------------------- /3_0_pgo_icp/ex_3_0_pgo_icp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethz-asl/ai_for_robotics/03bb66bae99bac3acd79bc1ec6d3b9c0eeabcdf8/3_0_pgo_icp/ex_3_0_pgo_icp.pdf -------------------------------------------------------------------------------- /3_0_pgo_icp/iterative_closest_point/assignment_II_1/alignment_synthetic.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sun Apr 2 10:00 2017 5 | @author: Timo Hinzmann (hitimo@ethz.ch) 6 | """ 7 | 8 | import numpy as np 9 | from matplotlib import pyplot 10 | import pylab 11 | from mpl_toolkits.mplot3d import Axes3D 12 | import copy 13 | from numpy import linalg as LA 14 | from scipy.spatial.distance import cdist 15 | 16 | def getNearestNeighbors(source, target): 17 | # TODO 18 | return indices, mean_error 19 | 20 | def computeBestTransformation(source, target): 21 | source_bar = #TODO 22 | target_bar = #TODO 23 | R_hat = computeBestRotation(source, source_bar, target, target_bar) 24 | t_hat = computeBestTranslation(source_bar, target_bar, R_hat) 25 | return getTransformationMatrix(R_hat, t_hat) 26 | 27 | def getTransformationMatrix(R, t): 28 | T = np.eye(4) 29 | # TODO 30 | return T 31 | 32 | def computeBestTranslation(source_bar, target_bar, R): 33 | # TODO 34 | return t_opt 35 | 36 | def computeBestRotation(source, source_bar, target, target_bar): 37 | # TODO 38 | R = np.eye(3) 39 | return R 40 | 41 | def main(): 42 | source_original = np.genfromtxt(open("synthetic_source.xyz")) 43 | target_original = np.genfromtxt(open("synthetic_target.xyz")) 44 | source = np.ones((4, source_original.shape[0])) 45 | target = np.ones((4, target_original.shape[0])) 46 | source[0:3,:] = np.copy(source_original.T) 47 | target[0:3,:] = np.copy(target_original.T) 48 | 49 | # Plotting. 50 | fig = pylab.figure() 51 | ax = Axes3D(fig) 52 | ax.scatter(source[0,:], source[1,:], source[2,:], color='red') 53 | ax.scatter(target[0,:], target[1,:], target[2,:], color='green') 54 | ax.view_init(azim=69, elev=-97) 55 | # pyplot.show(block=True) 56 | 57 | # Initialize. 58 | iter_max = 1000 59 | convergence_tolerance = 1.0e-16 60 | previous_mean_error = 1.0e12 61 | for iter in range(0, iter_max): 62 | 63 | # Get correspondences. 64 | target_indices, current_mean_error = getNearestNeighbors(source[0:3,:].T, target[0:3,:].T) 65 | 66 | # Compute best transformation. 67 | T = computeBestTransformation(source[0:3,:].T,target[0:3,target_indices].T) 68 | 69 | # Transform the source pointcloud. 70 | # TODO 71 | 72 | # Check convergence. 73 | if abs(previous_mean_error - current_mean_error) < convergence_tolerance: 74 | print "Converged at iteration: ", iter 75 | break 76 | else: 77 | previous_mean_error = current_mean_error 78 | 79 | # Plotting. 80 | pyplot.cla() 81 | ax.scatter(source[0,:], source[1,:], source[2,:], color='red') 82 | ax.scatter(target[0,:], target[1,:], target[2,:], color='green') 83 | pyplot.draw() 84 | ax.view_init(azim=69, elev=-97) 85 | pyplot.show(block=False) 86 | 87 | # Compute final transformation. 88 | # TODO 89 | T_final = np.eye(4) 90 | 91 | print "Final transformation: ", T_final 92 | np.savetxt('results_alignment_synthetic.txt', T_final) 93 | 94 | if __name__ == "__main__": 95 | main() 96 | -------------------------------------------------------------------------------- /3_0_pgo_icp/iterative_closest_point/assignment_II_2/alignment_real_world.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sun Apr 2 10:00 2017 5 | @author: Timo Hinzmann (hitimo@ethz.ch) 6 | """ 7 | 8 | import numpy as np 9 | from matplotlib import pyplot 10 | import pylab 11 | from mpl_toolkits.mplot3d import Axes3D 12 | import copy 13 | from numpy import linalg as LA 14 | from scipy.spatial.distance import cdist 15 | import matplotlib.pyplot as plt, numpy as np, numpy.random, scipy 16 | 17 | def main(): 18 | source_original = np.genfromtxt(open("vision_source.xyz")) 19 | target_original = np.genfromtxt(open("laser_target.xyz")) 20 | source = np.ones((4, source_original.shape[0])) 21 | target = np.ones((4, target_original.shape[0])) 22 | source[0:3,:] = np.copy(source_original[:,0:3].T) 23 | target[0:3,:] = np.copy(target_original[:,0:3].T) 24 | 25 | # Plotting. 26 | fig = pylab.figure() 27 | ax = Axes3D(fig) 28 | # Visualize only every 10th point. You can change this for quicker visualization. 29 | n = 10 30 | source_vis = np.copy(source[:,::n]) 31 | target_vis = np.copy(target[:,::n]) 32 | ax.scatter(source_vis[0,:], source_vis[1,:], source_vis[2,:], color='red', lw = 0, s=1) 33 | ax.scatter(target_vis[0,:], target_vis[1,:], target_vis[2,:], color='green', lw = 0, s=1) 34 | # Make sure that the aspect ratio is equal for x/y/z axis. 35 | X = target_vis[0,:] 36 | Y = target_vis[1,:] 37 | Z = target_vis[2,:] 38 | max_range = np.array([X.max()-X.min(), Y.max()-Y.min(), Z.max()-Z.min()]).max() / 2.0 39 | mid_x = (X.max()+X.min()) * 0.5 40 | mid_y = (Y.max()+Y.min()) * 0.5 41 | mid_z = (Z.max()+Z.min()) * 0.5 42 | ax.set_xlim(mid_x - max_range, mid_x + max_range) 43 | ax.set_ylim(mid_y - max_range, mid_y + max_range) 44 | ax.set_zlim(mid_z - max_range, mid_z + max_range) 45 | ax.set_aspect('equal') 46 | pyplot.show(block=True) 47 | 48 | # Align 'source' to 'target' pointcloud and compute the final transformation. 49 | # Feel free to reuse code from the previous exercise. 50 | # TODO 51 | T_final = np.eye(4) 52 | 53 | # Don't forget to save the final transformation. 54 | print "Final transformation: ", T_final 55 | np.savetxt('results_alignment_real_world.txt', T_final) 56 | 57 | if __name__ == "__main__": 58 | main() 59 | -------------------------------------------------------------------------------- /3_0_pgo_icp/pose_graph_optimization/assignment_I_1/data_1D.txt: -------------------------------------------------------------------------------- 1 | 0 0 1 1.1 2 | 0 1 2 1.0 3 | 0 2 3 1.1 4 | 0 3 4 -2.7 5 | 1 4 0 0.0 6 | -------------------------------------------------------------------------------- /3_0_pgo_icp/pose_graph_optimization/assignment_I_2/pgo_2D.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sun Apr 2 10:00 2017 5 | @author: Timo Hinzmann (hitimo@ethz.ch) 6 | """ 7 | 8 | import numpy as np 9 | import matplotlib.pyplot as plt 10 | from scipy.sparse import linalg as sla 11 | from scipy import array, linalg, dot 12 | from enum import Enum 13 | import copy 14 | import pylab 15 | 16 | def main(): 17 | 18 | vertices = np.genfromtxt(open("vertices.dat")) 19 | edges = np.genfromtxt(open("edges.dat")) 20 | lc = np.genfromtxt(open("loop_closures.dat")) 21 | 22 | pylab.plot(vertices[:,1], vertices[:,2], 'b') 23 | plt.pause(5) 24 | 25 | # TODO 26 | # Create and optimize the pose graph. 27 | # Feel free to reuse code from the 1D robot exercise. 28 | 29 | # Save the optimized states in rows: [x_0, y_0, th_0; x_1, y_1, th_1; ...] 30 | x_opt = [vertices[:,1].T, vertices[:,2].T, vertices[:,3].T] 31 | np.savetxt('results_2D.txt', np.transpose(x_opt)) 32 | 33 | if __name__ == "__main__": 34 | main() 35 | -------------------------------------------------------------------------------- /3_0_pgo_icp/solution/3_0_pgo_icp_reference_solution_score_sheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethz-asl/ai_for_robotics/03bb66bae99bac3acd79bc1ec6d3b9c0eeabcdf8/3_0_pgo_icp/solution/3_0_pgo_icp_reference_solution_score_sheet.pdf -------------------------------------------------------------------------------- /3_0_pgo_icp/solution/README.md: -------------------------------------------------------------------------------- 1 | # Ex3 - Solutions 2 | 3 | Weighted as follows: I.1 (0.4), I.2 (0.1), II.1 (0.4), II.2 (0.1) 4 | 5 | ### I.1 6 | Score computed based on RMSE (linear): 7 | ``` 8 | RMSE(student) >= RMSE(odometry): score = 0.0 9 | RMSE(student) <= RMSE(reference_optimizer): score = 100 10 | ``` 11 | 12 | ### I.2 13 | Score computed based on RMSE (linear): 14 | ``` 15 | RMSE(student) >= RMSE(odometry): score = 0.0 16 | RMSE(student) <= RMSE(reference_optimizer_olsen): score = 100 17 | ``` 18 | The reference solution is computed using [1] but many different approaches lead to good results. 19 | 20 | [1]: E. Olsen et al., "Fast Iterative Alignment of Pose Graphs with Poor Initial Estimates", 2006 21 | 22 | ### II.1 23 | Score computed based on transformation (translation and rotation) error (linear): 24 | ``` 25 | error(student) >= error(initial_transformation): score = 0.0 26 | error(student) = error(ground_truth): score = 100.0 27 | ``` 28 | 29 | ### II.2 30 | Score computed based on transformation (translation and rotation) error (linear): 31 | ``` 32 | error(student) >= (7.0): score = 0.0 33 | error(student) <= (2.9): score = 100.0 34 | ``` 35 | The reference solution is computed using ICP but many different approaches lead to good results. 36 | A relatively high error was tolerated since there is no unique point-to-point mapping. 37 | 38 | -------------------------------------------------------------------------------- /3_0_pgo_icp/solution/iterative_closest_point/assignment_II_1/alignment_synthetic.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sun Apr 2 10:00 2017 5 | @author: Timo Hinzmann (hitimo@ethz.ch) 6 | """ 7 | 8 | import numpy as np 9 | from matplotlib import pyplot 10 | import pylab 11 | from mpl_toolkits.mplot3d import Axes3D 12 | import copy 13 | from numpy import linalg as LA 14 | from scipy.spatial.distance import cdist 15 | 16 | def getNearestNeighbors(source, target): 17 | euclidean_distances = cdist(source, target, 'euclidean') 18 | indices = euclidean_distances.argmin(axis=1) 19 | errors = euclidean_distances[np.arange(euclidean_distances.shape[0]), indices] 20 | mean_error = np.sum(errors) / errors.size 21 | return indices, mean_error 22 | 23 | def computeBestTransformation(source, target): 24 | N = source.shape[0] 25 | sum_source = 0.0 26 | sum_target = 0.0 27 | for i in range(0, source.shape[0]): 28 | sum_source += source[i] 29 | sum_target += target[i] 30 | source_bar = np.dot(1.0/N, sum_source) 31 | target_bar = np.dot(1.0/N, sum_target) 32 | R_hat = computeBestRotation(source, source_bar, target, target_bar) 33 | t_hat = computeBestTranslation(source_bar, target_bar, R_hat) 34 | return getTransformationMatrix(R_hat, t_hat) 35 | 36 | def getTransformationMatrix(R,t): 37 | T = np.eye(4) 38 | T[0:3,0:3] = R 39 | T[0:3,3] = t 40 | return T 41 | 42 | def computeBestTranslation(source_bar, target_bar, R): 43 | t_opt = target_bar.transpose() - np.dot(R, source_bar.transpose()) 44 | return t_opt 45 | 46 | def computeBestRotation(source, source_bar, target, target_bar): 47 | M = np.zeros(shape=(3,3)) 48 | for i in range(0, source.shape[0]): 49 | M += np.outer(source[i,:]-source_bar,np.transpose(target[i,:]-target_bar)) 50 | U, D, V = np.linalg.svd(M) 51 | if np.linalg.det(U)*np.linalg.det(V) < 0: 52 | for x in range (0,3): 53 | V[2, x] *= -1; 54 | 55 | R = np.dot(V.T, U.T) 56 | return R 57 | 58 | def main(): 59 | # Uncomment to generate synthetic datasets. 60 | # Load the input pointclouds. 61 | #pcl_a = np.genfromtxt(open("pcl_a_bunny.xyz")) 62 | #pcl_b = copy.deepcopy(pcl_a) 63 | 64 | #T = [[0.9800,0.0098,-0.1987,0.1], 65 | # [0.0099,0.9952,0.0978,0.3], 66 | # [0.1987,-0.0979,0.9752,0.1], 67 | # [0.0, 0.0, 0.0, 1.0]] 68 | 69 | #for i in range(0, pcl_a.shape[0]): 70 | # p_hom_a = [pcl_a[i,0], pcl_a[i,1], pcl_a[i,2], 1.0] 71 | # p_hom_b = np.dot(T, p_hom_a) 72 | # pcl_b[i,:] = [p_hom_b[0], p_hom_b[1], p_hom_b[2]] 73 | 74 | #np.savetxt('synthetic_source.xyz', pcl_a, delimiter=' ') 75 | #np.savetxt('synthetic_target.xyz', pcl_b, delimiter=' ') 76 | 77 | # Relative path to data from exercise sheet. 78 | base = "../../../iterative_closest_point/assignment_II_1/" 79 | 80 | pcl_a = np.genfromtxt(open(base + "synthetic_source.xyz")) 81 | pcl_b = np.genfromtxt(open(base + "synthetic_target.xyz")) 82 | 83 | A = pcl_a 84 | B = pcl_b 85 | source = np.ones((4,A.shape[0])) 86 | target = np.ones((4,B.shape[0])) 87 | source[0:3,:] = np.copy(A.T) 88 | target[0:3,:] = np.copy(B.T) 89 | 90 | # Plotting. 91 | fig = pylab.figure() 92 | ax = Axes3D(fig) 93 | ax.scatter(source[0,:], source[1,:], source[2,:],color='red') 94 | ax.scatter(target[0,:], target[1,:], target[2,:],color='green') 95 | ax.view_init(azim=69, elev=-97) 96 | # pyplot.show(block=True) 97 | 98 | # Initialize. 99 | iter_max = 1000 100 | convergence_tolerance = 1.0e-16 101 | previous_mean_error = 1.0e12 102 | for iter in range(0, iter_max): 103 | 104 | # Get correspondences. 105 | target_indices, current_mean_error = getNearestNeighbors(source[0:3,:].T, target[0:3,:].T) 106 | 107 | # Compute best transformation. 108 | T = computeBestTransformation(source[0:3,:].T,target[0:3,target_indices].T) 109 | 110 | # Transform the source pointcloud. 111 | source = np.dot(T, source) 112 | 113 | # Check convergence. 114 | if abs(previous_mean_error - current_mean_error) < convergence_tolerance: 115 | print "Converged at iteration: ", iter 116 | break 117 | else: 118 | previous_mean_error = current_mean_error 119 | 120 | # Plotting 121 | pyplot.cla() 122 | ax.scatter(source[0,:], source[1,:], source[2,:],color='red') 123 | ax.scatter(target[0,:], target[1,:], target[2,:],color='green') 124 | pyplot.draw() 125 | ax.view_init(azim=69, elev=-97) 126 | pyplot.show(block=False) 127 | 128 | T_final = computeBestTransformation(A, source[0:3,:].T) 129 | print "Final transformation: ", T_final 130 | np.savetxt('results_alignment_synthetic.txt', T_final) 131 | 132 | if __name__ == "__main__": 133 | main() 134 | -------------------------------------------------------------------------------- /3_0_pgo_icp/solution/iterative_closest_point/assignment_II_1/groundtruth_alignment_synthetic.txt: -------------------------------------------------------------------------------- 1 | 0.9800 0.0098 -0.1987 0.1 2 | 0.0099 0.9952 0.0978 0.3 3 | 0.1987 -0.0979 0.9752 0.1 4 | 0.0 0.0 0.0 1.0 5 | -------------------------------------------------------------------------------- /3_0_pgo_icp/solution/iterative_closest_point/assignment_II_1/results_alignment_synthetic.txt: -------------------------------------------------------------------------------- 1 | 9.800089413592263377e-01 9.803061401642519657e-03 -1.987117883848961986e-01 1.000002676081543918e-01 2 | 9.888118414151474828e-03 9.951510490203346881e-01 9.786017958268539152e-02 3.000030363997642224e-01 3 | 1.987075740131609702e-01 -9.786873668788909075e-02 9.751599922109812635e-01 9.999810328849313701e-02 4 | 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 5 | -------------------------------------------------------------------------------- /3_0_pgo_icp/solution/iterative_closest_point/assignment_II_2/reference_alignment_real_world.txt: -------------------------------------------------------------------------------- 1 | 9.99717080e-01 2.03327474e-02 -1.23425965e-02 1.67490962e-01 2 | -2.06917633e-02 9.99344890e-01 -2.96924514e-02 1.38117013e+00 3 | 1.17307816e-02 2.99394409e-02 9.99482876e-01 -2.66080713e+01 4 | 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00 5 | -------------------------------------------------------------------------------- /3_0_pgo_icp/solution/iterative_closest_point/assignment_II_2/results_alignment_real_world.txt: -------------------------------------------------------------------------------- 1 | 9.996876422366776094e-01 2.154653057208510622e-02 -1.266352950722837885e-02 2.624802675002584351e-01 2 | -2.192019572495785065e-02 9.993050307899714602e-01 -3.014897108085326516e-02 1.176038415122501846e+00 3 | 1.200512301702006020e-02 3.041714086104718370e-02 9.994651942730098382e-01 -2.658165057747376281e+01 4 | 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 5 | -------------------------------------------------------------------------------- /3_0_pgo_icp/solution/pose_graph_optimization/assignment_I_1/ground_truth.txt: -------------------------------------------------------------------------------- 1 | 0.0 2 | 1.0 3 | 2.0 4 | 3.0 5 | 0.0 6 | -------------------------------------------------------------------------------- /3_0_pgo_icp/solution/pose_graph_optimization/assignment_I_1/results_1D.txt: -------------------------------------------------------------------------------- 1 | 8.571574822473638499e-18 2 | 1.000000000000000000e+00 3 | 1.900000000000000133e+00 4 | 2.900000000000000355e+00 5 | 9.999999999999999167e-02 6 | -------------------------------------------------------------------------------- /3_0_pgo_icp/solution/pose_graph_optimization/assignment_I_1/solution_odometry.txt: -------------------------------------------------------------------------------- 1 | 0.0 2 | 1.1 3 | 2.1 4 | 3.2 5 | 0.5 6 | -------------------------------------------------------------------------------- /3_0_pgo_icp/solution/pose_graph_optimization/assignment_I_1/solution_optimizer.txt: -------------------------------------------------------------------------------- 1 | 0.0 2 | 1.0 3 | 1.9 4 | 2.9 5 | 0.1 6 | -------------------------------------------------------------------------------- /4_0_pca_kmeans_svm/ex_4_0_pca_kmeans_svm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethz-asl/ai_for_robotics/03bb66bae99bac3acd79bc1ec6d3b9c0eeabcdf8/4_0_pca_kmeans_svm/ex_4_0_pca_kmeans_svm.pdf -------------------------------------------------------------------------------- /4_0_pca_kmeans_svm/k_means/k_means_main.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import random 3 | from scipy import misc 4 | from scipy import ndimage 5 | from sklearn import preprocessing 6 | import matplotlib.pyplot as plt 7 | from PIL import Image 8 | import os 9 | 10 | def clustering(X, mu): 11 | # TODO: Perform optimization of r_nk and fill datapoints into clusters[k] k = 0,...,1-K. 12 | clusters = {} 13 | return clusters 14 | 15 | def reevaluate_mu(mu, clusters): 16 | # TODO: Perform optimization of mu_k and return optimized mu_k. 17 | newmu = [] 18 | return newmu 19 | 20 | def has_converged(mu, oldmu): 21 | return set([tuple(j) for j in mu]) == set([tuple(j) for j in oldmu]) 22 | 23 | def find_centers(X, K): 24 | # Initialize to K random centers. 25 | # TODO: Robustify initialization towards global convergence (Exchange initialization of mu). 26 | mu = random.sample(X, K) 27 | oldmu = random.sample(X, K) 28 | 29 | while not has_converged(mu, oldmu): 30 | oldmu = mu 31 | # First step of optimization: Assign all datapoints in X to clusters. 32 | clusters = clustering(X, mu) 33 | # Second step of optimization: Optimize location of cluster centers mu. 34 | mu = reevaluate_mu(oldmu, clusters) 35 | return(mu, clusters) 36 | 37 | # Load precomputed (PCA) features from file. 38 | # WARNING: These are different from the results of the first exercise! Use the provided features file! 39 | features = np.genfromtxt(open("features_k_means.txt")) 40 | # Make sure to normalize your data, you may run into numerical issues otherwise. 41 | features = preprocessing.scale(features) 42 | n_samples, n_features = np.shape(features) 43 | # Initialize centers 44 | initial_mu = random.sample(features, 3) 45 | 46 | # Perform Lloyd's algorithm. 47 | mu, clusters = find_centers(features, 3) 48 | 49 | # Plot results. 50 | for x in range(len(clusters[0])): plt.plot(clusters[0][x][0], clusters[0][x][1], 'o', markersize=7, color='blue', alpha=0.5, label='Cluster 1') 51 | for x in range(len(clusters[1])): plt.plot(clusters[1][x][0], clusters[1][x][1], 'o', markersize=7, color='red', alpha=0.5, label='Cluster 2') 52 | for x in range(len(clusters[2])): plt.plot(clusters[2][x][0], clusters[2][x][1], 'o', markersize=7, color='green', alpha=0.5, label='Cluster 3') 53 | plt.plot([mu[0][0], mu[1][0], mu[2][0]], [mu[0][1], mu[1][1], mu[2][1]], '*', markersize=20, color='red', alpha=1.0, label='Cluster centers') 54 | plt.xlabel('principal component 1') 55 | plt.ylabel('principal component 2') 56 | plt.title('K-means clustering') 57 | plt.show() 58 | 59 | # Save results. 60 | np.savetxt('results_k_means.txt', mu) -------------------------------------------------------------------------------- /4_0_pca_kmeans_svm/principal_component_analysis/pca_main.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from sklearn import preprocessing 3 | import matplotlib.pyplot as plt 4 | 5 | # Load the dataset of orb features from file. 6 | orb_features = np.genfromtxt(open("orb_features.txt")) 7 | orb_features = orb_features.T 8 | 9 | orb_size = len(orb_features[:, 0]) 10 | # TODO: Compute covariance (exchange the value for None). 11 | cov = None 12 | 13 | # TODO: Compute eigenvectors and eigenvalues (exchange the value for None). 14 | eig_val_cov = None 15 | eig_vec_cov = None 16 | 17 | # Sort eigenvectors and corresponding eigenvalues in descending order. 18 | eig_pairs = [(np.abs(eig_val_cov[i]), eig_vec_cov[:, i]) for i in range(len(eig_val_cov))] 19 | eig_pairs.sort(key=lambda x: x[0], reverse=True) 20 | 21 | # TODO: Compute 5 dimensional feature vector based on largest eigenvalues and normalize the output (exchange the value for None). 22 | pca_features = None 23 | 24 | # Normalize pca features. 25 | pca_features = preprocessing.scale(pca_features) 26 | 27 | # 2D plot of first 2 principal components. 28 | plt.scatter(pca_features[:, 0], pca_features[:, 1], marker = 'o') 29 | plt.xlabel('principal component 1') 30 | plt.ylabel('principal component 2') 31 | plt.title('PCA result') 32 | plt.show() 33 | 34 | # Save results. 35 | np.savetxt('results_pca.txt', pca_features) 36 | -------------------------------------------------------------------------------- /4_0_pca_kmeans_svm/solution/k_means/k_means_main.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import random 3 | from scipy import misc 4 | from scipy import ndimage 5 | from sklearn import preprocessing 6 | import matplotlib.pyplot as plt 7 | from PIL import Image 8 | import os 9 | 10 | def clustering(X, mu): 11 | # TODO: Perform optimization of r_nk and fill datapoints into clusters[k] k = 0,...,1-K. 12 | clusters = {} 13 | for x_n in X: 14 | k = 0; 15 | pairs = [(j, np.linalg.norm(x_n - mu_j)) for j, mu_j in enumerate(mu)] 16 | k, _ = min(pairs, key = lambda p:p[1]) 17 | try: 18 | clusters[k].append(x_n) 19 | except KeyError: 20 | clusters[k] = [x_n] 21 | return clusters 22 | 23 | def reevaluate_mu(mu, clusters): 24 | # TODO: Perform optimization of mu_k and return optimized mu_k. 25 | newmu = [] 26 | keys = sorted(clusters.keys()) 27 | for k in keys: 28 | newmu.append(np.mean(clusters[k], axis = 0)) 29 | return newmu 30 | 31 | def has_converged(mu, oldmu): 32 | return set([tuple(j) for j in mu]) == set([tuple(j) for j in oldmu]) 33 | 34 | def find_centers(X, K): 35 | # Initialize to K random centers. 36 | # TODO: Robustify initialization towards global convergence (Exchange initialization of mu). 37 | mu = random.sample(X, K) 38 | oldmu = random.sample(X, K) 39 | 40 | while not has_converged(mu, oldmu): 41 | oldmu = mu 42 | # First step of optimization: Assign all datapoints in X to clusters. 43 | clusters = clustering(X, mu) 44 | # Second step of optimization: Optimize location of cluster centers mu. 45 | mu = reevaluate_mu(oldmu, clusters) 46 | return(mu, clusters) 47 | 48 | # Load precomputed (PCA) features from file. 49 | # WARNING: These are different from the results of the first exercise! Use the provided features file! 50 | features = np.genfromtxt(open("features_k_means.txt")) 51 | # Make sure to normalize your data, you may run into numerical issues otherwise. 52 | features = preprocessing.scale(features) 53 | n_samples, n_features = np.shape(features) 54 | # Initialize centers 55 | initial_mu = random.sample(features, 3) 56 | 57 | # Perform Lloyd's algorithm. 58 | mu, clusters = find_centers(features, 3) 59 | 60 | # Plot results. 61 | for x in range(len(clusters[0])): plt.plot(clusters[0][x][0], clusters[0][x][1], 'o', markersize=7, color='blue', alpha=0.5, label='Cluster 1') 62 | for x in range(len(clusters[1])): plt.plot(clusters[1][x][0], clusters[1][x][1], 'o', markersize=7, color='red', alpha=0.5, label='Cluster 2') 63 | for x in range(len(clusters[2])): plt.plot(clusters[2][x][0], clusters[2][x][1], 'o', markersize=7, color='green', alpha=0.5, label='Cluster 3') 64 | plt.plot([mu[0][0], mu[1][0], mu[2][0]], [mu[0][1], mu[1][1], mu[2][1]], '*', markersize=20, color='red', alpha=1.0, label='Cluster centers') 65 | plt.xlabel('principal component 1') 66 | plt.ylabel('principal component 2') 67 | plt.title('K-means clustering') 68 | plt.show() 69 | 70 | # Save results. 71 | np.savetxt('results_k_means.txt', mu) -------------------------------------------------------------------------------- /4_0_pca_kmeans_svm/solution/k_means/results_k_means.txt: -------------------------------------------------------------------------------- 1 | -1.619147926328102116e+00 1.935276271432851691e-01 6.556670755303104503e-01 9.541031162799857857e-01 6.489036331724318263e-01 2 | 1.035154190391680551e+00 1.554638556144949835e+00 -1.539698475062869942e+00 -1.444156976672702930e+00 -7.944285897161664778e-01 3 | 2.848749931397176471e-01 -8.527639918479190673e-01 4.312348290402729933e-01 2.390506636062035284e-01 7.098778367987121363e-02 4 | -------------------------------------------------------------------------------- /4_0_pca_kmeans_svm/solution/principal_component_analysis/pca_main.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from sklearn import preprocessing 3 | import matplotlib.pyplot as plt 4 | 5 | # Load the dataset of orb features from file. 6 | orb_features = np.genfromtxt(open("orb_features.txt")) 7 | orb_features = orb_features.T 8 | 9 | orb_size = len(orb_features[:, 0]) 10 | # TODO: Compute covariance. 11 | cov = np.cov(orb_features) 12 | 13 | # TODO: Compute eigenvectors and eigenvalues. 14 | eig_val_cov, eig_vec_cov = np.linalg.eig(cov) 15 | 16 | # Sort eigenvectors and corresponding eigenvalues in descending order. 17 | eig_pairs = [(np.abs(eig_val_cov[i]), eig_vec_cov[:, i]) for i in range(len(eig_val_cov))] 18 | eig_pairs.sort(key=lambda x: x[0], reverse=True) 19 | 20 | # TODO: Compute 5 dimensional feature vector based on largest eigenvalues and normalize the output. 21 | matrix_w = np.hstack((eig_pairs[0][1].reshape(orb_size, 1), eig_pairs[1][1].reshape(orb_size, 1), 22 | eig_pairs[2][1].reshape(orb_size, 1), eig_pairs[3][1].reshape(orb_size, 1), 23 | eig_pairs[4][1].reshape(orb_size, 1))).T 24 | 25 | pca_features = np.real(matrix_w.dot(orb_features)) 26 | 27 | pca_features = pca_features 28 | 29 | # Normalize pca features. 30 | pca_features = preprocessing.scale(pca_features.T) 31 | 32 | # 2D plot of first 2 principal components. 33 | plt.scatter(pca_features[:, 0], pca_features[:, 1], marker = 'o') 34 | plt.xlabel('principal component 1') 35 | plt.ylabel('principal component 2') 36 | plt.title('PCA result') 37 | plt.show() 38 | 39 | # Save results. 40 | np.savetxt('results_pca.txt', pca_features) 41 | -------------------------------------------------------------------------------- /4_0_pca_kmeans_svm/solution/support_vector_machines/labels_svm.txt: -------------------------------------------------------------------------------- 1 | 0.000000000000000000e+00 2 | 0.000000000000000000e+00 3 | 0.000000000000000000e+00 4 | 0.000000000000000000e+00 5 | 0.000000000000000000e+00 6 | 0.000000000000000000e+00 7 | 0.000000000000000000e+00 8 | 0.000000000000000000e+00 9 | 0.000000000000000000e+00 10 | 0.000000000000000000e+00 11 | 0.000000000000000000e+00 12 | 0.000000000000000000e+00 13 | 0.000000000000000000e+00 14 | 0.000000000000000000e+00 15 | 0.000000000000000000e+00 16 | 0.000000000000000000e+00 17 | 0.000000000000000000e+00 18 | 0.000000000000000000e+00 19 | 0.000000000000000000e+00 20 | 0.000000000000000000e+00 21 | 0.000000000000000000e+00 22 | 0.000000000000000000e+00 23 | 0.000000000000000000e+00 24 | 0.000000000000000000e+00 25 | 0.000000000000000000e+00 26 | 0.000000000000000000e+00 27 | 0.000000000000000000e+00 28 | 0.000000000000000000e+00 29 | 0.000000000000000000e+00 30 | 0.000000000000000000e+00 31 | 0.000000000000000000e+00 32 | 0.000000000000000000e+00 33 | 0.000000000000000000e+00 34 | 0.000000000000000000e+00 35 | 0.000000000000000000e+00 36 | 0.000000000000000000e+00 37 | 0.000000000000000000e+00 38 | 0.000000000000000000e+00 39 | 0.000000000000000000e+00 40 | 1.000000000000000000e+00 41 | 1.000000000000000000e+00 42 | 1.000000000000000000e+00 43 | 1.000000000000000000e+00 44 | 1.000000000000000000e+00 45 | 1.000000000000000000e+00 46 | 1.000000000000000000e+00 47 | 1.000000000000000000e+00 48 | 1.000000000000000000e+00 49 | 1.000000000000000000e+00 50 | 1.000000000000000000e+00 51 | 1.000000000000000000e+00 52 | 1.000000000000000000e+00 53 | 1.000000000000000000e+00 54 | 1.000000000000000000e+00 55 | 1.000000000000000000e+00 56 | 1.000000000000000000e+00 57 | 1.000000000000000000e+00 58 | 1.000000000000000000e+00 59 | 1.000000000000000000e+00 60 | 1.000000000000000000e+00 61 | 1.000000000000000000e+00 62 | 1.000000000000000000e+00 63 | 1.000000000000000000e+00 64 | 1.000000000000000000e+00 65 | 1.000000000000000000e+00 66 | 1.000000000000000000e+00 67 | 1.000000000000000000e+00 68 | 1.000000000000000000e+00 69 | 1.000000000000000000e+00 70 | 1.000000000000000000e+00 71 | 1.000000000000000000e+00 72 | 1.000000000000000000e+00 73 | 1.000000000000000000e+00 74 | 1.000000000000000000e+00 75 | 1.000000000000000000e+00 76 | 1.000000000000000000e+00 77 | 1.000000000000000000e+00 78 | 1.000000000000000000e+00 79 | 1.000000000000000000e+00 80 | 1.000000000000000000e+00 81 | 1.000000000000000000e+00 82 | 1.000000000000000000e+00 83 | 1.000000000000000000e+00 84 | 1.000000000000000000e+00 85 | 1.000000000000000000e+00 86 | 1.000000000000000000e+00 87 | 1.000000000000000000e+00 88 | 1.000000000000000000e+00 89 | 1.000000000000000000e+00 90 | 1.000000000000000000e+00 91 | -------------------------------------------------------------------------------- /4_0_pca_kmeans_svm/solution/support_vector_machines/results_svm_Z_g_perfect.txt: -------------------------------------------------------------------------------- 1 | 0.000000000000000000e+00 2 | 0.000000000000000000e+00 3 | 1.000000000000000000e+00 4 | 0.000000000000000000e+00 5 | 1.000000000000000000e+00 6 | 0.000000000000000000e+00 7 | 0.000000000000000000e+00 8 | 1.000000000000000000e+00 9 | 1.000000000000000000e+00 10 | 1.000000000000000000e+00 11 | 1.000000000000000000e+00 12 | 1.000000000000000000e+00 13 | 1.000000000000000000e+00 14 | 1.000000000000000000e+00 15 | 1.000000000000000000e+00 16 | 1.000000000000000000e+00 17 | 1.000000000000000000e+00 18 | 1.000000000000000000e+00 19 | 1.000000000000000000e+00 20 | 1.000000000000000000e+00 21 | 1.000000000000000000e+00 22 | 0.000000000000000000e+00 23 | 0.000000000000000000e+00 24 | 1.000000000000000000e+00 25 | 1.000000000000000000e+00 26 | 0.000000000000000000e+00 27 | 1.000000000000000000e+00 28 | 1.000000000000000000e+00 29 | 1.000000000000000000e+00 30 | 1.000000000000000000e+00 31 | 1.000000000000000000e+00 32 | 1.000000000000000000e+00 33 | 1.000000000000000000e+00 34 | 1.000000000000000000e+00 35 | 1.000000000000000000e+00 36 | 1.000000000000000000e+00 37 | 1.000000000000000000e+00 38 | 1.000000000000000000e+00 39 | 1.000000000000000000e+00 40 | 1.000000000000000000e+00 41 | 1.000000000000000000e+00 42 | 1.000000000000000000e+00 43 | 1.000000000000000000e+00 44 | 1.000000000000000000e+00 45 | 1.000000000000000000e+00 46 | 1.000000000000000000e+00 47 | 1.000000000000000000e+00 48 | 1.000000000000000000e+00 49 | 1.000000000000000000e+00 50 | 0.000000000000000000e+00 51 | 1.000000000000000000e+00 52 | 0.000000000000000000e+00 53 | 0.000000000000000000e+00 54 | 1.000000000000000000e+00 55 | 0.000000000000000000e+00 56 | 1.000000000000000000e+00 57 | 1.000000000000000000e+00 58 | 1.000000000000000000e+00 59 | 1.000000000000000000e+00 60 | 0.000000000000000000e+00 61 | 1.000000000000000000e+00 62 | 1.000000000000000000e+00 63 | 0.000000000000000000e+00 64 | 0.000000000000000000e+00 65 | 1.000000000000000000e+00 66 | 1.000000000000000000e+00 67 | 1.000000000000000000e+00 68 | 1.000000000000000000e+00 69 | 1.000000000000000000e+00 70 | 0.000000000000000000e+00 71 | 0.000000000000000000e+00 72 | 0.000000000000000000e+00 73 | 0.000000000000000000e+00 74 | 0.000000000000000000e+00 75 | 0.000000000000000000e+00 76 | 0.000000000000000000e+00 77 | 0.000000000000000000e+00 78 | 0.000000000000000000e+00 79 | 1.000000000000000000e+00 80 | 0.000000000000000000e+00 81 | 0.000000000000000000e+00 82 | 0.000000000000000000e+00 83 | 0.000000000000000000e+00 84 | 0.000000000000000000e+00 85 | 0.000000000000000000e+00 86 | 0.000000000000000000e+00 87 | 0.000000000000000000e+00 88 | 0.000000000000000000e+00 89 | 0.000000000000000000e+00 90 | 1.000000000000000000e+00 91 | 0.000000000000000000e+00 92 | 0.000000000000000000e+00 93 | 0.000000000000000000e+00 94 | 0.000000000000000000e+00 95 | 0.000000000000000000e+00 96 | 0.000000000000000000e+00 97 | 0.000000000000000000e+00 98 | 1.000000000000000000e+00 99 | 0.000000000000000000e+00 100 | 0.000000000000000000e+00 101 | 1.000000000000000000e+00 102 | 1.000000000000000000e+00 103 | 1.000000000000000000e+00 104 | 0.000000000000000000e+00 105 | 0.000000000000000000e+00 106 | 0.000000000000000000e+00 107 | 0.000000000000000000e+00 108 | 0.000000000000000000e+00 109 | 0.000000000000000000e+00 110 | 0.000000000000000000e+00 111 | 0.000000000000000000e+00 112 | 0.000000000000000000e+00 113 | 0.000000000000000000e+00 114 | 0.000000000000000000e+00 115 | 1.000000000000000000e+00 116 | 1.000000000000000000e+00 117 | 0.000000000000000000e+00 118 | 0.000000000000000000e+00 119 | 0.000000000000000000e+00 120 | 0.000000000000000000e+00 121 | 0.000000000000000000e+00 122 | 0.000000000000000000e+00 123 | -------------------------------------------------------------------------------- /4_0_pca_kmeans_svm/solution/support_vector_machines/results_svm_Z_g_slack.txt: -------------------------------------------------------------------------------- 1 | 0.000000000000000000e+00 2 | 0.000000000000000000e+00 3 | 1.000000000000000000e+00 4 | 0.000000000000000000e+00 5 | 0.000000000000000000e+00 6 | 0.000000000000000000e+00 7 | 0.000000000000000000e+00 8 | 1.000000000000000000e+00 9 | 1.000000000000000000e+00 10 | 1.000000000000000000e+00 11 | 1.000000000000000000e+00 12 | 1.000000000000000000e+00 13 | 1.000000000000000000e+00 14 | 1.000000000000000000e+00 15 | 1.000000000000000000e+00 16 | 1.000000000000000000e+00 17 | 1.000000000000000000e+00 18 | 1.000000000000000000e+00 19 | 1.000000000000000000e+00 20 | 1.000000000000000000e+00 21 | 1.000000000000000000e+00 22 | 0.000000000000000000e+00 23 | 0.000000000000000000e+00 24 | 1.000000000000000000e+00 25 | 1.000000000000000000e+00 26 | 0.000000000000000000e+00 27 | 1.000000000000000000e+00 28 | 1.000000000000000000e+00 29 | 1.000000000000000000e+00 30 | 1.000000000000000000e+00 31 | 1.000000000000000000e+00 32 | 1.000000000000000000e+00 33 | 1.000000000000000000e+00 34 | 1.000000000000000000e+00 35 | 1.000000000000000000e+00 36 | 1.000000000000000000e+00 37 | 1.000000000000000000e+00 38 | 1.000000000000000000e+00 39 | 1.000000000000000000e+00 40 | 1.000000000000000000e+00 41 | 1.000000000000000000e+00 42 | 1.000000000000000000e+00 43 | 1.000000000000000000e+00 44 | 1.000000000000000000e+00 45 | 1.000000000000000000e+00 46 | 1.000000000000000000e+00 47 | 1.000000000000000000e+00 48 | 1.000000000000000000e+00 49 | 1.000000000000000000e+00 50 | 0.000000000000000000e+00 51 | 1.000000000000000000e+00 52 | 0.000000000000000000e+00 53 | 0.000000000000000000e+00 54 | 1.000000000000000000e+00 55 | 0.000000000000000000e+00 56 | 1.000000000000000000e+00 57 | 1.000000000000000000e+00 58 | 1.000000000000000000e+00 59 | 1.000000000000000000e+00 60 | 0.000000000000000000e+00 61 | 1.000000000000000000e+00 62 | 1.000000000000000000e+00 63 | 0.000000000000000000e+00 64 | 0.000000000000000000e+00 65 | 1.000000000000000000e+00 66 | 1.000000000000000000e+00 67 | 1.000000000000000000e+00 68 | 1.000000000000000000e+00 69 | 1.000000000000000000e+00 70 | 0.000000000000000000e+00 71 | 0.000000000000000000e+00 72 | 0.000000000000000000e+00 73 | 0.000000000000000000e+00 74 | 0.000000000000000000e+00 75 | 0.000000000000000000e+00 76 | 0.000000000000000000e+00 77 | 0.000000000000000000e+00 78 | 0.000000000000000000e+00 79 | 1.000000000000000000e+00 80 | 0.000000000000000000e+00 81 | 0.000000000000000000e+00 82 | 0.000000000000000000e+00 83 | 0.000000000000000000e+00 84 | 0.000000000000000000e+00 85 | 0.000000000000000000e+00 86 | 0.000000000000000000e+00 87 | 0.000000000000000000e+00 88 | 0.000000000000000000e+00 89 | 0.000000000000000000e+00 90 | 1.000000000000000000e+00 91 | 0.000000000000000000e+00 92 | 0.000000000000000000e+00 93 | 0.000000000000000000e+00 94 | 0.000000000000000000e+00 95 | 0.000000000000000000e+00 96 | 0.000000000000000000e+00 97 | 0.000000000000000000e+00 98 | 1.000000000000000000e+00 99 | 0.000000000000000000e+00 100 | 0.000000000000000000e+00 101 | 1.000000000000000000e+00 102 | 1.000000000000000000e+00 103 | 1.000000000000000000e+00 104 | 0.000000000000000000e+00 105 | 0.000000000000000000e+00 106 | 0.000000000000000000e+00 107 | 0.000000000000000000e+00 108 | 0.000000000000000000e+00 109 | 0.000000000000000000e+00 110 | 0.000000000000000000e+00 111 | 0.000000000000000000e+00 112 | 0.000000000000000000e+00 113 | 0.000000000000000000e+00 114 | 0.000000000000000000e+00 115 | 1.000000000000000000e+00 116 | 1.000000000000000000e+00 117 | 0.000000000000000000e+00 118 | 0.000000000000000000e+00 119 | 0.000000000000000000e+00 120 | 0.000000000000000000e+00 121 | 0.000000000000000000e+00 122 | 0.000000000000000000e+00 123 | -------------------------------------------------------------------------------- /4_0_pca_kmeans_svm/solution/support_vector_machines/results_svm_Z_linear.txt: -------------------------------------------------------------------------------- 1 | 0.000000000000000000e+00 2 | 0.000000000000000000e+00 3 | 1.000000000000000000e+00 4 | 0.000000000000000000e+00 5 | 1.000000000000000000e+00 6 | 0.000000000000000000e+00 7 | 0.000000000000000000e+00 8 | 1.000000000000000000e+00 9 | 1.000000000000000000e+00 10 | 1.000000000000000000e+00 11 | 1.000000000000000000e+00 12 | 1.000000000000000000e+00 13 | 1.000000000000000000e+00 14 | 1.000000000000000000e+00 15 | 1.000000000000000000e+00 16 | 1.000000000000000000e+00 17 | 1.000000000000000000e+00 18 | 1.000000000000000000e+00 19 | 1.000000000000000000e+00 20 | 1.000000000000000000e+00 21 | 1.000000000000000000e+00 22 | 1.000000000000000000e+00 23 | 0.000000000000000000e+00 24 | 1.000000000000000000e+00 25 | 1.000000000000000000e+00 26 | 0.000000000000000000e+00 27 | 1.000000000000000000e+00 28 | 1.000000000000000000e+00 29 | 1.000000000000000000e+00 30 | 1.000000000000000000e+00 31 | 1.000000000000000000e+00 32 | 1.000000000000000000e+00 33 | 1.000000000000000000e+00 34 | 1.000000000000000000e+00 35 | 1.000000000000000000e+00 36 | 1.000000000000000000e+00 37 | 1.000000000000000000e+00 38 | 1.000000000000000000e+00 39 | 1.000000000000000000e+00 40 | 1.000000000000000000e+00 41 | 1.000000000000000000e+00 42 | 1.000000000000000000e+00 43 | 1.000000000000000000e+00 44 | 1.000000000000000000e+00 45 | 1.000000000000000000e+00 46 | 1.000000000000000000e+00 47 | 1.000000000000000000e+00 48 | 1.000000000000000000e+00 49 | 1.000000000000000000e+00 50 | 1.000000000000000000e+00 51 | 1.000000000000000000e+00 52 | 0.000000000000000000e+00 53 | 0.000000000000000000e+00 54 | 1.000000000000000000e+00 55 | 0.000000000000000000e+00 56 | 1.000000000000000000e+00 57 | 1.000000000000000000e+00 58 | 1.000000000000000000e+00 59 | 1.000000000000000000e+00 60 | 0.000000000000000000e+00 61 | 1.000000000000000000e+00 62 | 1.000000000000000000e+00 63 | 0.000000000000000000e+00 64 | 0.000000000000000000e+00 65 | 1.000000000000000000e+00 66 | 1.000000000000000000e+00 67 | 1.000000000000000000e+00 68 | 1.000000000000000000e+00 69 | 1.000000000000000000e+00 70 | 0.000000000000000000e+00 71 | 0.000000000000000000e+00 72 | 0.000000000000000000e+00 73 | 0.000000000000000000e+00 74 | 0.000000000000000000e+00 75 | 0.000000000000000000e+00 76 | 0.000000000000000000e+00 77 | 0.000000000000000000e+00 78 | 0.000000000000000000e+00 79 | 1.000000000000000000e+00 80 | 1.000000000000000000e+00 81 | 0.000000000000000000e+00 82 | 0.000000000000000000e+00 83 | 0.000000000000000000e+00 84 | 0.000000000000000000e+00 85 | 0.000000000000000000e+00 86 | 0.000000000000000000e+00 87 | 0.000000000000000000e+00 88 | 0.000000000000000000e+00 89 | 0.000000000000000000e+00 90 | 0.000000000000000000e+00 91 | 0.000000000000000000e+00 92 | 0.000000000000000000e+00 93 | 0.000000000000000000e+00 94 | 0.000000000000000000e+00 95 | 1.000000000000000000e+00 96 | 0.000000000000000000e+00 97 | 0.000000000000000000e+00 98 | 1.000000000000000000e+00 99 | 0.000000000000000000e+00 100 | 0.000000000000000000e+00 101 | 1.000000000000000000e+00 102 | 0.000000000000000000e+00 103 | 1.000000000000000000e+00 104 | 0.000000000000000000e+00 105 | 0.000000000000000000e+00 106 | 0.000000000000000000e+00 107 | 0.000000000000000000e+00 108 | 0.000000000000000000e+00 109 | 0.000000000000000000e+00 110 | 0.000000000000000000e+00 111 | 0.000000000000000000e+00 112 | 0.000000000000000000e+00 113 | 0.000000000000000000e+00 114 | 0.000000000000000000e+00 115 | 0.000000000000000000e+00 116 | 1.000000000000000000e+00 117 | 0.000000000000000000e+00 118 | 0.000000000000000000e+00 119 | 0.000000000000000000e+00 120 | 0.000000000000000000e+00 121 | 0.000000000000000000e+00 122 | 1.000000000000000000e+00 123 | -------------------------------------------------------------------------------- /4_0_pca_kmeans_svm/solution/support_vector_machines/svm_main.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | 4 | from sklearn import svm 5 | from sklearn import preprocessing 6 | 7 | def visualize_2D(features, labels, clf_a, clf_b, clf_c): 8 | h = 0.02 9 | x_min, x_max = features[:, 0].min() - 1, features[:, 0].max() + 1 10 | y_min, y_max = features[:, 1].min() - 1, features[:, 1].max() + 1 11 | xx, yy = np.meshgrid(np.arange(x_min, x_max, h), 12 | np.arange(y_min, y_max, h)) 13 | for i, clf in enumerate((clf_a, clf_b, clf_c)): 14 | plt.subplot(2, 2, i + 1) 15 | plt.subplots_adjust(wspace=0.4, hspace=0.4) 16 | if clf.probability == False: 17 | Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) 18 | Z = Z.reshape(xx.shape) 19 | else: 20 | Z = clf.predict_proba(np.c_[xx.ravel(), yy.ravel()]) 21 | Z = Z[:,1].reshape(xx.shape) 22 | plt.subplot(2, 2, i + 1) 23 | plt.contourf(xx, yy, Z, cmap=plt.cm.coolwarm, alpha=0.8) 24 | plt.scatter(features[:, 0], features[:, 1], c=labels, cmap=plt.cm.coolwarm) 25 | plt.xlim(xx.min(), xx.max()) 26 | plt.ylim(yy.min(), yy.max()) 27 | plt.xlabel('principal component 1') 28 | plt.ylabel('principal component 2') 29 | plt.title('SVMs') 30 | plt.show() 31 | 32 | # Load features and labels from file. 33 | # WARNING: These are different from the results of the previous exercises! Use the provided file! 34 | features = np.genfromtxt(open("features_svm.txt")) 35 | n_samples, n_features = np.shape(features) 36 | labels = np.genfromtxt(open("labels_svm.txt")) 37 | features_evaluation = np.genfromtxt(open("features_evaluation.txt")) 38 | visualization = True 39 | 40 | # TODO: Normalize your input feature data (the evaluation data is already normalized). 41 | features = preprocessing.scale(features) 42 | 43 | # TODO: Train 3 different classifiers as specified in the exercise sheet. 44 | classifier_linear = svm.SVC(C=1, kernel='linear') 45 | classifier_linear.fit(features, labels) 46 | 47 | classifier_g_perfect = svm.SVC(C=1000000, kernel='rbf') 48 | classifier_g_perfect.fit(features, labels) 49 | 50 | classifier_g_slack = svm.SVC(C=1, kernel='rbf') 51 | classifier_g_slack.fit(features, labels) 52 | 53 | # TODO (optional): Train 3 different classifiers only on first 2 dimensions for visualization. 54 | if visualization: 55 | classifier_linear_viz = svm.SVC(C=1, kernel='linear') 56 | classifier_linear_viz.fit(features[:,[0,1]], labels) 57 | 58 | classifier_g_perfect_viz = svm.SVC(C=1000000, kernel='rbf') 59 | classifier_g_perfect_viz.fit(features[:,[0,1]], labels) 60 | 61 | classifier_g_slack_viz = svm.SVC(C=1, kernel='rbf') 62 | classifier_g_slack_viz.fit(features[:,[0,1]], labels) 63 | 64 | visualize_2D(features, labels, classifier_linear_viz, classifier_g_perfect_viz, classifier_g_slack_viz) 65 | 66 | # TODO: classify evaluation data and store classifications to file. 67 | Z_linear = classifier_linear.predict(features_evaluation) 68 | Z_g_perfect = classifier_g_perfect.predict(features_evaluation) 69 | Z_g_slack = classifier_g_slack.predict(features_evaluation) 70 | 71 | # Save probability results to file. 72 | # Z_linear, Z_g_perfect and Z_g_slack are of the form N x 1 dimensions, 73 | # with number of features N. 74 | np.savetxt('results_svm_Z_linear.txt', Z_linear) 75 | np.savetxt('results_svm_Z_g_perfect.txt', Z_g_perfect) 76 | np.savetxt('results_svm_Z_g_slack.txt', Z_g_slack) 77 | 78 | # TODO: Train the same 3 classifiers as specified in the exercise sheet with additional probability estimates. 79 | classifier_linear = svm.SVC(C=1, kernel='linear', probability=True) 80 | classifier_linear.fit(features, labels) 81 | 82 | classifier_g_perfect = svm.SVC(C=1000000, kernel='rbf', probability=True) 83 | classifier_g_perfect.fit(features, labels) 84 | 85 | classifier_g_slack = svm.SVC(C=1, kernel='rbf', probability=True) 86 | classifier_g_slack.fit(features, labels) 87 | 88 | # TODO (optional): Train 3 different classifiers with probability estimates only on first 2 dimensions for visualization. 89 | if visualization: 90 | classifier_linear_viz = svm.SVC(C=1, kernel='linear', probability=True) 91 | classifier_linear_viz.fit(features[:, [0,1]], labels) 92 | 93 | classifier_g_perfect_viz = svm.SVC(C=1000000, kernel='rbf', probability=True) 94 | classifier_g_perfect_viz.fit(features[:, [0,1]], labels) 95 | 96 | classifier_g_slack_viz = svm.SVC(C=1, kernel='rbf', probability=True) 97 | classifier_g_slack_viz.fit(features[:, [0,1]], labels) 98 | 99 | visualize_2D(features, labels, classifier_linear_viz, classifier_g_perfect_viz, classifier_g_slack_viz) 100 | 101 | # TODO: classify newly loaded features and store classification probabilities to file. 102 | P_linear = classifier_linear.predict_proba(features_evaluation) 103 | P_g_perfect = classifier_g_perfect.predict_proba(features_evaluation) 104 | P_g_slack = classifier_g_slack.predict_proba(features_evaluation) 105 | 106 | # Save probability results to file. 107 | # P_linear, P_g_perfect and P_g_slack are of the form N x 2 dimensions, 108 | # with number of features N and classification probabilities for the two classes. 109 | np.savetxt('results_svm_P_linear.txt', P_linear) 110 | np.savetxt('results_svm_P_g_perfect.txt', P_g_perfect) 111 | np.savetxt('results_svm_P_g_slack.txt', P_g_slack) -------------------------------------------------------------------------------- /4_0_pca_kmeans_svm/support_vector_machines/labels_svm.txt: -------------------------------------------------------------------------------- 1 | 0.000000000000000000e+00 2 | 0.000000000000000000e+00 3 | 0.000000000000000000e+00 4 | 0.000000000000000000e+00 5 | 0.000000000000000000e+00 6 | 0.000000000000000000e+00 7 | 0.000000000000000000e+00 8 | 0.000000000000000000e+00 9 | 0.000000000000000000e+00 10 | 0.000000000000000000e+00 11 | 0.000000000000000000e+00 12 | 0.000000000000000000e+00 13 | 0.000000000000000000e+00 14 | 0.000000000000000000e+00 15 | 0.000000000000000000e+00 16 | 0.000000000000000000e+00 17 | 0.000000000000000000e+00 18 | 0.000000000000000000e+00 19 | 0.000000000000000000e+00 20 | 0.000000000000000000e+00 21 | 0.000000000000000000e+00 22 | 0.000000000000000000e+00 23 | 0.000000000000000000e+00 24 | 0.000000000000000000e+00 25 | 0.000000000000000000e+00 26 | 0.000000000000000000e+00 27 | 0.000000000000000000e+00 28 | 0.000000000000000000e+00 29 | 0.000000000000000000e+00 30 | 0.000000000000000000e+00 31 | 0.000000000000000000e+00 32 | 0.000000000000000000e+00 33 | 0.000000000000000000e+00 34 | 0.000000000000000000e+00 35 | 0.000000000000000000e+00 36 | 0.000000000000000000e+00 37 | 0.000000000000000000e+00 38 | 0.000000000000000000e+00 39 | 0.000000000000000000e+00 40 | 1.000000000000000000e+00 41 | 1.000000000000000000e+00 42 | 1.000000000000000000e+00 43 | 1.000000000000000000e+00 44 | 1.000000000000000000e+00 45 | 1.000000000000000000e+00 46 | 1.000000000000000000e+00 47 | 1.000000000000000000e+00 48 | 1.000000000000000000e+00 49 | 1.000000000000000000e+00 50 | 1.000000000000000000e+00 51 | 1.000000000000000000e+00 52 | 1.000000000000000000e+00 53 | 1.000000000000000000e+00 54 | 1.000000000000000000e+00 55 | 1.000000000000000000e+00 56 | 1.000000000000000000e+00 57 | 1.000000000000000000e+00 58 | 1.000000000000000000e+00 59 | 1.000000000000000000e+00 60 | 1.000000000000000000e+00 61 | 1.000000000000000000e+00 62 | 1.000000000000000000e+00 63 | 1.000000000000000000e+00 64 | 1.000000000000000000e+00 65 | 1.000000000000000000e+00 66 | 1.000000000000000000e+00 67 | 1.000000000000000000e+00 68 | 1.000000000000000000e+00 69 | 1.000000000000000000e+00 70 | 1.000000000000000000e+00 71 | 1.000000000000000000e+00 72 | 1.000000000000000000e+00 73 | 1.000000000000000000e+00 74 | 1.000000000000000000e+00 75 | 1.000000000000000000e+00 76 | 1.000000000000000000e+00 77 | 1.000000000000000000e+00 78 | 1.000000000000000000e+00 79 | 1.000000000000000000e+00 80 | 1.000000000000000000e+00 81 | 1.000000000000000000e+00 82 | 1.000000000000000000e+00 83 | 1.000000000000000000e+00 84 | 1.000000000000000000e+00 85 | 1.000000000000000000e+00 86 | 1.000000000000000000e+00 87 | 1.000000000000000000e+00 88 | 1.000000000000000000e+00 89 | 1.000000000000000000e+00 90 | 1.000000000000000000e+00 91 | -------------------------------------------------------------------------------- /4_0_pca_kmeans_svm/support_vector_machines/results_svm_Y_linear.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethz-asl/ai_for_robotics/03bb66bae99bac3acd79bc1ec6d3b9c0eeabcdf8/4_0_pca_kmeans_svm/support_vector_machines/results_svm_Y_linear.txt -------------------------------------------------------------------------------- /4_0_pca_kmeans_svm/support_vector_machines/svm_main.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | 4 | from sklearn import svm 5 | from sklearn import preprocessing 6 | 7 | def visualize_2D(features, labels, clf_a, clf_b, clf_c): 8 | h = 0.02 9 | x_min, x_max = features[:, 0].min() - 1, features[:, 0].max() + 1 10 | y_min, y_max = features[:, 1].min() - 1, features[:, 1].max() + 1 11 | xx, yy = np.meshgrid(np.arange(x_min, x_max, h), 12 | np.arange(y_min, y_max, h)) 13 | for i, clf in enumerate((clf_a, clf_b, clf_c)): 14 | plt.subplot(2, 2, i + 1) 15 | plt.subplots_adjust(wspace=0.4, hspace=0.4) 16 | if clf.probability == False: 17 | Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) 18 | Z = Z.reshape(xx.shape) 19 | else: 20 | Z = clf.predict_proba(np.c_[xx.ravel(), yy.ravel()]) 21 | Z = Z[:,1].reshape(xx.shape) 22 | plt.subplot(2, 2, i + 1) 23 | plt.contourf(xx, yy, Z, cmap=plt.cm.coolwarm, alpha=0.8) 24 | plt.scatter(features[:, 0], features[:, 1], c=labels, cmap=plt.cm.coolwarm) 25 | plt.xlim(xx.min(), xx.max()) 26 | plt.ylim(yy.min(), yy.max()) 27 | plt.xlabel('principal component 1') 28 | plt.ylabel('principal component 2') 29 | plt.title('SVMs') 30 | plt.show() 31 | 32 | # Load features and labels from file. 33 | # WARNING: These are different from the results of the previous exercises! Use the provided file! 34 | features = np.genfromtxt(open("features_svm.txt")) 35 | n_samples, n_features = np.shape(features) 36 | labels = np.genfromtxt(open("labels_svm.txt")) 37 | features_evaluation = np.genfromtxt(open("features_evaluation.txt")) 38 | visualization = True 39 | 40 | # Normalize your input feature data (the evaluation data is already normalized). 41 | features = preprocessing.scale(features) 42 | 43 | # TODO: Train 3 different classifiers as specified in the exercise sheet (exchange the value for None). 44 | classifier_linear = None 45 | classifier_g_perfect = None 46 | classifier_g_slack = None 47 | 48 | # TODO (optional): Train 3 different classifiers only on first 2 dimensions for visualization (exchange the value for None). 49 | if visualization: 50 | classifier_linear_viz = None 51 | classifier_g_perfect_viz = None 52 | classifier_g_slack_viz = None 53 | visualize_2D(features, labels, classifier_linear_viz, classifier_g_perfect_viz, classifier_g_slack_viz) 54 | 55 | # TODO: classify evaluation data and store classifications to file (exchange the value for None). 56 | Y_linear = None 57 | Y_g_perfect = None 58 | Y_g_slack = None 59 | 60 | # Save probability results to file. 61 | # Y_linear, Y_g_perfect and Y_g_slack are of the form N x 1 dimensions, 62 | # with number of features N. 63 | np.savetxt('results_svm_Y_linear.txt', Y_linear) 64 | np.savetxt('results_svm_Y_g_perfect.txt', Y_g_perfect) 65 | np.savetxt('results_svm_Y_g_slack.txt', Y_g_slack) 66 | 67 | # TODO: Train the same 3 classifiers as specified in the exercise sheet with additional probability estimates (exchange the value for None). 68 | classifier_linear = None 69 | classifier_g_perfect = None 70 | classifier_g_slack = None 71 | 72 | # TODO (optional): Train 3 different classifiers with probability estimates only on first 2 dimensions for visualization (exchange the value for None). 73 | if visualization: 74 | classifier_linear_viz = None 75 | classifier_g_perfect_viz = None 76 | classifier_g_slack_viz = None 77 | visualize_2D(features, labels, classifier_linear_viz, classifier_g_perfect_viz, classifier_g_slack_viz) 78 | 79 | # TODO: classify newly loaded features and store classification probabilities to file (exchange the value for None). 80 | P_linear = None 81 | P_g_perfect = None 82 | P_g_slack = None 83 | 84 | # Save probability results to file. 85 | # P_linear, P_g_perfect and P_g_slack are of the form N x 2 dimensions, 86 | # with number of features N and classification probabilities for the two classes. 87 | np.savetxt('results_svm_P_linear.txt', P_linear) 88 | np.savetxt('results_svm_P_g_perfect.txt', P_g_perfect) 89 | np.savetxt('results_svm_P_g_slack.txt', P_g_slack) -------------------------------------------------------------------------------- /5_deep_learning/01_DL_framework/ActivationFunction.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import numpy as np 6 | from abc import ABCMeta, abstractmethod 7 | 8 | class ActivationFunction(): 9 | """ 10 | Activation function base class. 11 | """ 12 | __metaClass__ = ABCMeta 13 | 14 | @abstractmethod 15 | def evaluate(self, input): 16 | pass 17 | 18 | @abstractmethod 19 | def derivative(self, input): 20 | pass 21 | 22 | 23 | class SigmoidActivation(ActivationFunction): 24 | """ 25 | Sigmoid activation function. Sigmoid works elementwise on an array. 26 | """ 27 | def evaluate(self, input): 28 | return 1 / (1 + np.exp(-input)) 29 | 30 | def derivative(self, input): 31 | return np.multiply(self.evaluate(input), (1 - self.evaluate(input))) # dotwise multiplication 32 | 33 | 34 | class UnitActivation(ActivationFunction): 35 | """ 36 | A unit activation function. 37 | This evaluates to the input and its derivative is one. 38 | """ 39 | def evaluate(self, input): 40 | return input 41 | 42 | def derivative(self, input): 43 | return np.ones(input.shape) 44 | -------------------------------------------------------------------------------- /5_deep_learning/01_DL_framework/FCLayer.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import numpy as np 6 | 7 | 8 | class FCLayer(): 9 | """ 10 | A fully connected layer. 11 | """ 12 | 13 | activation_function = None 14 | W = None 15 | b = None 16 | layer_number = None 17 | 18 | def __init__(self, layer_number, activation_function, input_size, output_size): 19 | self.layer_number = layer_number 20 | self.activation_function = activation_function 21 | self.W = np.random.randn(input_size, output_size) 22 | self.b = np.random.randn(1, output_size) 23 | 24 | def affinePart(self, x): 25 | """ 26 | Get the affine part of the layer, excluding the activation function. 27 | """ 28 | return #TODO (output dimension should be a row vector) 29 | 30 | def output(self, x): 31 | """ 32 | Layer output. Activation function applied to affine part. 33 | """ 34 | return #TODO 35 | 36 | def derivativeActivation(self, x): 37 | """ 38 | Derivative of the activation function of this layer. 39 | Will be required by the chain rule. 40 | """ 41 | return self.activation_function.derivative(self.affinePart(x)) 42 | 43 | def inputDimension(self): 44 | return self.W.shape[0] 45 | 46 | def outputDimension(self): 47 | return self.W.shape[1] 48 | 49 | # Getters and setters 50 | def setWeights(self, W): 51 | assert self.W.shape == W.shape, 'Weight shapes are inconsistent.' 52 | self.W = W 53 | 54 | def getWeights(self): 55 | return self.W 56 | 57 | def setBiases(self, b): 58 | assert self.b.shape == b.shape, 'Bias shapes are inconsistent.' 59 | self.b = b 60 | 61 | def getBiases(self): 62 | return self.b 63 | 64 | def __len__(self): 65 | return self.outputDimension() 66 | -------------------------------------------------------------------------------- /5_deep_learning/01_DL_framework/GradientDescentOptimizer.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import Support as sup 6 | import numpy as np 7 | 8 | class GradientDescentOptimizer(): 9 | """ 10 | Gradient descent optimization for neural network parameters. 11 | """ 12 | learning_rate = 0 13 | 14 | def __init__(self, learning_rate=0.01): 15 | self.learning_rate = learning_rate 16 | 17 | def getUpdatedParameters(self, nn, gradients): 18 | """ 19 | Update parameters of the network and return them. 20 | """ 21 | #TODO: update network parameters 22 | 23 | def computeBatchGradient(self, gradient_list): 24 | """ 25 | Compute the gradient for a whole data batch from a provided gradient list. 26 | Input: 27 | Gradient list contains the gradient for each sample in the data batch. The structure is a list of variables (provided data structure support.Variable()). 28 | The weights and biases members both contain the gradients of all the layers for one data sample. 29 | Return value: 30 | One fused gradient including all data sample gradients. 31 | """ 32 | batch_gradient = gradient_list[0] 33 | for g in gradient_list[1:]: 34 | batch_gradient = batch_gradient + g 35 | return batch_gradient 36 | 37 | def updateStep(self, nn, loss_function, x_batch, y_target_batch): 38 | """ 39 | Update the NN model parameters given the loss function and a data batch. 40 | """ 41 | gradients = [] 42 | avg_batch_loss = 0 43 | batch_size = x_batch.shape[0] 44 | 45 | for i in range(x_batch.shape[0]): 46 | x = np.array([x_batch[i,:]]) 47 | y_target = np.array([y_target_batch[i,:]]) 48 | y = nn.output(x) 49 | avg_batch_loss += loss_function.evaluate(y, y_target) 50 | nn_gradient = nn.gradients(x, loss_function, y_target) 51 | gradients.append(nn_gradient) 52 | 53 | batch_gradient = self.computeBatchGradient(gradients) 54 | new_p = self.getUpdatedParameters(nn, batch_gradient) 55 | nn.setParameters(new_p) 56 | return avg_batch_loss/batch_size 57 | 58 | -------------------------------------------------------------------------------- /5_deep_learning/01_DL_framework/LossFunction.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import numpy as np 6 | from abc import ABCMeta, abstractmethod 7 | 8 | class LossFunction(): 9 | """ 10 | Loss function base class. 11 | """ 12 | __metaClass__ = ABCMeta 13 | 14 | @abstractmethod 15 | def evaluate(self, y, y_target): 16 | pass 17 | 18 | @abstractmethod 19 | def derivative(self, y, y_target): 20 | pass 21 | 22 | 23 | class SquaredErrorFunction(LossFunction): 24 | """ 25 | Squared error loss function. 26 | """ 27 | def evaluate(self, y, y_target): 28 | return 0.5 * np.sum(np.dot((y_target - y), (y_target - y).T)) 29 | 30 | def derivative(self, y, y_target): 31 | return -(y_target - y) 32 | -------------------------------------------------------------------------------- /5_deep_learning/01_DL_framework/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dube, ASL, ETH Zurich, Switzerland 4 | 5 | .PHONY: generate_data, train, eval, run_tests, clean, clean_models, clean_data, distclean 6 | 7 | generate_data: 8 | python generate_data.py 9 | 10 | train: 11 | python train_classification.py --plot --verbosity info 12 | 13 | eval: 14 | python test_classification.py --plot 15 | 16 | run_tests: 17 | python unit_tests.py 18 | 19 | clean: 20 | rm -rf *.pyc && rm -rf *~ 21 | 22 | clean_models: 23 | rm -rf models 24 | 25 | clean_data: 26 | rm -rf data 27 | 28 | distclean: 29 | $(MAKE) clean 30 | $(MAKE) clean_models 31 | $(MAKE) clean_data 32 | 33 | -------------------------------------------------------------------------------- /5_deep_learning/01_DL_framework/ModelWrapper.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import numpy as np 6 | import FCLayer as fc_layer 7 | import pickle as pkl 8 | import os 9 | 10 | class Params(): 11 | 12 | training_batch_size = 10 13 | max_training_steps = 1000 14 | print_steps = 100 15 | 16 | class ModelWrapper(): 17 | 18 | network = None 19 | optimizer = None 20 | loss_function = None 21 | x = None 22 | y_target = None 23 | params = None 24 | current_idx = 0 25 | 26 | def __init__(self, network, loss_function, optimizer, x, y_target, params): 27 | self.params = params 28 | self.network = network 29 | self.optimizer = optimizer 30 | self.loss_function = loss_function 31 | # Training data 32 | self.x = x 33 | self.y_target = y_target 34 | 35 | def setNetwork(self, network): 36 | self.network = network 37 | def getNetwork(self): 38 | return self.network 39 | 40 | def setOptimizer(self, optimizer): 41 | self.optimizer = optimizer 42 | def getOptimizer(self): 43 | return self.optimizer 44 | 45 | def getNextDataPoint(self): 46 | if self.current_idx >= self.x.shape[0]: 47 | self.current_idx = 0 48 | input_batch = np.array([self.x[self.current_idx, :]]) 49 | label_batch = np.array([self.y_target[self.current_idx, :]]) 50 | self.current_idx += 1 51 | return input_batch, label_batch 52 | 53 | def getNextTrainingBatch(self, batch_size=1): 54 | input_batch = np.zeros([batch_size, self.x.shape[1]]) 55 | label_batch = np.zeros([batch_size, self.y_target.shape[1]]) 56 | for i in range(batch_size): 57 | X, y_target = self.getNextDataPoint() 58 | input_batch[i, :] = X 59 | label_batch[i, :] = y_target 60 | return input_batch, label_batch 61 | 62 | def prediction(self, x): 63 | y_net = self.network.output(x) 64 | y = np.zeros(y_net.shape) 65 | y[0, np.argmax(y_net)] = 1 66 | return y 67 | 68 | def train(self): 69 | step = 0 70 | loss_evolution = np.zeros([self.params.max_training_steps, 2]) 71 | while step < self.params.max_training_steps: 72 | x_batch, y_target_batch = self.getNextTrainingBatch(self.params.training_batch_size) 73 | loss = self.optimizer.updateStep(self.network, self.loss_function, x_batch, y_target_batch) 74 | loss_evolution[step,:] = np.array([step, loss]) 75 | if step % self.params.print_steps == 0: 76 | print("Loss in step {} is {}.".format(step, loss)) 77 | step += 1 78 | 79 | return loss_evolution 80 | 81 | 82 | def eval(self, x, y_target): 83 | eval_size = x.shape[0] 84 | correct_classifications = 0 85 | for i in range(eval_size): 86 | prediction = self.prediction(np.array([x[i,:]])) 87 | truth = np.array([y_target[i,:]]) 88 | if np.all(prediction == truth): 89 | correct_classifications += 1.0 90 | return correct_classifications / float(eval_size) 91 | 92 | def loss(self, x, y_target): 93 | return self.loss_function.evaluate(self.prediction(x), y_target) 94 | 95 | def gradients(self, x, y_target): 96 | return self.network.gradients(x, self.loss_function, y_target) 97 | -------------------------------------------------------------------------------- /5_deep_learning/01_DL_framework/Support.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import numpy as np 6 | 7 | class Variables(): 8 | """ 9 | Variable structure for networks variables / parameters and their gradients 10 | """ 11 | weights = [] 12 | biases = [] 13 | 14 | def __init__(self): 15 | self.weights = [] 16 | self.biases = [] 17 | 18 | def __len__(self): 19 | if len(self.weights) == len(self.biases): 20 | return len(self.weights) 21 | else: 22 | print("Dimension mismatch.") 23 | raise 24 | 25 | def __mul__(self, factor): 26 | new_p = Variables() 27 | for w, b in zip(self.weights, self.biases): 28 | new_p.weights.append(w * factor) 29 | new_p.biases.append(b * factor) 30 | return new_p 31 | 32 | def __add__(self, other_variables): 33 | assert len(self.weights) == len(other_variables.weights), 'Number of weight entries have to match.' 34 | assert len(self.biases) == len(other_variables.biases), 'Number of bias entries have to match.' 35 | 36 | new_p = Variables() 37 | for w, b, o_w, o_b in zip(self.weights, self.biases, other_variables.weights, other_variables.biases): 38 | new_p.weights.append(w + o_w) 39 | new_p.biases.append(b + o_b) 40 | return new_p 41 | 42 | def __sub__(self, other_variables): 43 | return self.__add__(other_variables * (-1)) 44 | 45 | def __eq__(self, other_variables): 46 | assert len(self.weights) == len(other_variables.weights), 'Number of weight entries have to match.' 47 | assert len(self.biases) == len(other_variables.biases), 'Number of bias entries have to match.' 48 | 49 | variables_equal = True 50 | 51 | for i in range(len(self.weights)): 52 | if not np.all(self.weights[i] == other_variables.weights[i]): 53 | variables_equal = False 54 | break 55 | if not np.all(self.biases[i] == other_variables.biases[i]): 56 | variables_equal = False 57 | break 58 | 59 | return variables_equal 60 | 61 | def __ne__(self, other_variables): 62 | return not self.__eq__(other_variables) 63 | 64 | 65 | 66 | # Methods 67 | def computeScore(network, x, labels): 68 | n_samples = x.shape[0] 69 | correct_classifications = 0.0 70 | for i in range(n_samples): 71 | if np.argmax(network.output(x[i,:])) == np.argmax(labels[i,:]): 72 | correct_classifications += 1.0 73 | 74 | return correct_classifications / float(n_samples) -------------------------------------------------------------------------------- /5_deep_learning/01_DL_framework/train_classification.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 4 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 5 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 6 | 7 | import numpy as np 8 | import pylab as pl 9 | import pickle as pkl 10 | import argparse 11 | import os 12 | 13 | import ModelWrapper as model 14 | import GradientDescentOptimizer as optimizer 15 | import FCNetwork as network 16 | import LossFunction as loss 17 | import ActivationFunction as activation 18 | import Support as sup 19 | 20 | # Tabula rasa 21 | pl.close('all') 22 | 23 | def parse_args(): 24 | parser = argparse.ArgumentParser(description='Train a simple deep NN') 25 | parser.add_argument('--verbosity', help='Specify verbosity of output. (Options: error, warn, info, debug).', \ 26 | type=str, default='info') 27 | parser.add_argument('--plot', help='Activate plotting.', action='store_true', default=False) 28 | return parser.parse_args() 29 | 30 | args = parse_args() 31 | plotting_active = args.plot 32 | 33 | # Load data 34 | if os.path.exists('./data/data_train.pkl'): 35 | data_train = pkl.load(open('./data/data_train.pkl', 'rb')) 36 | else: 37 | raise Exception('Training data file does not exist.') 38 | X = data_train[0] 39 | labels_onehot = data_train[1] 40 | n_features = X.shape[1] 41 | n_classes = labels_onehot.shape[1] 42 | 43 | # Model setup 44 | # Parameters 45 | params = model.Params() 46 | params.training_batch_size = 32 47 | params.max_training_steps = 20000 48 | params.learning_rate = 0.01 49 | params.print_steps = 200 50 | 51 | # Network 52 | input_dim = n_features 53 | hidden_layer_specs = [] 54 | # TODO: update network, add more layers, ... 55 | hidden_layer_specs.append({'activation': activation.SigmoidActivation(), 'dim': 2}) 56 | output_dim = n_classes 57 | fc_net = network.FCNetwork(input_dim, output_dim, hidden_layer_specs, output_activation=activation.SigmoidActivation(), loglevel=args.verbosity) 58 | loss_function = loss.SquaredErrorFunction() 59 | gdo = #TODO: instantiate the gradient descent optimizer 60 | 61 | nn_model = model.ModelWrapper(network=fc_net, optimizer=gdo, loss_function=loss_function, 62 | x=X, y_target=labels_onehot, params=params) 63 | 64 | # Run training 65 | loss = nn_model.train() 66 | nn_model.network.saveModel('./models', 'net_lastname.pkl') 67 | 68 | score_train = sup.computeScore(fc_net, X, labels_onehot) 69 | print('The classification score on the training data is {}.'.format(score_train)) 70 | 71 | # Plotting training specs 72 | if plotting_active: 73 | pl.figure('Loss evolution') 74 | ax = pl.gca() 75 | ax.plot(loss[:,0], loss[:,1], c='b', label='training error') 76 | ax.set_ylim([-0.2, 1.2]) 77 | ax.set_xlabel('Training step') 78 | ax.set_ylabel('Training error') 79 | 80 | # Visualization of classification results 81 | mesh_step_size = 0.02 82 | x1_min, x1_max = X[:, 0].min() - .5, X[:, 0].max() + .5 83 | x2_min, x2_max = X[:, 1].min() - .5, X[:, 1].max() + .5 84 | xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, mesh_step_size), np.arange(x2_min, x2_max, mesh_step_size)) 85 | predicted_label = np.zeros(xx1.shape) 86 | 87 | for ii in range(xx1.shape[0]): 88 | for jj in range(xx1.shape[1]): 89 | x_query = np.array([[xx1[ii,jj], xx2[ii,jj]]]) 90 | y_net = fc_net.output(x_query) 91 | predicted_label[ii,jj] = np.argmax(y_net) 92 | 93 | pl.figure('Classification result') 94 | ax = pl.subplot(111) 95 | ax.pcolormesh(xx1, xx2, predicted_label, cmap=pl.cm.Spectral) 96 | # Plot training data 97 | ax.scatter(X[:, 0], X[:, 1], c=np.argmax(labels_onehot, 1), cmap=pl.cm.Spectral, s=40) 98 | ax.set_xlabel('x1') 99 | ax.set_ylabel('x2') 100 | 101 | pl.show(block=True) 102 | 103 | -------------------------------------------------------------------------------- /5_deep_learning/01_DL_framework/unit_tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 4 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 5 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 6 | 7 | #!/usr/bin/env python 8 | 9 | import unittest 10 | import numpy as np 11 | 12 | import ActivationFunction as activation 13 | import GradientDescentOptimizer as gdo 14 | import FCLayer as layer 15 | import FCNetwork as network 16 | import LossFunction as loss 17 | import Support as sup 18 | 19 | # TODO: Update and extend tests 20 | 21 | # Global variables for test network in order to be accessible in all test cases. 22 | # Input 23 | x = np.random.randn(1, 3) 24 | 25 | # Layer 1 26 | w_1 = np.random.randn(3,4) 27 | b_1 = np.random.randn(1,4) 28 | 29 | # Layer 2 30 | w_out = np.random.randn(4,2) 31 | b_out = np.random.randn(1,2) 32 | 33 | # Output labels 34 | y_target = np.random.randn(1, 2) 35 | 36 | 37 | input_dim = x.shape[1] 38 | hidden_layer_specs = [] 39 | hidden_layer_specs.append({'activation': activation.SigmoidActivation(), 'dim': w_1.shape[1]}) 40 | output_dim = y_target.shape[1] 41 | 42 | fc_net = network.FCNetwork(input_dim, output_dim, hidden_layer_specs) 43 | 44 | fc_net.layers[0].setWeights(w_1) 45 | fc_net.layers[0].setBiases(b_1) 46 | 47 | fc_net.layers[1].setWeights(w_out) 48 | fc_net.layers[1].setBiases(b_out) 49 | 50 | 51 | class TestNetwork(unittest.TestCase): 52 | 53 | # Was tested above, can be used now 54 | sigmoid = activation.SigmoidActivation() 55 | 56 | def testGradients(self): 57 | 58 | # General computations 59 | loss_function = loss.SquaredErrorFunction() 60 | y = fc_net.output(x) 61 | loss_derivative = loss_function.derivative(y, y_target) 62 | 63 | # Manually compute gradients 64 | h_1 = fc_net.evaluateLayer(1, x) 65 | output_sigmoid = self.sigmoid.evaluate(np.dot(h_1, w_out) + b_out) 66 | output_sigmoid_derivative = output_sigmoid * (1 - output_sigmoid) 67 | 68 | ## Output layer 69 | delta_out = loss_derivative * output_sigmoid_derivative 70 | L_w_out = np.dot(h_1.T, delta_out) 71 | L_b_out = delta_out 72 | 73 | ## Hidden layer 74 | delta_1 = np.dot(delta_out, w_out.T) * self.sigmoid.derivative(np.dot(x, w_1) + b_1) 75 | L_w_1 = np.dot(x.T, delta_1) 76 | L_b_1 = delta_1 77 | 78 | # Network gradients 79 | gradients = fc_net.gradients(x, loss_function, y_target) 80 | ## Output layer 81 | nn_L_w_out = gradients.weights[1] 82 | nn_L_b_out = gradients.biases[1] 83 | 84 | ## Hidden layer 85 | nn_L_w_1 = gradients.weights[0] 86 | nn_L_b_1 = gradients.biases[0] 87 | 88 | # Output derivatives 89 | self.assertTrue(np.all(nn_L_w_out.shape == w_out.shape), 'Gradient shapes of output layer do not match.') 90 | self.assertTrue(np.all(nn_L_b_out.shape == b_out.shape), 'Gradient shapes of output layer do not match.') 91 | self.assertTrue(np.all(np.isclose(L_w_out, nn_L_w_out, rtol=1.e-8))) 92 | self.assertTrue(np.all(np.isclose(L_b_out, nn_L_b_out, rtol=1.e-8))) 93 | 94 | # Hidden layer derivatives 95 | self.assertTrue(np.all(nn_L_w_1.shape == w_1.shape), 'Gradient shapes of hidden layer do not match.') 96 | self.assertTrue(np.all(nn_L_b_1.shape == b_1.shape), 'Gradient shapes of hidden layer do not match.') 97 | self.assertTrue(np.all(np.isclose(L_w_1, nn_L_w_1, rtol=1.e-8))) 98 | self.assertTrue(np.all(np.isclose(L_b_1, nn_L_b_1, rtol=1.e-8))) 99 | 100 | 101 | if __name__ == '__main__': 102 | unittest.main() 103 | -------------------------------------------------------------------------------- /5_deep_learning/02_CNN/batchmaker.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import numpy as np 6 | from random import shuffle 7 | 8 | class Batchmaker: 9 | def __init__(self, input_data, output_data, batch_size=64): 10 | self.input_data = input_data 11 | self.input_shape = input_data.shape[1] * input_data.shape[2] 12 | self.output_data = output_data 13 | self.output_shape = output_data.shape[1] 14 | 15 | assert len(input_data) == len(output_data) 16 | assert type(batch_size) is int 17 | if batch_size > len(input_data): 18 | print("WARNING: more examples per batch than possible examples in all input_data") 19 | self.batch_size = len(input_data) 20 | else: 21 | self.batch_size = batch_size 22 | 23 | # initialize example indices list 24 | self.remaining_example_indices = list(range(len(input_data))) 25 | shuffle(self.remaining_example_indices) 26 | 27 | def next_batch(self): 28 | # Create a single batch 29 | batch_input_values = np.zeros([self.batch_size] + [self.input_shape]) 30 | batch_output_values = np.zeros([self.batch_size] + [self.output_shape]) 31 | for i_example in range(self.batch_size): 32 | if not self.remaining_example_indices: 33 | self.remaining_example_indices = list(range(len(self.input_data))) 34 | shuffle(self.remaining_example_indices) 35 | 36 | # Create training example at index 'pos' in input_data. 37 | pos = self.remaining_example_indices.pop(0) 38 | batch_input_values[i_example] = np.reshape(self.input_data[pos], [self.input_shape]) 39 | batch_output_values[i_example] = np.reshape(self.output_data[pos], [self.output_shape]) 40 | return batch_input_values, batch_output_values 41 | -------------------------------------------------------------------------------- /5_deep_learning/02_CNN/cnn_model.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | import numpy as np 3 | import os 4 | 5 | from tf_helpers import build_conv2d_layer 6 | from tf_helpers import build_fc_layer 7 | 8 | class CNNModel(): 9 | 10 | def __init__(self): 11 | 12 | # Dataset specific parameters. 13 | self.img_width = 32 14 | self.img_height = 32 15 | self.n_channels = 1 16 | self.n_classes = 2 17 | 18 | # Parameters for fully connected layers. 19 | self.fc_size1 = 256 20 | self.fc_size2 = 128 21 | 22 | # Create a TensorFlow session and initialize variables. 23 | tf.reset_default_graph() 24 | self.sess = tf.Session() 25 | 26 | # Create a TensorFlow place holder for the input variables. 27 | self.x = tf.placeholder(tf.float32, shape=[None, self.img_width * self.img_height], name='x') 28 | 29 | # Create a TensorFlow place holder for the output variables encoded in one hot format. 30 | self.y_true = tf.placeholder(tf.float32, shape=[None, self.n_classes], name='y_true') 31 | 32 | # Add a tensor which calculates the true class using argmax. 33 | self.y_true_cls = tf.argmax(self.y_true, dimension=1) 34 | 35 | # Reshape the input in a format expected by the convolutional layers. 36 | # -1 signifies that the first dimension will automatically be adjusted to the number of images, i.e. the batch size. 37 | self.x_image = tf.reshape(self.x, [-1, self.img_width, self.img_height, self.n_channels]) 38 | 39 | # TODO Build the convolutional layers taking self.x_image as input. 40 | 41 | # Flatten the output of the final convolutional layer. 42 | # TODO Use the tf.contrib.layers.flatten() function in order to flatten the output of the convolutional part. 43 | 44 | # First fully connected layer. 45 | # TODO Adapt using the flattened output. 46 | self.first_fc_layer = build_fc_layer(self.x, self.fc_size1, '_fc1') 47 | self.first_fc_layer = tf.nn.relu(self.first_fc_layer) 48 | 49 | # Second fully connected layer. 50 | self.second_fc_layer = build_fc_layer(self.first_fc_layer, self.fc_size2, '_fc2') 51 | self.second_fc_layer = tf.nn.relu(self.second_fc_layer) 52 | 53 | # Output layer. 54 | self.output_layer = build_fc_layer(self.second_fc_layer, self.n_classes, '_output') 55 | 56 | # Prediction layer. 57 | self.y_pred = tf.nn.softmax(self.output_layer) 58 | self.y_pred = tf.argmax(self.y_pred, dimension=1) 59 | 60 | # Create a cost function based on cross entropy. 61 | # Note that the function calculates the softmax internally so we must use the output of `layer_fc2` 62 | # directly rather than `y_pred` which has already had the softmax applied. 63 | self.cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=self.output_layer, 64 | labels=self.y_true)) 65 | 66 | self.reg_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES) 67 | self.cost = tf.add(self.cost, tf.add_n(self.reg_losses)) 68 | 69 | # Create an optimizer. 70 | self.optimizer = tf.train.AdamOptimizer(learning_rate=1e-4).minimize(self.cost) 71 | 72 | # Create a tensor for computing the accuracy of a network. 73 | self.accuracy = tf.reduce_mean(tf.cast(tf.equal(self.y_pred, self.y_true_cls), tf.float32)) 74 | 75 | # Initialize the model's variables. 76 | self.sess.run(tf.global_variables_initializer()) 77 | 78 | # Create an object for saving and loading a model. 79 | self.saver = tf.train.Saver() 80 | 81 | def make_dictionary(self, input_data, output_data): 82 | input_values = np.zeros([len(input_data)] + [self.img_width * self.img_height]) 83 | output_values = np.zeros([len(output_data)] + [self.n_classes]) 84 | i = 0 85 | for input_sample, output_sample in zip(input_data, output_data): 86 | input_values[i] = np.reshape(input_sample, [self.img_width * self.img_height]) 87 | output_values[i] = np.reshape(output_sample, [self.n_classes]) 88 | i += 1 89 | return {self.x: input_values, self.y_true: output_values} 90 | 91 | def save(self, model_path): 92 | if not os.path.exists(model_path): 93 | os.makedirs(model_path) 94 | self.saver.save(self.sess, model_path + '/model-final.ckpt') 95 | 96 | def load(self, model_path): 97 | print('Loading session from "{}"'.format(model_path)) 98 | ckpt = tf.train.get_checkpoint_state(model_path) 99 | print('Restoring model {}'.format(ckpt.model_checkpoint_path)) 100 | self.saver.restore(self.sess, ckpt.model_checkpoint_path) -------------------------------------------------------------------------------- /5_deep_learning/02_CNN/test_cnn.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import numpy as np 3 | import time 4 | 5 | from datetime import timedelta 6 | 7 | from cnn_model import CNNModel 8 | from utilities import load_dataset 9 | 10 | parser = argparse.ArgumentParser() 11 | parser.add_argument("--use_evaluation_dataset", help="use evaluation dataset", 12 | action="store_true") 13 | args = parser.parse_args() 14 | 15 | if args.use_evaluation_dataset: 16 | test_dataset_path = "/tmp/deers_and_trucks_evaluation" 17 | else: 18 | test_dataset_path = "data/deers_and_trucks_test" 19 | 20 | # Load the dataset. 21 | images_test, cls_test = load_dataset(test_dataset_path) 22 | n_classes = 2 23 | cls_names = ["deers", "trucks"] 24 | 25 | # Encode the labels as one hot. 26 | cls_test_one_hot_encoded = np.eye(n_classes, dtype=float)[cls_test] 27 | 28 | # Create a convolutional neural network. 29 | model = CNNModel() 30 | 31 | # Load the saved model. 32 | model.load("model/") 33 | 34 | # Create a dictionary for evaluating the network on the full validation data. 35 | testing_dict = model.make_dictionary(images_test, cls_test_one_hot_encoded) 36 | 37 | # Evaluate and print the accuracy of the network. 38 | acc_full_test = model.sess.run(model.accuracy, feed_dict=testing_dict) 39 | msg = "Training Accuracy On Full Testing Data: {0:>6.1%}" 40 | print(msg.format(acc_full_test)) 41 | -------------------------------------------------------------------------------- /5_deep_learning/02_CNN/tf_helpers.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | # This file defines a few helper functions to build and optimize tensorflow graphs. 6 | import numpy as np 7 | import tensorflow as tf 8 | from IPython import embed 9 | 10 | def build_conv2d_layer(previous_layer, 11 | filter_size, 12 | n_filters, 13 | var_suffix, 14 | stride_length=1, 15 | regularizer_weight=0.001): 16 | 17 | # The number of channels is the last element of the shape. 18 | n_channels_previous_layer = previous_layer.get_shape()[-1] 19 | 20 | weights = tf.get_variable("weights"+var_suffix, 21 | [filter_size, filter_size, n_channels_previous_layer, n_filters], 22 | tf.float32, 23 | tf.contrib.layers.xavier_initializer(), 24 | tf.contrib.layers.l2_regularizer(regularizer_weight)) 25 | 26 | biases = tf.get_variable("biases"+var_suffix, 27 | n_filters, 28 | tf.float32, 29 | tf.constant_initializer(0)) 30 | 31 | conv_layer = tf.nn.conv2d(previous_layer, weights, [1, stride_length, stride_length, 1], 'SAME') 32 | 33 | conv_layer = tf.nn.bias_add(conv_layer, biases) 34 | 35 | return conv_layer 36 | 37 | def build_fc_layer(previous_layer, 38 | n_neurons, 39 | var_suffix, 40 | regularizer_weight=0.001): 41 | 42 | # The size is the last element of the shape. 43 | previous_layer_size = previous_layer.get_shape()[-1] 44 | 45 | weights = tf.get_variable("weights"+var_suffix, 46 | [previous_layer_size, n_neurons], 47 | tf.float32, 48 | tf.contrib.layers.xavier_initializer(), 49 | tf.contrib.layers.l2_regularizer(regularizer_weight)) 50 | 51 | biases = tf.get_variable("biases"+var_suffix, 52 | n_neurons, 53 | tf.float32, 54 | tf.constant_initializer(0)) 55 | 56 | return tf.matmul(previous_layer, weights) + biases -------------------------------------------------------------------------------- /5_deep_learning/02_CNN/train_cnn.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 4 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 5 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 6 | 7 | # A good introduction to TensorFlow layers and CNN can be found here: https://www.tensorflow.org/tutorials/layers 8 | # This exercise has been inspired by Magnus Erik Hvass Pedersen's tutorial on CNN: https://github.com/Hvass-Labs/TensorFlow-Tutorials/blob/master/02_Convolutional_Neural_Network.ipynb 9 | 10 | import argparse 11 | import numpy as np 12 | import time 13 | 14 | from datetime import timedelta 15 | 16 | from batchmaker import Batchmaker 17 | from cnn_model import CNNModel 18 | from utilities import load_dataset, plot_images 19 | 20 | DATASET_PATH = "data/deers_and_trucks" 21 | 22 | # Load the dataset. 23 | images_train, cls_train = load_dataset(DATASET_PATH) 24 | n_classes = 2 25 | cls_names = ["deers", "trucks"] 26 | 27 | # Plot a few samples if not disabled. 28 | parser = argparse.ArgumentParser() 29 | parser.add_argument("--disable_visualization", help="disable image visualization", 30 | action="store_true") 31 | args = parser.parse_args() 32 | if not(args.disable_visualization): 33 | plot_images(images_train[0:9], np.asarray(cls_names)[cls_train[0:9]]) 34 | 35 | # Encode the labels as one hot. 36 | cls_train_one_hot_encoded = np.eye(n_classes, dtype=float)[cls_train] 37 | 38 | # Create a convolutional neural network. 39 | model = CNNModel() 40 | 41 | # Create an object responsible of generating random batches. 42 | train_batch_size = 64 43 | batchmaker = Batchmaker(images_train, cls_train_one_hot_encoded, train_batch_size) 44 | 45 | # Create a dictionary for evaluating the network on the full training data. 46 | training_dict = model.make_dictionary(images_train, cls_train_one_hot_encoded) 47 | 48 | # Function for running the optimizer on random training batches. 49 | def optimize(num_iterations): 50 | start_time = time.time() 51 | 52 | for i in range(num_iterations): 53 | # Get a batch of training examples and feed it to the network for optimization. 54 | x_batch, y_true_batch = batchmaker.next_batch() 55 | feed_dict_train = {model.x: x_batch, 56 | model.y_true: y_true_batch} 57 | model.sess.run(model.optimizer, feed_dict=feed_dict_train) 58 | 59 | # Print status every x iterations. 60 | if i % 5 == 0: 61 | # Calculate and print accuracies. 62 | acc = model.sess.run(model.accuracy, feed_dict=feed_dict_train) 63 | acc_full_train = model.sess.run(model.accuracy, feed_dict=training_dict) 64 | 65 | msg = "Optimization Iteration: {0:>6}, Training Accuracy On Batch: {1:>6.1%}, Training Accuracy On Full Training Data: {2:>6.1%}." 66 | print(msg.format(i + 1, acc, acc_full_train)) 67 | 68 | end_time = time.time() 69 | time_dif = end_time - start_time 70 | print("Time usage: " + str(timedelta(seconds=int(round(time_dif))))) 71 | 72 | optimize(num_iterations=100) 73 | 74 | model.save("model/") 75 | -------------------------------------------------------------------------------- /5_deep_learning/02_CNN/utilities.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import pickle 3 | 4 | def load_dataset(path): 5 | with open(path, "rb") as input_file: 6 | data = pickle.load(input_file) 7 | print("Loaded dataset with " + str(data['images'].shape[0]) + " samples.") 8 | return data['images'], data['cls'] 9 | 10 | def plot_images(images, cls_names): 11 | 12 | assert len(images) == len(cls_names) == 9 13 | 14 | # Create figure with sub-plots. 15 | fig, axes = plt.subplots(3, 3) 16 | fig.subplots_adjust(hspace=0.3, wspace=0.3) 17 | 18 | for i, ax in enumerate(axes.flat): 19 | # Plot image. 20 | ax.imshow(images[i], cmap = plt.get_cmap('gray'), 21 | interpolation='spline16') 22 | 23 | # Name of the true class. 24 | xlabel = cls_names[i] 25 | 26 | # Show the classes as the label on the x-axis. 27 | ax.set_xlabel(xlabel) 28 | 29 | # Remove ticks from the plot. 30 | ax.set_xticks([]) 31 | ax.set_yticks([]) 32 | 33 | # Ensure the plot is shown correctly with multiple plots 34 | # in a single Notebook cell. 35 | plt.show() -------------------------------------------------------------------------------- /5_deep_learning/03_Deep_RL/NNModel.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import tensorflow as tf 6 | import numpy as np 7 | 8 | class NNModel(): 9 | """ 10 | NN model for reinforcement learning that maps from state to action probabilities 11 | """ 12 | 13 | def __init__(self, learning_rate=0.01): 14 | self.input_dim = 4 # physical state of the system [cart position, cart velocity, pole angle, pole rotational velocity] 15 | self.output_dim = 1 # action to be taken (left or right) 16 | self.hidden_layer_size = #TODO: list of hidden layer dimensions # numbers of hidden units for the 2 hidden layers 17 | 18 | #### NETWORK DEFINITION #### 19 | self.input = tf.placeholder(dtype=tf.float32, shape=[None, self.input_dim], name='observations') 20 | # Layer 1 21 | Wfc1 = tf.get_variable('Wfc1', shape=[self.input_dim, self.hidden_layer_size[0]], initializer=tf.contrib.layers.xavier_initializer()) 22 | relu1 = tf.nn.relu(tf.matmul(self.input, Wfc1), name='relu1') 23 | #Layer 2 24 | Wfc2 = tf.get_variable('Wfc2', shape=[self.hidden_layer_size[0], self.hidden_layer_size[1]], initializer=tf.contrib.layers.xavier_initializer()) 25 | relu2 = tf.nn.relu(tf.matmul(relu1, Wfc2), name='relu2') 26 | # Layer 3 27 | Wfc3 = tf.get_variable('Wfc3', shape=[self.hidden_layer_size[1], self.output_dim], initializer=tf.contrib.layers.xavier_initializer()) 28 | score = tf.matmul(relu2, Wfc3) 29 | 30 | # probability of taking action 1 (right) 31 | self.action_probability = tf.nn.sigmoid(score) 32 | 33 | #### LOSS FUNCTION #### 34 | self.negated_action = tf.placeholder(dtype=tf.float32, shape=[None, self.output_dim], name='action_taken') 35 | self.reward_signal = tf.placeholder(dtype=tf.float32, shape=[None, 1], name='reward_signal') 36 | 37 | # Loss function 38 | # likelihood of the chosen action given the probability output of the model 39 | # (negated_action stands for the action which was not taken) 40 | self.likelihood = # TODO: likelihood of taking the wrong action 41 | log_likelihood = tf.log(self.likelihood) 42 | # overall reward (whole episode) would be the likelihood * reward signal 43 | # -> the likelihood of choosing the action which gives high reward has to be maximized 44 | self.loss = -tf.reduce_mean(log_likelihood * self.reward_signal) 45 | # gradients = tf.gradients(loss, training_vars) 46 | 47 | 48 | #### NETWORK OPTIMIZATION #### 49 | optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate) 50 | # compute (gradient, variable) pairs 51 | self.gradient_variable_pairs = optimizer.compute_gradients(self.loss) 52 | self.Wfc1_grad = tf.placeholder(dtype=tf.float32, name='batch_grad1') 53 | self.Wfc2_grad = tf.placeholder(dtype=tf.float32, name='batch_grad2') 54 | self.Wfc3_grad = tf.placeholder(dtype=tf.float32, name='batch_grad3') 55 | batch_grad = [self.Wfc1_grad, self.Wfc2_grad, self.Wfc3_grad] 56 | self.training_vars = tf.trainable_variables() 57 | batch_gradient_variable_pairs = zip(batch_grad, self.training_vars) 58 | self.update_grads = optimizer.apply_gradients(batch_gradient_variable_pairs) 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /5_deep_learning/03_Deep_RL/Support.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import numpy as np 6 | 7 | 8 | def discountedReward(reward_array, gamma): 9 | """ 10 | Compute discounted reward over time series. 11 | Each timestep will give a reward of 1. 12 | This function leaves the final reward (1) unchanged but increases the shorter term reward. 13 | """ 14 | discounted_reward = np.zeros([len(reward_array), 1]) 15 | running_reward = 0 16 | for i in reversed(range(0, len(reward_array))): 17 | running_reward = running_reward * gamma + reward_array[i] 18 | discounted_reward[i] = running_reward 19 | return discounted_reward 20 | -------------------------------------------------------------------------------- /5_deep_learning/ex_5_0_dl.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethz-asl/ai_for_robotics/03bb66bae99bac3acd79bc1ec6d3b9c0eeabcdf8/5_deep_learning/ex_5_0_dl.pdf -------------------------------------------------------------------------------- /5_deep_learning/solution/01_DL_framework/ActivationFunction.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import numpy as np 6 | from abc import ABCMeta, abstractmethod 7 | 8 | 9 | class ActivationFunction(): 10 | """Activation function base class.""" 11 | __metaClass__ = ABCMeta 12 | 13 | @abstractmethod 14 | def evaluate(self, input): 15 | pass 16 | 17 | @abstractmethod 18 | def derivative(self, input): 19 | pass 20 | 21 | 22 | class SigmoidActivation(ActivationFunction): 23 | """Sigmoid activation function. Sigmoid works elementwise on an array.""" 24 | 25 | def evaluate(self, input): 26 | return 1 / (1 + np.exp(-input)) 27 | 28 | def derivative(self, input): 29 | return np.multiply( 30 | self.evaluate(input), 31 | (1 - self.evaluate(input))) # dotwise multiplication 32 | 33 | 34 | class UnitActivation(ActivationFunction): 35 | """ 36 | A unit activation function. 37 | 38 | This evaluates to the input and its derivative is one. 39 | """ 40 | 41 | def evaluate(self, input): 42 | return input 43 | 44 | def derivative(self, input): 45 | return np.ones(input.shape) 46 | -------------------------------------------------------------------------------- /5_deep_learning/solution/01_DL_framework/FCLayer.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import numpy as np 6 | 7 | 8 | class FCLayer(): 9 | """A fully connected layer.""" 10 | 11 | activation_function = None 12 | W = None 13 | b = None 14 | layer_number = None 15 | 16 | def __init__(self, layer_number, activation_function, input_size, 17 | output_size): 18 | self.layer_number = layer_number 19 | self.activation_function = activation_function 20 | self.W = np.random.randn(input_size, output_size) 21 | self.b = np.random.randn(1, output_size) 22 | 23 | def affinePart(self, x): 24 | """ 25 | Get the affine part of the layer, excluding the activation function. 26 | """ 27 | return np.dot(x, self.W) + self.b 28 | 29 | def output(self, x): 30 | """Layer output. Activation function applied to affine part.""" 31 | return self.activation_function.evaluate(self.affinePart(x)) 32 | 33 | def derivativeActivation(self, x): 34 | """ 35 | Derivative of the activation function of this layer. 36 | 37 | Will be required by the chain rule. 38 | """ 39 | return self.activation_function.derivative(self.affinePart(x)) 40 | 41 | def inputDimension(self): 42 | return self.W.shape[0] 43 | 44 | def outputDimension(self): 45 | return self.W.shape[1] 46 | 47 | # Getters and setters 48 | def setWeights(self, W): 49 | assert self.W.shape == W.shape, 'Weight shapes are inconsistent.' 50 | self.W = W 51 | 52 | def getWeights(self): 53 | return self.W 54 | 55 | def setBiases(self, b): 56 | assert self.b.shape == b.shape, 'Bias shapes are inconsistent.' 57 | self.b = b 58 | 59 | def getBiases(self): 60 | return self.b 61 | 62 | def __len__(self): 63 | return self.outputDimension() 64 | -------------------------------------------------------------------------------- /5_deep_learning/solution/01_DL_framework/GradientDescentOptimizer.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import Support as sup 6 | import numpy as np 7 | 8 | 9 | class GradientDescentOptimizer(): 10 | """Gradient descent optimization for neural network parameters.""" 11 | learning_rate = 0 12 | 13 | def __init__(self, learning_rate=0.01): 14 | self.learning_rate = learning_rate 15 | 16 | def getUpdatedParameters(self, nn, gradients): 17 | """Update parameters of the network and return them.""" 18 | p = nn.getParameters() 19 | new_p = p - gradients * self.learning_rate 20 | return new_p 21 | 22 | def computeBatchGradient(self, gradient_list): 23 | """Compute the gradient for a whole data batch from a provided gradient list. 24 | 25 | Input: 26 | Gradient list contains the gradient for each sample in the data batch. The structure is a list of variables (provided data structure support.Variable()). 27 | The weights and biases members both contain the gradients of all the layers for one data sample. 28 | Return value: 29 | One fused gradient including all data sample gradients. 30 | """ 31 | batch_gradient = gradient_list[0] 32 | for g in gradient_list[1:]: 33 | batch_gradient = batch_gradient + g 34 | return batch_gradient 35 | 36 | def updateStep(self, nn, loss_function, x_batch, y_target_batch): 37 | """ 38 | Update the NN model parameters given the loss function and a data 39 | batch. 40 | """ 41 | gradients = [] 42 | avg_batch_loss = 0 43 | batch_size = x_batch.shape[0] 44 | 45 | for i in range(x_batch.shape[0]): 46 | x = np.array([x_batch[i, :]]) 47 | y_target = np.array([y_target_batch[i, :]]) 48 | y = nn.output(x) 49 | avg_batch_loss += loss_function.evaluate(y, y_target) 50 | nn_gradient = nn.gradients(x, loss_function, y_target) 51 | gradients.append(nn_gradient) 52 | 53 | batch_gradient = self.computeBatchGradient(gradients) 54 | new_p = self.getUpdatedParameters(nn, batch_gradient) 55 | nn.setParameters(new_p) 56 | return avg_batch_loss / batch_size 57 | -------------------------------------------------------------------------------- /5_deep_learning/solution/01_DL_framework/LossFunction.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import numpy as np 6 | from abc import ABCMeta, abstractmethod 7 | 8 | 9 | class LossFunction(): 10 | """Loss function base class.""" 11 | __metaClass__ = ABCMeta 12 | 13 | @abstractmethod 14 | def evaluate(self, y, y_target): 15 | pass 16 | 17 | @abstractmethod 18 | def derivative(self, y, y_target): 19 | pass 20 | 21 | 22 | class SquaredErrorFunction(LossFunction): 23 | """Squared error loss function.""" 24 | 25 | def evaluate(self, y, y_target): 26 | return 0.5 * np.sum(np.dot((y_target - y), (y_target - y).T)) 27 | 28 | def derivative(self, y, y_target): 29 | return -(y_target - y) 30 | -------------------------------------------------------------------------------- /5_deep_learning/solution/01_DL_framework/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dube, ASL, ETH Zurich, Switzerland 4 | 5 | .PHONY: generate_data, train, eval, run_tests, clean, clean_models, clean_data, distclean 6 | 7 | generate_data: 8 | python generate_data.py 9 | 10 | train: 11 | python train_classification.py --plot --verbosity info 12 | 13 | eval: 14 | python test_classification.py --plot 15 | 16 | run_tests: 17 | python unit_tests.py 18 | 19 | clean: 20 | rm -rf *.pyc && rm -rf *~ 21 | 22 | clean_models: 23 | rm -rf models 24 | 25 | clean_data: 26 | rm -rf data 27 | 28 | distclean: 29 | $(MAKE) clean 30 | $(MAKE) clean_models 31 | $(MAKE) clean_data 32 | -------------------------------------------------------------------------------- /5_deep_learning/solution/01_DL_framework/ModelWrapper.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import numpy as np 6 | import FCLayer as fc_layer 7 | import pickle as pkl 8 | import os 9 | 10 | 11 | class Params(): 12 | 13 | training_batch_size = 10 14 | max_training_steps = 1000 15 | print_steps = 100 16 | 17 | 18 | class ModelWrapper(): 19 | 20 | network = None 21 | optimizer = None 22 | loss_function = None 23 | x = None 24 | y_target = None 25 | params = None 26 | current_idx = 0 27 | 28 | def __init__(self, network, loss_function, optimizer, x, y_target, params): 29 | self.params = params 30 | self.network = network 31 | self.optimizer = optimizer 32 | self.loss_function = loss_function 33 | # Training data 34 | self.x = x 35 | self.y_target = y_target 36 | 37 | def setNetwork(self, network): 38 | self.network = network 39 | 40 | def getNetwork(self): 41 | return self.network 42 | 43 | def setOptimizer(self, optimizer): 44 | self.optimizer = optimizer 45 | 46 | def getOptimizer(self): 47 | return self.optimizer 48 | 49 | def getNextDataPoint(self): 50 | if self.current_idx >= self.x.shape[0]: 51 | self.current_idx = 0 52 | input_batch = np.array([self.x[self.current_idx, :]]) 53 | label_batch = np.array([self.y_target[self.current_idx, :]]) 54 | self.current_idx += 1 55 | return input_batch, label_batch 56 | 57 | def getNextTrainingBatch(self, batch_size=1): 58 | input_batch = np.zeros([batch_size, self.x.shape[1]]) 59 | label_batch = np.zeros([batch_size, self.y_target.shape[1]]) 60 | for i in range(batch_size): 61 | X, y_target = self.getNextDataPoint() 62 | input_batch[i, :] = X 63 | label_batch[i, :] = y_target 64 | return input_batch, label_batch 65 | 66 | def prediction(self, x): 67 | y_net = self.network.output(x) 68 | y = np.zeros(y_net.shape) 69 | y[0, np.argmax(y_net)] = 1 70 | return y 71 | 72 | def train(self): 73 | step = 0 74 | loss_evolution = np.zeros([self.params.max_training_steps, 2]) 75 | while step < self.params.max_training_steps: 76 | x_batch, y_target_batch = self.getNextTrainingBatch( 77 | self.params.training_batch_size) 78 | loss = self.optimizer.updateStep(self.network, self.loss_function, 79 | x_batch, y_target_batch) 80 | loss_evolution[step, :] = np.array([step, loss]) 81 | if step % self.params.print_steps == 0: 82 | print("Loss in step {} is {}.".format(step, loss)) 83 | step += 1 84 | 85 | return loss_evolution 86 | 87 | def eval(self, x, y_target): 88 | eval_size = x.shape[0] 89 | correct_classifications = 0 90 | for i in range(eval_size): 91 | prediction = self.prediction(np.array([x[i, :]])) 92 | truth = np.array([y_target[i, :]]) 93 | if np.all(prediction == truth): 94 | correct_classifications += 1.0 95 | return correct_classifications / float(eval_size) 96 | 97 | def loss(self, x, y_target): 98 | return self.loss_function.evaluate(self.prediction(x), y_target) 99 | 100 | def gradients(self, x, y_target): 101 | return self.network.gradients(x, self.loss_function, y_target) 102 | -------------------------------------------------------------------------------- /5_deep_learning/solution/01_DL_framework/README.md: -------------------------------------------------------------------------------- 1 | # Usage instructions 2 | When you just checked out the repo you first need to generate the data by typing `make generate_data`. 3 | Afterwards, the network can be trained with `make train` and evaluated with `make eval`. 4 | The unit tests can be run by typing `make run_tests`. 5 | -------------------------------------------------------------------------------- /5_deep_learning/solution/01_DL_framework/Support.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import numpy as np 6 | 7 | 8 | class Variables(): 9 | """ 10 | Variable structure for networks variables / parameters and their 11 | gradients 12 | """ 13 | weights = [] 14 | biases = [] 15 | 16 | def __init__(self): 17 | self.weights = [] 18 | self.biases = [] 19 | 20 | def __len__(self): 21 | if len(self.weights) == len(self.biases): 22 | return len(self.weights) 23 | else: 24 | print("Dimension mismatch.") 25 | raise 26 | 27 | def __mul__(self, factor): 28 | new_p = Variables() 29 | for w, b in zip(self.weights, self.biases): 30 | new_p.weights.append(w * factor) 31 | new_p.biases.append(b * factor) 32 | return new_p 33 | 34 | def __add__(self, other_variables): 35 | assert len(self.weights) == len( 36 | other_variables.weights), 'Number of weight entries have to match.' 37 | assert len(self.biases) == len( 38 | other_variables.biases), 'Number of bias entries have to match.' 39 | 40 | new_p = Variables() 41 | for w, b, o_w, o_b in zip(self.weights, self.biases, 42 | other_variables.weights, 43 | other_variables.biases): 44 | new_p.weights.append(w + o_w) 45 | new_p.biases.append(b + o_b) 46 | return new_p 47 | 48 | def __sub__(self, other_variables): 49 | return self.__add__(other_variables * (-1)) 50 | 51 | def __eq__(self, other_variables): 52 | assert len(self.weights) == len( 53 | other_variables.weights), 'Number of weight entries have to match.' 54 | assert len(self.biases) == len( 55 | other_variables.biases), 'Number of bias entries have to match.' 56 | 57 | variables_equal = True 58 | 59 | for i in range(len(self.weights)): 60 | if not np.all(self.weights[i] == other_variables.weights[i]): 61 | variables_equal = False 62 | break 63 | if not np.all(self.biases[i] == other_variables.biases[i]): 64 | variables_equal = False 65 | break 66 | 67 | return variables_equal 68 | 69 | def __ne__(self, other_variables): 70 | return not self.__eq__(other_variables) 71 | 72 | 73 | # Methods 74 | def computeScore(network, x, labels): 75 | n_samples = x.shape[0] 76 | correct_classifications = 0.0 77 | for i in range(n_samples): 78 | if np.argmax(network.output(x[i, :])) == np.argmax(labels[i, :]): 79 | correct_classifications += 1.0 80 | 81 | return correct_classifications / float(n_samples) 82 | -------------------------------------------------------------------------------- /5_deep_learning/solution/01_DL_framework/generate_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 4 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 5 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 6 | 7 | from sklearn import datasets 8 | import numpy as np 9 | import pickle as pkl 10 | import os 11 | 12 | np.random.seed(100) 13 | 14 | n_classes = 6 15 | n_features = 2 16 | n_samples = 10000 17 | ratio_train = 0.8 18 | X, labels = datasets.make_blobs( 19 | centers=n_classes, 20 | n_features=n_features, 21 | n_samples=n_samples, 22 | center_box=(-2, 2), 23 | cluster_std=0.3, 24 | shuffle=True) 25 | labels_onehot = np.eye(n_classes, dtype=float)[labels] 26 | 27 | cutoff_idx = int(ratio_train * n_samples) 28 | data_train = (X[:cutoff_idx, :], labels_onehot[:cutoff_idx, :]) 29 | data_test = (X[cutoff_idx:, :], labels_onehot[cutoff_idx:, :]) 30 | 31 | directory = 'data' 32 | if not os.path.isdir(directory): 33 | os.mkdir(directory) 34 | 35 | pkl.dump(data_train, open(os.path.join(directory, 'data_train.pkl'), 'wb')) 36 | pkl.dump(data_test, open(os.path.join(directory, 'data_test.pkl'), 'wb')) 37 | 38 | print('Successfully generated data and saved to directory "{}".'.format( 39 | directory)) 40 | -------------------------------------------------------------------------------- /5_deep_learning/solution/01_DL_framework/models/trained.pkl: -------------------------------------------------------------------------------- 1 | (iFCNetwork 2 | FCNetwork 3 | p0 4 | (dp1 5 | S'layers' 6 | p2 7 | (lp3 8 | (iFCLayer 9 | FCLayer 10 | p4 11 | (dp5 12 | S'activation_function' 13 | p6 14 | (iActivationFunction 15 | SigmoidActivation 16 | p7 17 | (dp8 18 | bsS'b' 19 | p9 20 | cnumpy.core.multiarray 21 | _reconstruct 22 | p10 23 | (cnumpy 24 | ndarray 25 | p11 26 | (I0 27 | tp12 28 | g9 29 | tp13 30 | Rp14 31 | (I1 32 | (I1 33 | I5 34 | tp15 35 | cnumpy 36 | dtype 37 | p16 38 | (S'f8' 39 | p17 40 | I0 41 | I1 42 | tp18 43 | Rp19 44 | (I3 45 | S'<' 46 | p20 47 | NNNI-1 48 | I-1 49 | I0 50 | tp21 51 | bI00 52 | S'\xe7\x044\xfe\xc2\x17\xbe\xbf\x9cbY\xdf\xa1\x15\xd1\xbf\xa5\xd3\xa4g\xbf\xcb\xf0\xbf\x0f\xa80\xd3\x0eC\x0c@\xb9\x01\xf1\xf4\x0c\xb6\x00@' 53 | p22 54 | tp23 55 | bsS'layer_number' 56 | p24 57 | I0 58 | sS'W' 59 | p25 60 | g10 61 | (g11 62 | (I0 63 | tp26 64 | g9 65 | tp27 66 | Rp28 67 | (I1 68 | (I2 69 | I5 70 | tp29 71 | g19 72 | I00 73 | S'l\x95}\xf5h\xa5\xf9?p\x9c\x94\xc1\xab\xff\x13@\x04\xde\xf2\xd5x\xc4\x08\xc0\xa8\x96\xc0\x96xL\xa1?\x17{\xaf\xc3\xf59\x1d@\x0c\xfa\x90\x1a\xfas\x15\xc0\xc4\xa5\x97x\x1b\xa7\x0c@\x0c\xd8{"%\xa6\x07\xc0\xe0\xddD:[_\x10@\xe6\x16\xb3\xdd&\xd3\x03\xc0' 74 | p30 75 | tp31 76 | bsba(iFCLayer 77 | FCLayer 78 | p32 79 | (dp33 80 | g6 81 | (iActivationFunction 82 | SigmoidActivation 83 | p34 84 | (dp35 85 | bsg9 86 | g10 87 | (g11 88 | (I0 89 | tp36 90 | g9 91 | tp37 92 | Rp38 93 | (I1 94 | (I1 95 | I6 96 | tp39 97 | g19 98 | I00 99 | S'$\xd5\xfd\x11\xfb\x0b\x0f\xc0,\x106Y\x8e\x13\xec\xbfDH\xd6\xf0\xa3$\x03\xc0\xec\x89Bl\xdf\xaf\x05\xc0\xb8\xbd\xbe?\x05\x14\x01\xc0\xf0\xa2^A\xedY\x05\xc0' 100 | p40 101 | tp41 102 | bsg24 103 | I1 104 | sg25 105 | g10 106 | (g11 107 | (I0 108 | tp42 109 | g9 110 | tp43 111 | Rp44 112 | (I1 113 | (I5 114 | I6 115 | tp45 116 | g19 117 | I00 118 | S"88a\x83\xc3b\x00@\xb2\x07\x84\xa4\xc2h\x00\xc0\xca\x83Y\x83\xb2H\xfd?\x9b\\\xf4\xf0\xf7\x86\x19\xc0e\xccx\xa1zA\x13\xc0\x87\x94\xaaSN\x1a\x07@\x1b\x9c]8\x81\xa5\x1e\xc0\xdf\xaa?\xac\x99\x1d\x0b@\xc8\x93?\xb5\xd9\xb0\x02\xc0d& \x1cz\xe1\xe6\xbf\x8d\xeb\xbf\xb9R<\x16\xc0\x95\x1a\xb0\x13\xb9\x8f\x10@\x96\xbe\x1f]\xeb\xf4\xfe\xbfaOS(e\xa8\x11\xc0@m~\xfa\\\xa2\x11@\xc6\x05\x13Y\xa5\x95\x0b\xc0\x1b'\x18D*\x11\t@\xab\x9a\x87X\xb3\xd6\x11\xc0\xd9Q\x88\x08\xdaY\x05@\xe4\xd4\xfc\xa0\xf9R\xf8?+\x8bAK\x0b\n\x15\xc0f\x02\xdd\x1d\xb6\x84\xaa?BxX+\xf7\x10\x05@Kq\xda3[\x8d\x18\xc0\x1e\x1c\x01\xfd\xa4\x96\x17@\x00\x82\x1b3c\xa3\x1c\xc0\xf0V\xc3\x08k\x82\x14\xc0JR\x89\xf1]5\x19@\xa4\x01%\x1co=\x05\xc0\x82M\xda\xcf[\xca\xf7?" 119 | p46 120 | tp47 121 | bsbasS'hidden_layer_specs' 122 | p48 123 | (lp49 124 | (dp50 125 | S'dim' 126 | p51 127 | I5 128 | sS'activation' 129 | p52 130 | g7 131 | sasS'output_dim' 132 | p53 133 | I6 134 | sS'input_dim' 135 | p54 136 | I2 137 | sb. -------------------------------------------------------------------------------- /5_deep_learning/solution/01_DL_framework/test_classification.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 4 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 5 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 6 | 7 | import numpy as np 8 | import pylab as pl 9 | import pickle as pkl 10 | import argparse 11 | from sklearn import datasets, linear_model, preprocessing 12 | import Support as sup 13 | 14 | import FCNetwork as network 15 | 16 | 17 | def parse_args(): 18 | parser = argparse.ArgumentParser(description='Train a simple deep NN') 19 | parser.add_argument( 20 | '--plot', 21 | help='Activate plotting.', 22 | action='store_true', 23 | default=False) 24 | return parser.parse_args() 25 | 26 | 27 | args = parse_args() 28 | test_data = pkl.load(open('./data/data_test.pkl', 'rb')) 29 | 30 | fc_net = network.FCNetwork() 31 | fc_net.loadModel('./models/', 'trained.pkl') 32 | 33 | X_test = test_data[0] 34 | labels_test = test_data[1] 35 | 36 | # Compute scores on training and testing data 37 | score_test = sup.computeScore(fc_net, X_test, labels_test) 38 | print('The classification score on the test data is {}'.format(score_test)) 39 | 40 | # Visualization of classification results 41 | if args.plot: 42 | mesh_step_size = 0.05 43 | x1_min, x1_max = X_test[:, 0].min() - .5, X_test[:, 0].max() + .5 44 | x2_min, x2_max = X_test[:, 1].min() - .5, X_test[:, 1].max() + .5 45 | xx1, xx2 = np.meshgrid( 46 | np.arange(x1_min, x1_max, mesh_step_size), 47 | np.arange(x2_min, x2_max, mesh_step_size)) 48 | predicted_label = np.zeros(xx1.shape) 49 | 50 | for ii in range(xx1.shape[0]): 51 | for jj in range(xx1.shape[1]): 52 | x_query = np.array([[xx1[ii, jj], xx2[ii, jj]]]) 53 | y_net = fc_net.output(x_query) 54 | predicted_label[ii, jj] = np.argmax(y_net) 55 | 56 | pl.figure('Classification result') 57 | ax = pl.subplot(111) 58 | ax.pcolormesh(xx1, xx2, predicted_label, cmap=pl.cm.Spectral) 59 | # Plot training data 60 | ax.scatter( 61 | X_test[:, 0], 62 | X_test[:, 1], 63 | c=np.argmax(labels_test, 1), 64 | cmap=pl.cm.Spectral, 65 | s=40) 66 | ax.set_xlabel('x1') 67 | ax.set_ylabel('x2') 68 | 69 | pl.show(block=True) 70 | -------------------------------------------------------------------------------- /5_deep_learning/solution/01_DL_framework/train_classification.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 4 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 5 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 6 | 7 | import numpy as np 8 | import pylab as pl 9 | import pickle as pkl 10 | import argparse 11 | import os 12 | 13 | import ModelWrapper as model 14 | import GradientDescentOptimizer as optimizer 15 | import FCNetwork as network 16 | import LossFunction as loss 17 | import ActivationFunction as activation 18 | import Support as sup 19 | 20 | # Tabula rasa 21 | pl.close('all') 22 | 23 | 24 | def parse_args(): 25 | parser = argparse.ArgumentParser(description='Train a simple deep NN') 26 | parser.add_argument( 27 | '--verbosity', 28 | help= 29 | 'Specify verbosity of output. (Options: error, warn, info, debug).', 30 | type=str, 31 | default='info') 32 | parser.add_argument( 33 | '--plot', 34 | help='Activate plotting.', 35 | action='store_true', 36 | default=False) 37 | return parser.parse_args() 38 | 39 | 40 | args = parse_args() 41 | plotting_active = args.plot 42 | 43 | # Load data 44 | if os.path.exists('./data/data_train.pkl'): 45 | data_train = pkl.load(open('./data/data_train.pkl', 'rb')) 46 | else: 47 | raise Exception('Training data file does not exist.') 48 | X = data_train[0] 49 | labels_onehot = data_train[1] 50 | n_features = X.shape[1] 51 | n_classes = labels_onehot.shape[1] 52 | 53 | # Model setup 54 | # Parameters 55 | params = model.Params() 56 | params.training_batch_size = 32 57 | params.max_training_steps = 20000 58 | params.learning_rate = 0.01 59 | params.print_steps = 200 60 | 61 | # Network 62 | input_dim = n_features 63 | hidden_layer_specs = [] 64 | hidden_layer_specs.append({ 65 | 'activation': activation.SigmoidActivation(), 66 | 'dim': 5 67 | }) 68 | output_dim = n_classes 69 | fc_net = network.FCNetwork( 70 | input_dim, 71 | output_dim, 72 | hidden_layer_specs, 73 | output_activation=activation.SigmoidActivation(), 74 | loglevel=args.verbosity) 75 | loss_function = loss.SquaredErrorFunction() 76 | gdo = optimizer.GradientDescentOptimizer(learning_rate=params.learning_rate) 77 | 78 | nn_model = model.ModelWrapper( 79 | network=fc_net, 80 | optimizer=gdo, 81 | loss_function=loss_function, 82 | x=X, 83 | y_target=labels_onehot, 84 | params=params) 85 | 86 | # Run training 87 | loss = nn_model.train() 88 | nn_model.network.saveModel('./models', 'trained.pkl') 89 | 90 | score_train = sup.computeScore(fc_net, X, labels_onehot) 91 | print( 92 | 'The classification score on the training data is {}.'.format(score_train)) 93 | 94 | # Plotting training specs 95 | if plotting_active: 96 | pl.figure('Loss evolution') 97 | ax = pl.gca() 98 | ax.plot(loss[:, 0], loss[:, 1], c='b', label='training error') 99 | ax.set_ylim([-0.2, 1.2]) 100 | ax.set_xlabel('Training step') 101 | ax.set_ylabel('Training error') 102 | 103 | # Visualization of classification results 104 | mesh_step_size = 0.02 105 | x1_min, x1_max = X[:, 0].min() - .5, X[:, 0].max() + .5 106 | x2_min, x2_max = X[:, 1].min() - .5, X[:, 1].max() + .5 107 | xx1, xx2 = np.meshgrid( 108 | np.arange(x1_min, x1_max, mesh_step_size), 109 | np.arange(x2_min, x2_max, mesh_step_size)) 110 | predicted_label = np.zeros(xx1.shape) 111 | 112 | for ii in range(xx1.shape[0]): 113 | for jj in range(xx1.shape[1]): 114 | x_query = np.array([[xx1[ii, jj], xx2[ii, jj]]]) 115 | y_net = fc_net.output(x_query) 116 | predicted_label[ii, jj] = np.argmax(y_net) 117 | 118 | pl.figure('Classification result') 119 | ax = pl.subplot(111) 120 | ax.pcolormesh(xx1, xx2, predicted_label, cmap=pl.cm.Spectral) 121 | # Plot training data 122 | ax.scatter( 123 | X[:, 0], 124 | X[:, 1], 125 | c=np.argmax(labels_onehot, 1), 126 | cmap=pl.cm.Spectral, 127 | s=40) 128 | ax.set_xlabel('x1') 129 | ax.set_ylabel('x2') 130 | 131 | pl.show(block=True) 132 | -------------------------------------------------------------------------------- /5_deep_learning/solution/01_DL_framework/unit_tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 4 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 5 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 6 | 7 | import unittest 8 | import numpy as np 9 | 10 | import ActivationFunction as activation 11 | import GradientDescentOptimizer as gdo 12 | import FCLayer as layer 13 | import FCNetwork as network 14 | import LossFunction as loss 15 | import Support as sup 16 | 17 | # TODO: Update and extend tests 18 | 19 | # Global variables for test network in order to be accessible in all test cases. 20 | # Input 21 | x = np.random.randn(1, 3) 22 | 23 | # Layer 1 24 | w_1 = np.random.randn(3, 4) 25 | b_1 = np.random.randn(1, 4) 26 | 27 | # Layer 2 28 | w_out = np.random.randn(4, 2) 29 | b_out = np.random.randn(1, 2) 30 | 31 | # Output labels 32 | y_target = np.random.randn(1, 2) 33 | 34 | input_dim = x.shape[1] 35 | hidden_layer_specs = [] 36 | hidden_layer_specs.append({ 37 | 'activation': activation.SigmoidActivation(), 38 | 'dim': w_1.shape[1] 39 | }) 40 | output_dim = y_target.shape[1] 41 | 42 | fc_net = network.FCNetwork(input_dim, output_dim, hidden_layer_specs) 43 | 44 | fc_net.layers[0].setWeights(w_1) 45 | fc_net.layers[0].setBiases(b_1) 46 | 47 | fc_net.layers[1].setWeights(w_out) 48 | fc_net.layers[1].setBiases(b_out) 49 | 50 | 51 | class TestNetwork(unittest.TestCase): 52 | 53 | # Was tested above, can be used now 54 | sigmoid = activation.SigmoidActivation() 55 | 56 | def testGradients(self): 57 | 58 | # General computations 59 | loss_function = loss.SquaredErrorFunction() 60 | y = fc_net.output(x) 61 | loss_derivative = loss_function.derivative(y, y_target) 62 | 63 | # Manually compute gradients 64 | h_1 = fc_net.evaluateLayer(1, x) 65 | output_sigmoid = self.sigmoid.evaluate(np.dot(h_1, w_out) + b_out) 66 | output_sigmoid_derivative = output_sigmoid * (1 - output_sigmoid) 67 | 68 | ## Output layer 69 | delta_out = loss_derivative * output_sigmoid_derivative 70 | L_w_out = np.dot(h_1.T, delta_out) 71 | L_b_out = delta_out 72 | 73 | ## Hidden layer 74 | delta_1 = np.dot(delta_out, w_out.T) * self.sigmoid.derivative( 75 | np.dot(x, w_1) + b_1) 76 | L_w_1 = np.dot(x.T, delta_1) 77 | L_b_1 = delta_1 78 | 79 | # Network gradients 80 | gradients = fc_net.gradients(x, loss_function, y_target) 81 | ## Output layer 82 | nn_L_w_out = gradients.weights[1] 83 | nn_L_b_out = gradients.biases[1] 84 | 85 | ## Hidden layer 86 | nn_L_w_1 = gradients.weights[0] 87 | nn_L_b_1 = gradients.biases[0] 88 | 89 | # Output derivatives 90 | self.assertTrue( 91 | np.all(nn_L_w_out.shape == w_out.shape), 92 | 'Gradient shapes of output layer do not match.') 93 | self.assertTrue( 94 | np.all(nn_L_b_out.shape == b_out.shape), 95 | 'Gradient shapes of output layer do not match.') 96 | self.assertTrue(np.all(np.isclose(L_w_out, nn_L_w_out, rtol=1.e-8))) 97 | self.assertTrue(np.all(np.isclose(L_b_out, nn_L_b_out, rtol=1.e-8))) 98 | 99 | # Hidden layer derivatives 100 | self.assertTrue( 101 | np.all(nn_L_w_1.shape == w_1.shape), 102 | 'Gradient shapes of hidden layer do not match.') 103 | self.assertTrue( 104 | np.all(nn_L_b_1.shape == b_1.shape), 105 | 'Gradient shapes of hidden layer do not match.') 106 | self.assertTrue(np.all(np.isclose(L_w_1, nn_L_w_1, rtol=1.e-8))) 107 | self.assertTrue(np.all(np.isclose(L_b_1, nn_L_b_1, rtol=1.e-8))) 108 | 109 | 110 | if __name__ == '__main__': 111 | unittest.main() 112 | -------------------------------------------------------------------------------- /5_deep_learning/solution/02_CNN/batchmaker.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import numpy as np 6 | from random import shuffle 7 | 8 | 9 | class Batchmaker: 10 | def __init__(self, input_data, output_data, batch_size=64): 11 | self.input_data = input_data 12 | self.input_shape = input_data.shape[1] * input_data.shape[2] 13 | self.output_data = output_data 14 | self.output_shape = output_data.shape[1] 15 | 16 | assert len(input_data) == len(output_data) 17 | assert type(batch_size) is int 18 | if batch_size > len(input_data): 19 | print( 20 | "WARNING: more examples per batch than possible examples in all input_data" 21 | ) 22 | self.batch_size = len(input_data) 23 | else: 24 | self.batch_size = batch_size 25 | 26 | # initialize example indices list 27 | self.remaining_example_indices = list(range(len(input_data))) 28 | shuffle(self.remaining_example_indices) 29 | 30 | def next_batch(self): 31 | # Create a single batch 32 | batch_input_values = np.zeros([self.batch_size] + [self.input_shape]) 33 | batch_output_values = np.zeros([self.batch_size] + [self.output_shape]) 34 | for i_example in range(self.batch_size): 35 | if not self.remaining_example_indices: 36 | self.remaining_example_indices = list( 37 | range(len(self.input_data))) 38 | shuffle(self.remaining_example_indices) 39 | 40 | # Create training example at index 'pos' in input_data. 41 | pos = self.remaining_example_indices.pop(0) 42 | batch_input_values[i_example] = np.reshape(self.input_data[pos], 43 | [self.input_shape]) 44 | batch_output_values[i_example] = np.reshape( 45 | self.output_data[pos], [self.output_shape]) 46 | return batch_input_values, batch_output_values 47 | -------------------------------------------------------------------------------- /5_deep_learning/solution/02_CNN/test_cnn.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 4 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 5 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 6 | 7 | import argparse 8 | import numpy as np 9 | import time 10 | 11 | from datetime import timedelta 12 | 13 | from cnn_model import CNNModel 14 | from utilities import load_dataset 15 | 16 | parser = argparse.ArgumentParser() 17 | parser.add_argument( 18 | "--use_evaluation_dataset", 19 | help="use evaluation dataset", 20 | action="store_true") 21 | args = parser.parse_args() 22 | 23 | if args.use_evaluation_dataset: 24 | test_dataset_path = "/tmp/deers_and_trucks_evaluation" 25 | else: 26 | test_dataset_path = "data/deers_and_trucks_test" 27 | 28 | # Load the dataset. 29 | images_test, cls_test = load_dataset(test_dataset_path) 30 | n_classes = 2 31 | cls_names = ["deers", "trucks"] 32 | 33 | # Encode the labels as one hot. 34 | cls_test_one_hot_encoded = np.eye(n_classes, dtype=float)[cls_test] 35 | 36 | # Create a convolutional neural network. 37 | model = CNNModel() 38 | 39 | # Load the saved model. 40 | model.load("model/") 41 | 42 | # Create a dictionary for evaluating the network on the full validation data. 43 | testing_dict = model.make_dictionary(images_test, cls_test_one_hot_encoded) 44 | 45 | # Evaluate and print the accuracy of the network. 46 | acc_full_test = model.sess.run(model.accuracy, feed_dict=testing_dict) 47 | msg = "Training Accuracy On Full Testing Data: {0:>6.1%}" 48 | print(msg.format(acc_full_test)) 49 | -------------------------------------------------------------------------------- /5_deep_learning/solution/02_CNN/tf_helpers.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | # This file defines a few helper functions to build and optimize tensorflow graphs. 6 | import numpy as np 7 | import tensorflow as tf 8 | from IPython import embed 9 | 10 | 11 | def build_conv2d_layer(previous_layer, 12 | filter_size, 13 | n_filters, 14 | var_suffix, 15 | stride_length=1, 16 | regularizer_weight=0.001): 17 | 18 | # The number of channels is the last element of the shape. 19 | n_channels_previous_layer = previous_layer.get_shape()[-1] 20 | 21 | weights = tf.get_variable( 22 | "weights" + var_suffix, 23 | [filter_size, filter_size, n_channels_previous_layer, 24 | n_filters], tf.float32, 25 | tf.contrib.layers.xavier_initializer(), 26 | tf.contrib.layers.l2_regularizer(regularizer_weight)) 27 | 28 | biases = tf.get_variable("biases" + var_suffix, n_filters, tf.float32, 29 | tf.constant_initializer(0)) 30 | 31 | conv_layer = tf.nn.conv2d(previous_layer, weights, 32 | [1, stride_length, stride_length, 1], 'SAME') 33 | 34 | conv_layer = tf.nn.bias_add(conv_layer, biases) 35 | 36 | return conv_layer 37 | 38 | 39 | def build_fc_layer(previous_layer, 40 | n_neurons, 41 | var_suffix, 42 | regularizer_weight=0.001): 43 | 44 | # The size is the last element of the shape. 45 | previous_layer_size = previous_layer.get_shape()[-1] 46 | 47 | weights = tf.get_variable( 48 | "weights" + var_suffix, [previous_layer_size, n_neurons], tf.float32, 49 | tf.contrib.layers.xavier_initializer(), 50 | tf.contrib.layers.l2_regularizer(regularizer_weight)) 51 | 52 | biases = tf.get_variable("biases" + var_suffix, n_neurons, tf.float32, 53 | tf.constant_initializer(0)) 54 | 55 | return tf.matmul(previous_layer, weights) + biases 56 | -------------------------------------------------------------------------------- /5_deep_learning/solution/02_CNN/train_cnn.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 4 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 5 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 6 | 7 | # A good introduction to TensorFlow layers and CNN can be found here: https://www.tensorflow.org/tutorials/layers 8 | # This exercise has been inspired by Magnus Erik Hvass Pedersen's tutorial on CNN: https://github.com/Hvass-Labs/TensorFlow-Tutorials/blob/master/02_Convolutional_Neural_Network.ipynb 9 | import tensorflow as tf 10 | import argparse 11 | import numpy as np 12 | import time 13 | 14 | from datetime import timedelta 15 | 16 | from batchmaker import Batchmaker 17 | from cnn_model import CNNModel 18 | from utilities import load_dataset, plot_images 19 | 20 | DATASET_PATH = "data/deers_and_trucks" 21 | 22 | # Load the dataset. 23 | images_train, cls_train = load_dataset(DATASET_PATH) 24 | n_classes = 2 25 | cls_names = ["deers", "trucks"] 26 | 27 | # Plot a few samples if not disabled. 28 | parser = argparse.ArgumentParser() 29 | parser.add_argument( 30 | "--disable_visualization", 31 | help="disable image visualization", 32 | action="store_true") 33 | args = parser.parse_args() 34 | if not (args.disable_visualization): 35 | plot_images(images_train[0:9], np.asarray(cls_names)[cls_train[0:9]]) 36 | 37 | # Encode the labels as one hot. 38 | cls_train_one_hot_encoded = np.eye(n_classes, dtype=float)[cls_train] 39 | 40 | # Create a convolutional neural network. 41 | model = CNNModel() 42 | 43 | # Create an object responsible of generating random batches. 44 | train_batch_size = 64 45 | batchmaker = Batchmaker(images_train, cls_train_one_hot_encoded, 46 | train_batch_size) 47 | 48 | # Create a dictionary for evaluating the network on the full training data. 49 | training_dict = model.make_dictionary(images_train, cls_train_one_hot_encoded) 50 | 51 | 52 | # Function for running the optimizer on random training batches. 53 | def optimize(num_iterations): 54 | start_time = time.time() 55 | 56 | for i in range(num_iterations): 57 | # Get a batch of training examples and feed it to the network for optimization. 58 | x_batch, y_true_batch = batchmaker.next_batch() 59 | feed_dict_train = {model.x: x_batch, model.y_true: y_true_batch} 60 | model.sess.run(model.optimizer, feed_dict=feed_dict_train) 61 | 62 | # Print status every x iterations. 63 | if i % 5 == 0: 64 | # Calculate and print accuracies. 65 | acc = model.sess.run(model.accuracy, feed_dict=feed_dict_train) 66 | acc_full_train = model.sess.run( 67 | model.accuracy, feed_dict=training_dict) 68 | 69 | msg = "Optimization Iteration: {0:>6}, Training Accuracy On Batch: {1:>6.1%}, Training Accuracy On Full Training Data: {2:>6.1%}." 70 | print(msg.format(i + 1, acc, acc_full_train)) 71 | 72 | end_time = time.time() 73 | time_dif = end_time - start_time 74 | print("Time usage: " + str(timedelta(seconds=int(round(time_dif))))) 75 | 76 | 77 | optimize(num_iterations=100) 78 | 79 | model.save("model/") 80 | -------------------------------------------------------------------------------- /5_deep_learning/solution/02_CNN/utilities.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import matplotlib.pyplot as plt 6 | import pickle 7 | 8 | 9 | def load_dataset(path): 10 | with open(path, "rb") as input_file: 11 | data = pickle.load(input_file) 12 | print("Loaded dataset with " + str(data['images'].shape[0]) + " samples.") 13 | return data['images'], data['cls'] 14 | 15 | 16 | def plot_images(images, cls_names): 17 | 18 | assert len(images) == len(cls_names) == 9 19 | 20 | # Create figure with sub-plots. 21 | fig, axes = plt.subplots(3, 3) 22 | fig.subplots_adjust(hspace=0.3, wspace=0.3) 23 | 24 | for i, ax in enumerate(axes.flat): 25 | # Plot image. 26 | ax.imshow( 27 | images[i], cmap=plt.get_cmap('gray'), interpolation='spline16') 28 | 29 | # Name of the true class. 30 | xlabel = cls_names[i] 31 | 32 | # Show the classes as the label on the x-axis. 33 | ax.set_xlabel(xlabel) 34 | 35 | # Remove ticks from the plot. 36 | ax.set_xticks([]) 37 | ax.set_yticks([]) 38 | 39 | # Ensure the plot is shown correctly with multiple plots 40 | # in a single Notebook cell. 41 | plt.show() 42 | -------------------------------------------------------------------------------- /5_deep_learning/solution/03_Deep_RL/NNModel.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import tensorflow as tf 6 | import numpy as np 7 | 8 | 9 | class NNModel(): 10 | """NN model for reinforcement learning that maps from state to action 11 | probabilities.""" 12 | 13 | def __init__(self, learning_rate=0.01): 14 | self.input_dim = 4 # physical state of the system [cart position, cart velocity, pole angle, pole rotational velocity] 15 | self.output_dim = 1 # action to be taken (left or right) 16 | self.hidden_layer_size = [ 17 | 50, 20 18 | ] # numbers of hidden units for the 2 hidden layers 19 | 20 | #### NETWORK DEFINITION #### 21 | self.input = tf.placeholder( 22 | dtype=tf.float32, 23 | shape=[None, self.input_dim], 24 | name='observations') 25 | # Layer 1 26 | Wfc1 = tf.get_variable( 27 | 'Wfc1', 28 | shape=[self.input_dim, self.hidden_layer_size[0]], 29 | initializer=tf.contrib.layers.xavier_initializer()) 30 | relu1 = tf.nn.relu(tf.matmul(self.input, Wfc1), name='relu1') 31 | #Layer 2 32 | Wfc2 = tf.get_variable( 33 | 'Wfc2', 34 | shape=[self.hidden_layer_size[0], self.hidden_layer_size[1]], 35 | initializer=tf.contrib.layers.xavier_initializer()) 36 | relu2 = tf.nn.relu(tf.matmul(relu1, Wfc2), name='relu2') 37 | # Layer 3 38 | Wfc3 = tf.get_variable( 39 | 'Wfc3', 40 | shape=[self.hidden_layer_size[1], self.output_dim], 41 | initializer=tf.contrib.layers.xavier_initializer()) 42 | score = tf.matmul(relu2, Wfc3) 43 | 44 | # probability of taking action 1 (right) 45 | self.action_probability = tf.nn.sigmoid(score) 46 | 47 | #### LOSS FUNCTION #### 48 | self.negated_action = tf.placeholder( 49 | dtype=tf.float32, 50 | shape=[None, self.output_dim], 51 | name='action_taken') 52 | self.reward_signal = tf.placeholder( 53 | dtype=tf.float32, shape=[None, 1], name='reward_signal') 54 | 55 | # Loss function 56 | # likelihood of the chosen action given the probability output of the model 57 | # (negated_action stands for the action which was not taken) 58 | self.likelihood = self.negated_action * (self.negated_action - self.action_probability) + \ 59 | (1 - self.negated_action) * (self.negated_action + self.action_probability) 60 | log_likelihood = tf.log(self.likelihood) 61 | # overall reward (whole episode) would be the likelihood * reward signal 62 | # -> the likelihood of choosing the action which gives high reward has to be maximized 63 | self.loss = -tf.reduce_mean(log_likelihood * self.reward_signal) 64 | # gradients = tf.gradients(loss, training_vars) 65 | 66 | #### NETWORK OPTIMIZATION #### 67 | optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate) 68 | # compute (gradient, variable) pairs 69 | self.gradient_variable_pairs = optimizer.compute_gradients(self.loss) 70 | self.Wfc1_grad = tf.placeholder(dtype=tf.float32, name='batch_grad1') 71 | self.Wfc2_grad = tf.placeholder(dtype=tf.float32, name='batch_grad2') 72 | self.Wfc3_grad = tf.placeholder(dtype=tf.float32, name='batch_grad3') 73 | batch_grad = [self.Wfc1_grad, self.Wfc2_grad, self.Wfc3_grad] 74 | self.training_vars = tf.trainable_variables() 75 | batch_gradient_variable_pairs = zip(batch_grad, self.training_vars) 76 | self.update_grads = optimizer.apply_gradients( 77 | batch_gradient_variable_pairs) 78 | -------------------------------------------------------------------------------- /5_deep_learning/solution/03_Deep_RL/Support.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 2 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 3 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 4 | 5 | import numpy as np 6 | 7 | def discountedReward(reward_array, gamma): 8 | """ 9 | Compute discounted reward over time series. 10 | 11 | Each timestep will give a reward of 1. 12 | This function leaves the final reward (1) unchanged but increases the 13 | shorter term reward. 14 | """ 15 | discounted_reward = np.zeros([len(reward_array), 1]) 16 | running_reward = 0 17 | for i in reversed(range(0, len(reward_array))): 18 | running_reward = running_reward * gamma + reward_array[i] 19 | discounted_reward[i] = running_reward 20 | return discounted_reward 21 | -------------------------------------------------------------------------------- /5_deep_learning/solution/03_Deep_RL/model/checkpoint: -------------------------------------------------------------------------------- 1 | model_checkpoint_path: "model-final.ckpt" 2 | all_model_checkpoint_paths: "model-final.ckpt" 3 | -------------------------------------------------------------------------------- /5_deep_learning/solution/03_Deep_RL/model/model-final.ckpt.data-00000-of-00001: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethz-asl/ai_for_robotics/03bb66bae99bac3acd79bc1ec6d3b9c0eeabcdf8/5_deep_learning/solution/03_Deep_RL/model/model-final.ckpt.data-00000-of-00001 -------------------------------------------------------------------------------- /5_deep_learning/solution/03_Deep_RL/model/model-final.ckpt.index: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethz-asl/ai_for_robotics/03bb66bae99bac3acd79bc1ec6d3b9c0eeabcdf8/5_deep_learning/solution/03_Deep_RL/model/model-final.ckpt.index -------------------------------------------------------------------------------- /5_deep_learning/solution/03_Deep_RL/model/model-final.ckpt.meta: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethz-asl/ai_for_robotics/03bb66bae99bac3acd79bc1ec6d3b9c0eeabcdf8/5_deep_learning/solution/03_Deep_RL/model/model-final.ckpt.meta -------------------------------------------------------------------------------- /5_deep_learning/solution/03_Deep_RL/test_reinforcement_cart_pole.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright 2017 Mark Pfeiffer, ASL, ETH Zurich, Switzerland 4 | # Copyright 2017 Fadri Furrer, ASL, ETH Zurich, Switzerland 5 | # Copyright 2017 Renaud Dubé, ASL, ETH Zurich, Switzerland 6 | 7 | import tensorflow as tf 8 | import time 9 | import numpy as np 10 | import gym 11 | import pylab as pl 12 | import progressbar 13 | 14 | from NNModel import * 15 | 16 | # Set up the simulation environment 17 | env = gym.make('CartPole-v0') 18 | env.reset() 19 | env.render() 20 | env.close() 21 | 22 | # Params 23 | num_test_runs = 100 24 | max_num_steps_per_episode = 5000 25 | num_steps_per_episode = [] 26 | do_visualize = False 27 | 28 | # Reset TF 29 | tf.reset_default_graph() 30 | 31 | # Model definition 32 | model = NNModel() 33 | saver = tf.train.Saver() 34 | checkpoint_path = 'model' 35 | 36 | p_bar = progressbar.ProgressBar( 37 | widgets=[progressbar.Percentage(), 38 | progressbar.Bar()], 39 | maxval=num_test_runs).start() 40 | with tf.Session() as sess: 41 | # Restore model 42 | print('Loading session from "{}"'.format(checkpoint_path)) 43 | ckpt = tf.train.get_checkpoint_state(checkpoint_path) 44 | print('Restoring model {}'.format(ckpt.model_checkpoint_path)) 45 | saver.restore(sess, ckpt.model_checkpoint_path) 46 | 47 | # Visualize once after optimization 48 | for i in range(num_test_runs): 49 | observation = env.reset() 50 | done = False 51 | reward_episode = 0 52 | while not done and reward_episode < max_num_steps_per_episode: 53 | # Compute action 54 | x = np.reshape(observation, [1, model.input_dim]) 55 | network_output = sess.run( 56 | model.action_probability, feed_dict={model.input: x}) 57 | # now don't take a stochastic but deterministic action 58 | action = 1 if network_output > 0.5 else 0 59 | # Simulate 60 | observation, reward, done, _ = env.step(action) 61 | reward_episode += reward 62 | if do_visualize: 63 | env.render() 64 | num_steps_per_episode.append(reward_episode) 65 | p_bar.update(i) 66 | 67 | p_bar.finish() 68 | env.close() 69 | 70 | print('### FINAL SCORE ###') 71 | print('Avg. steps per episode: {}'.format(np.mean(num_steps_per_episode))) 72 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, Autonomous Systems Lab, ETH Zurich. 2 | All rights reserved. 3 | 4 | Unlike otherwise stated in source files, the code in this repository is 5 | published under the Revised BSD (New BSD) license. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | * Neither the name of the nor the 15 | names of its contributors may be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 22 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Artificial Intelligence for Robotics 2 | 3 | A python cheat sheet containing the basics needed for this course can be found here: https://perso.limsi.fr/pointal/_media/python:cours:mementopython3-english.pdf 4 | 5 | The documentation of SciPy can be found here: http://scipy-cookbook.readthedocs.io/index.html 6 | 7 | ## Exercise overview 8 | 9 | * **0\_1\_python\_introduction\_exercise**: basic python examples 10 | * **0\_2\_python\_intro\_applications**: python applications (linear regression, optimization) 11 | * **1\_0\_probability\_ml\_basics**: Probability recap and machine learning basics 12 | * **2\_0\_regression\_pgm**: Regression and probabilistic graphical models 13 | * **3\_0\_pgo\_icp**: Pose graph optimization and iterative closest point 14 | * **4\_0\_pca\_kmeans\_svm**: Principal Component Analysis (PCA), k-means clustering, Support Vector Machine (SVM). 15 | * **5\_deep\_learning**: Backpropagation, Convolutional Neural Networks (CNNs), Deep Reinforcement Learning (RL). 16 | --------------------------------------------------------------------------------