From b2178e275de57337a8394667ec0c340ec387accc Mon Sep 17 00:00:00 2001 From: Morvan Zhou Date: Sat, 6 May 2017 01:12:39 +1000 Subject: [PATCH] move files --- README.md | 90 +++++++++ logo.png | Bin 0 -> 4045 bytes tutorial-contents/201_torch_numpy.py | 63 +++++++ tutorial-contents/202_variable.py | 57 ++++++ tutorial-contents/203_activation.py | 49 +++++ tutorial-contents/301_regression.py | 64 +++++++ tutorial-contents/302_classification.py | 72 ++++++++ tutorial-contents/303_build_nn_quickly.py | 35 ++++ tutorial-contents/304_save_reload.py | 88 +++++++++ tutorial-contents/305_batch_train.py | 31 ++++ tutorial-contents/306_optimizer.py | 85 +++++++++ tutorial-contents/401_CNN.py | 109 +++++++++++ tutorial-contents/402_RNN_classifier.py | 108 +++++++++++ tutorial-contents/403_RNN_regressor.py | 96 ++++++++++ tutorial-contents/404_autoencoder.py | 142 ++++++++++++++ .../405_DQN_Reinforcement_learning.py | 129 +++++++++++++ .../501_why_torch_dynamic_graph.py | 106 +++++++++++ tutorial-contents/502_GPU.py | 84 +++++++++ tutorial-contents/503_dropout.py | 100 ++++++++++ tutorial-contents/504_batch_normalization.py | 173 ++++++++++++++++++ tutorial-contents/mnist/processed/test.pt | Bin 0 -> 7920408 bytes tutorial-contents/mnist/processed/training.pt | Bin 0 -> 47520408 bytes .../mnist/raw/t10k-images-idx3-ubyte | Bin 0 -> 7840016 bytes .../mnist/raw/t10k-labels-idx1-ubyte | Bin 0 -> 10008 bytes .../mnist/raw/train-images-idx3-ubyte | Bin 0 -> 47040016 bytes .../mnist/raw/train-labels-idx1-ubyte | Bin 0 -> 60008 bytes 26 files changed, 1681 insertions(+) create mode 100644 README.md create mode 100644 logo.png create mode 100644 tutorial-contents/201_torch_numpy.py create mode 100644 tutorial-contents/202_variable.py create mode 100644 tutorial-contents/203_activation.py create mode 100644 tutorial-contents/301_regression.py create mode 100644 tutorial-contents/302_classification.py create mode 100644 tutorial-contents/303_build_nn_quickly.py create mode 100644 tutorial-contents/304_save_reload.py create mode 100644 tutorial-contents/305_batch_train.py create mode 100644 tutorial-contents/306_optimizer.py create mode 100644 tutorial-contents/401_CNN.py create mode 100644 tutorial-contents/402_RNN_classifier.py create mode 100644 tutorial-contents/403_RNN_regressor.py create mode 100644 tutorial-contents/404_autoencoder.py create mode 100644 tutorial-contents/405_DQN_Reinforcement_learning.py create mode 100644 tutorial-contents/501_why_torch_dynamic_graph.py create mode 100644 tutorial-contents/502_GPU.py create mode 100644 tutorial-contents/503_dropout.py create mode 100644 tutorial-contents/504_batch_normalization.py create mode 100644 tutorial-contents/mnist/processed/test.pt create mode 100644 tutorial-contents/mnist/processed/training.pt create mode 100644 tutorial-contents/mnist/raw/t10k-images-idx3-ubyte create mode 100644 tutorial-contents/mnist/raw/t10k-labels-idx1-ubyte create mode 100644 tutorial-contents/mnist/raw/train-images-idx3-ubyte create mode 100644 tutorial-contents/mnist/raw/train-labels-idx1-ubyte diff --git a/README.md b/README.md new file mode 100644 index 0000000..62363e8 --- /dev/null +++ b/README.md @@ -0,0 +1,90 @@ +

+ + + +

+ +--- + +
+ +# pyTorch Tutorials + +In these tutorials for pyTorch, we will build our first Neural Network and try to build some advanced Neural Network architectures developed recent years. + +All methods mentioned below have their video and text tutorial in Chinese. Visit [莫烦 Python](https://morvanzhou.github.io/tutorials/) for more. +If you speak Chinese, you can watch my [Youtube channel](https://www.youtube.com/channel/UCdyjiB5H8Pu7aDTNVXTTpcg) as well. + + +* pyTorch basic + * [torch and numpy](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/201_torch_numpy.py) + * [Variable](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/202_variable.py) + * [Activation](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/203_activation.py) +* Build your first network + * [Regression](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/301_regression.py) + * [Classification](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/302_classification.py) + * [An easy way](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/303_build_nn_quickly.py) + * [Save and reload](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/304_save_reload.py) + * [Train on batch](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/305_batch_train.py) + * [Optimizers](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/306_optimizer.py) +* Advanced neural network + * [CNN](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/401_CNN.py) + * [RNN-Classification](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/402_RNN_classifier.py) + * [RNN-Regression](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/403_RNN_regressor.py) + * [AutoEncoder](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/404_autoencoder.py) + * [DQN Reinforcement Learning](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/405_DQN_Reinforcement_learning.py) +* Others (WIP) + * [Why torch dynamic](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/501_why_torch_dynamic_graph.py) + * [Train on GPU](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/502_GPU.py) + * [Dropout](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/503_dropout.py) + * [Batch Normalization](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/504_batch_normalization.py) + +### [Regression](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/301_regression.py) + + + + + +### [Classification](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/302_classification.py) + + + + + +### [RNN](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/403_RNN_regressor.py) + + + + + +### [Autoencoder](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/404_autoencoder.py) + + + + + + + + + +### [Dropout](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/503_dropout.py) + + + + +### [Batch Normalization](https://github.com/MorvanZhou/tutorials/blob/master/pytorchTUT/504_batch_normalization.py) + + + + +# Donation + +*If this does help you, please consider donating to support me for better tutorials. Any contribution is greatly appreciated!* + +
+ + Paypal +
diff --git a/logo.png b/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f68dc895f17645f66f9a5174b3823bf037364992 GIT binary patch literal 4045 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 literal 0 HcmV?d00001 diff --git a/tutorial-contents/201_torch_numpy.py b/tutorial-contents/201_torch_numpy.py new file mode 100644 index 0000000..4d9584b --- /dev/null +++ b/tutorial-contents/201_torch_numpy.py @@ -0,0 +1,63 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +numpy +""" +import torch +import numpy as np + +# details about math operation in torch can be found in: http://pytorch.org/docs/torch.html#math-operations + +# convert numpy to tensor or vise versa +np_data = np.arange(6).reshape((2, 3)) +torch_data = torch.from_numpy(np_data) +tensor2array = torch_data.numpy() +print( + '\nnumpy array:', np_data, # [[0 1 2], [3 4 5]] + '\ntorch tensor:', torch_data, # 0 1 2 \n 3 4 5 [torch.LongTensor of size 2x3] + '\ntensor to array:', tensor2array, # [[0 1 2], [3 4 5]] +) + + +# abs +data = [-1, -2, 1, 2] +tensor = torch.FloatTensor(data) # 32-bit floating point +print( + '\nabs', + '\nnumpy: ', np.abs(data), # [1 2 1 2] + '\ntorch: ', torch.abs(tensor) # [1 2 1 2] +) + +# sin +print( + '\nsin', + '\nnumpy: ', np.sin(data), # [-0.84147098 -0.90929743 0.84147098 0.90929743] + '\ntorch: ', torch.sin(tensor) # [-0.8415 -0.9093 0.8415 0.9093] +) + +# mean +print( + '\nmean', + '\nnumpy: ', np.mean(data), # 0.0 + '\ntorch: ', torch.mean(tensor) # 0.0 +) + +# matrix multiplication +data = [[1,2], [3,4]] +tensor = torch.FloatTensor(data) # 32-bit floating point +# correct method +print( + '\nmatrix multiplication (matmul)', + '\nnumpy: ', np.matmul(data, data), # [[7, 10], [15, 22]] + '\ntorch: ', torch.mm(tensor, tensor) # [[7, 10], [15, 22]] +) +# incorrect method +data = np.array(data) +print( + '\nmatrix multiplication (dot)', + '\nnumpy: ', data.dot(data), # [[7, 10], [15, 22]] + '\ntorch: ', tensor.dot(tensor) # this will convert tensor to [1,2,3,4], you'll get 30.0 +) \ No newline at end of file diff --git a/tutorial-contents/202_variable.py b/tutorial-contents/202_variable.py new file mode 100644 index 0000000..194c2f4 --- /dev/null +++ b/tutorial-contents/202_variable.py @@ -0,0 +1,57 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +""" +import torch +from torch.autograd import Variable + +# Variable in torch is to build a computational graph, +# but this graph is dynamic compared with a static graph in Tensorflow or Theano. +# So torch does not have placeholder, torch can just pass variable to the computational graph. + +tensor = torch.FloatTensor([[1,2],[3,4]]) # build a tensor +variable = Variable(tensor, requires_grad=True) # build a variable, usually for compute gradients + +print(tensor) # [torch.FloatTensor of size 2x2] +print(variable) # [torch.FloatTensor of size 2x2] + +# till now the tensor and variable seem the same. +# However, the variable is a part of the graph, it's a part of the auto-gradient. + +t_out = torch.mean(tensor*tensor) # x^2 +v_out = torch.mean(variable*variable) # x^2 +print(t_out) +print(v_out) # 7.5 + +v_out.backward() # backpropagation from v_out +# v_out = 1/4 * sum(variable*variable) +# the gradients w.r.t the variable, d(v_out)/d(variable) = 1/4*2*variable = variable/2 +print(variable.grad) +''' + 0.5000 1.0000 + 1.5000 2.0000 +''' + +print(variable) # this is data in variable format +""" +Variable containing: + 1 2 + 3 4 +[torch.FloatTensor of size 2x2] +""" + +print(variable.data) # this is data in tensor format +""" + 1 2 + 3 4 +[torch.FloatTensor of size 2x2] +""" + +print(variable.data.numpy()) # numpy format +""" +[[ 1. 2.] + [ 3. 4.]] +""" \ No newline at end of file diff --git a/tutorial-contents/203_activation.py b/tutorial-contents/203_activation.py new file mode 100644 index 0000000..a0c3849 --- /dev/null +++ b/tutorial-contents/203_activation.py @@ -0,0 +1,49 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +matplotlib +""" +import torch +import torch.nn.functional as F +from torch.autograd import Variable +import matplotlib.pyplot as plt + +# fake data +x = torch.linspace(-5, 5, 200) # x data (tensor), shape=(100, 1) +x = Variable(x) +x_np = x.data.numpy() # numpy array for plotting + +# following are popular activation functions +y_relu = F.relu(x).data.numpy() +y_sigmoid = F.sigmoid(x).data.numpy() +y_tanh = F.tanh(x).data.numpy() +y_softplus = F.softplus(x).data.numpy() +# y_softmax = F.softmax(x) softmax is a special kind of activation function, it is about probability + + +# plt to visualize these activation function +plt.figure(1, figsize=(8, 6)) +plt.subplot(221) +plt.plot(x_np, y_relu, c='red', label='relu') +plt.ylim((-1, 5)) +plt.legend(loc='best') + +plt.subplot(222) +plt.plot(x_np, y_sigmoid, c='red', label='sigmoid') +plt.ylim((-0.2, 1.2)) +plt.legend(loc='best') + +plt.subplot(223) +plt.plot(x_np, y_tanh, c='red', label='tanh') +plt.ylim((-1.2, 1.2)) +plt.legend(loc='best') + +plt.subplot(224) +plt.plot(x_np, y_softplus, c='red', label='softplus') +plt.ylim((-0.2, 6)) +plt.legend(loc='best') + +plt.show() \ No newline at end of file diff --git a/tutorial-contents/301_regression.py b/tutorial-contents/301_regression.py new file mode 100644 index 0000000..149fac3 --- /dev/null +++ b/tutorial-contents/301_regression.py @@ -0,0 +1,64 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +matplotlib +""" +import torch +from torch.autograd import Variable +import torch.nn.functional as F +import matplotlib.pyplot as plt + +torch.manual_seed(1) # reproducible + +x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1) # x data (tensor), shape=(100, 1) +y = x.pow(2) + 0.2*torch.rand(x.size()) # noisy y data (tensor), shape=(100, 1) + +# torch can only train on Variable, so convert them to Variable +x, y = Variable(x), Variable(y) + +# plt.scatter(x.data.numpy(), y.data.numpy()) +# plt.show() + + +class Net(torch.nn.Module): + def __init__(self, n_feature, n_hidden, n_output): + super(Net, self).__init__() + self.hidden = torch.nn.Linear(n_feature, n_hidden) # hidden layer + self.predict = torch.nn.Linear(n_hidden, n_output) # output layer + + def forward(self, x): + x = F.relu(self.hidden(x)) # activation function for hidden layer + x = self.predict(x) # linear output + return x + +net = Net(n_feature=1, n_hidden=10, n_output=1) # define the network +print(net) # net architecture + +optimizer = torch.optim.SGD(net.parameters(), lr=0.5) +loss_func = torch.nn.MSELoss() # this is for regression mean squared loss + +plt.ion() # something about plotting +plt.show() + +for t in range(100): + prediction = net(x) # input x and predict based on x + + loss = loss_func(prediction, y) # must be (1. nn output, 2. target) + + optimizer.zero_grad() # clear gradients for next train + loss.backward() # backpropagation, compute gradients + optimizer.step() # apply gradients + + if t % 5 == 0: + # plot and show learning process + plt.cla() + plt.scatter(x.data.numpy(), y.data.numpy()) + plt.plot(x.data.numpy(), prediction.data.numpy(), 'r-', lw=5) + plt.text(0.5, 0, 'Loss=%.4f' % loss.data[0], fontdict={'size': 20, 'color': 'red'}) + plt.pause(0.1) + +plt.ioff() +plt.show() \ No newline at end of file diff --git a/tutorial-contents/302_classification.py b/tutorial-contents/302_classification.py new file mode 100644 index 0000000..b371395 --- /dev/null +++ b/tutorial-contents/302_classification.py @@ -0,0 +1,72 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +matplotlib +""" +import torch +from torch.autograd import Variable +import torch.nn.functional as F +import matplotlib.pyplot as plt + +torch.manual_seed(1) # reproducible + +# make fake data +n_data = torch.ones(100, 2) +x0 = torch.normal(2*n_data, 1) # class0 x data (tensor), shape=(100, 2) +y0 = torch.zeros(100) # class0 y data (tensor), shape=(100, 1) +x1 = torch.normal(-2*n_data, 1) # class1 x data (tensor), shape=(100, 2) +y1 = torch.ones(100) # class1 y data (tensor), shape=(100, 1) +x = torch.cat((x0, x1), 0).type(torch.FloatTensor) # FloatTensor = 32-bit floating +y = torch.cat((y0, y1), ).type(torch.LongTensor) # LongTensor = 64-bit integer + +# torch can only train on Variable, so convert them to Variable +x, y = Variable(x), Variable(y) + +# plt.scatter(x.data.numpy()[:, 0], x.data.numpy()[:, 1], c=y.data.numpy(), s=100, lw=0, cmap='RdYlGn') +# plt.show() + + +class Net(torch.nn.Module): + def __init__(self, n_feature, n_hidden, n_output): + super(Net, self).__init__() + self.hidden = torch.nn.Linear(n_feature, n_hidden) # hidden layer + self.out = torch.nn.Linear(n_hidden, n_output) # output layer + + def forward(self, x): + x = F.relu(self.hidden(x)) # activation function for hidden layer + x = self.out(x) + return x + +net = Net(n_feature=2, n_hidden=10, n_output=2) # define the network +print(net) # net architecture + +optimizer = torch.optim.SGD(net.parameters(), lr=0.02) +loss_func = torch.nn.CrossEntropyLoss() # the target label is not one-hotted + +plt.ion() # something about plotting +plt.show() + +for t in range(100): + out = net(x) # input x and predict based on x + loss = loss_func(out, y) # must be (1. nn output, 2. target), the target label is not one-hotted + + optimizer.zero_grad() # clear gradients for next train + loss.backward() # backpropagation, compute gradients + optimizer.step() # apply gradients + + if t % 2 == 0: + # plot and show learning process + plt.cla() + prediction = torch.max(F.softmax(out), 1)[1] + pred_y = prediction.data.numpy().squeeze() + target_y = y.data.numpy() + plt.scatter(x.data.numpy()[:, 0], x.data.numpy()[:, 1], c=pred_y, s=100, lw=0, cmap='RdYlGn') + accuracy = sum(pred_y == target_y)/200 + plt.text(1.5, -4, 'Accuracy=%.2f' % accuracy, fontdict={'size': 20, 'color': 'red'}) + plt.pause(0.1) + +plt.ioff() +plt.show() \ No newline at end of file diff --git a/tutorial-contents/303_build_nn_quickly.py b/tutorial-contents/303_build_nn_quickly.py new file mode 100644 index 0000000..de19845 --- /dev/null +++ b/tutorial-contents/303_build_nn_quickly.py @@ -0,0 +1,35 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +""" +import torch +import torch.nn.functional as F + + +# replace following class code with an easy sequential network +class Net(torch.nn.Module): + def __init__(self, n_feature, n_hidden, n_output): + super(Net, self).__init__() + self.hidden = torch.nn.Linear(n_feature, n_hidden) # hidden layer + self.predict = torch.nn.Linear(n_hidden, n_output) # output layer + + def forward(self, x): + x = F.relu(self.hidden(x)) # activation function for hidden layer + x = self.predict(x) # linear output + return x + +net1 = Net(1, 10, 1) + +# easy and fast way to build your network +net2 = torch.nn.Sequential( + torch.nn.Linear(1, 10), + torch.nn.ReLU(), + torch.nn.Linear(10, 1) +) + + +print(net1) # net1 architecture +print(net2) # net2 architecture \ No newline at end of file diff --git a/tutorial-contents/304_save_reload.py b/tutorial-contents/304_save_reload.py new file mode 100644 index 0000000..8c28824 --- /dev/null +++ b/tutorial-contents/304_save_reload.py @@ -0,0 +1,88 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +matplotlib +""" +import torch +from torch.autograd import Variable +import matplotlib.pyplot as plt + +torch.manual_seed(1) # reproducible + +# fake data +x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1) # x data (tensor), shape=(100, 1) +y = x.pow(2) + 0.2*torch.rand(x.size()) # noisy y data (tensor), shape=(100, 1) +x, y = Variable(x, requires_grad=False), Variable(y, requires_grad=False) + + +def save(): + # save net1 + net1 = torch.nn.Sequential( + torch.nn.Linear(1, 10), + torch.nn.ReLU(), + torch.nn.Linear(10, 1) + ) + optimizer = torch.optim.SGD(net1.parameters(), lr=0.5) + loss_func = torch.nn.MSELoss() + + for t in range(100): + prediction = net1(x) + loss = loss_func(prediction, y) + optimizer.zero_grad() + loss.backward() + optimizer.step() + + # plot result + plt.figure(1, figsize=(10, 3)) + plt.subplot(131) + plt.title('Net1') + plt.scatter(x.data.numpy(), y.data.numpy()) + plt.plot(x.data.numpy(), prediction.data.numpy(), 'r-', lw=5) + + # 2 ways to save the net + torch.save(net1, 'net.pkl') # save entire net + torch.save(net1.state_dict(), 'net_params.pkl') # save only the parameters + + +def restore_net(): + # restore entire net1 to net2 + net2 = torch.load('net.pkl') + prediction = net2(x) + + # plot result + plt.subplot(132) + plt.title('Net2') + plt.scatter(x.data.numpy(), y.data.numpy()) + plt.plot(x.data.numpy(), prediction.data.numpy(), 'r-', lw=5) + + +def restore_params(): + # restore only the parameters in net1 to net3 + net3 = torch.nn.Sequential( + torch.nn.Linear(1, 10), + torch.nn.ReLU(), + torch.nn.Linear(10, 1) + ) + + # copy net1's parameters into net3 + net3.load_state_dict(torch.load('net_params.pkl')) + prediction = net3(x) + + # plot result + plt.subplot(133) + plt.title('Net3') + plt.scatter(x.data.numpy(), y.data.numpy()) + plt.plot(x.data.numpy(), prediction.data.numpy(), 'r-', lw=5) + plt.show() + +# save net1 +save() + +# restore entire net (may slow) +restore_net() + +# restore only the net parameters +restore_params() diff --git a/tutorial-contents/305_batch_train.py b/tutorial-contents/305_batch_train.py new file mode 100644 index 0000000..4a09232 --- /dev/null +++ b/tutorial-contents/305_batch_train.py @@ -0,0 +1,31 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +""" +import torch +import torch.utils.data as Data + +torch.manual_seed(1) # reproducible + +BATCH_SIZE = 5 +# BATCH_SIZE = 8 + +x = torch.linspace(1, 10, 10) # this is x data (torch tensor) +y = torch.linspace(10, 1, 10) # this is y data (torch tensor) + +torch_dataset = Data.TensorDataset(data_tensor=x, target_tensor=y) +loader = Data.DataLoader( + dataset=torch_dataset, # torch TensorDataset format + batch_size=BATCH_SIZE, # mini batch size + shuffle=True, # random shuffle for training + num_workers=2, # subprocesses for loading data +) + +for epoch in range(3): # train entire dataset 3 times + for step, (batch_x, batch_y) in enumerate(loader): # for each training step + # train your data... + print('Epoch: ', epoch, '| Step: ', step, '| batch x: ', + batch_x.numpy(), '| batch y: ', batch_y.numpy()) diff --git a/tutorial-contents/306_optimizer.py b/tutorial-contents/306_optimizer.py new file mode 100644 index 0000000..ab2809d --- /dev/null +++ b/tutorial-contents/306_optimizer.py @@ -0,0 +1,85 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +matplotlib +""" +import torch +import torch.utils.data as Data +import torch.nn.functional as F +from torch.autograd import Variable +import matplotlib.pyplot as plt + +torch.manual_seed(1) # reproducible + +LR = 0.01 +BATCH_SIZE = 32 +EPOCH = 12 + +# fake dataset +x = torch.unsqueeze(torch.linspace(-1, 1, 1000), dim=1) +y = x.pow(2) + 0.1*torch.normal(torch.zeros(*x.size())) + +# plot dataset +plt.scatter(x.numpy(), y.numpy()) +plt.show() + +# put dateset into torch dataset +torch_dataset = Data.TensorDataset(data_tensor=x, target_tensor=y) +loader = Data.DataLoader(dataset=torch_dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=2,) + + +# default network +class Net(torch.nn.Module): + def __init__(self): + super(Net, self).__init__() + self.hidden = torch.nn.Linear(1, 20) # hidden layer + self.predict = torch.nn.Linear(20, 1) # output layer + + def forward(self, x): + x = F.relu(self.hidden(x)) # activation function for hidden layer + x = self.predict(x) # linear output + return x + +# different nets +net_SGD = Net() +net_Momentum = Net() +net_RMSprop = Net() +net_Adam = Net() +nets = [net_SGD, net_Momentum, net_RMSprop, net_Adam] + +# different optimizers +opt_SGD = torch.optim.SGD(net_SGD.parameters(), lr=LR) +opt_Momentum = torch.optim.SGD(net_Momentum.parameters(), lr=LR, momentum=0.8) +opt_RMSprop = torch.optim.RMSprop(net_RMSprop.parameters(), lr=LR, alpha=0.9) +opt_Adam = torch.optim.Adam(net_Adam.parameters(), lr=LR, betas=(0.9, 0.99)) +optimizers = [opt_SGD, opt_Momentum, opt_RMSprop, opt_Adam] + +loss_func = torch.nn.MSELoss() +losses_his = [[], [], [], []] # record loss + +# training +for epoch in range(EPOCH): + print('Epoch: ', epoch) + for step, (batch_x, batch_y) in enumerate(loader): # for each training step + b_x = Variable(batch_x) + b_y = Variable(batch_y) + + for net, opt, l_his in zip(nets, optimizers, losses_his): + output = net(b_x) # get output for every net + loss = loss_func(output, b_y) # compute loss for every net + opt.zero_grad() # clear gradients for next train + loss.backward() # backpropagation, compute gradients + opt.step() # apply gradients + l_his.append(loss.data[0]) # loss recoder + +labels = ['SGD', 'Momentum', 'RMSprop', 'Adam'] +for i, l_his in enumerate(losses_his): + plt.plot(l_his, label=labels[i]) +plt.legend(loc='best') +plt.xlabel('Steps') +plt.ylabel('Loss') +plt.ylim((0, 0.2)) +plt.show() diff --git a/tutorial-contents/401_CNN.py b/tutorial-contents/401_CNN.py new file mode 100644 index 0000000..f6904ee --- /dev/null +++ b/tutorial-contents/401_CNN.py @@ -0,0 +1,109 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +torchvision +matplotlib +""" +import torch +import torch.nn as nn +from torch.autograd import Variable +import torch.utils.data as Data +import torchvision +import matplotlib.pyplot as plt + +torch.manual_seed(1) # reproducible + +# Hyper Parameters +EPOCH = 1 # train the training data n times, to save time, we just train 1 epoch +BATCH_SIZE = 50 +LR = 0.001 # learning rate +DOWNLOAD_MNIST = False + + +# Mnist digits dataset +train_data = torchvision.datasets.MNIST( + root='./mnist/', + train=True, # this is training data + transform=torchvision.transforms.ToTensor(), # Converts a PIL.Image or numpy.ndarray to + # torch.FloatTensor of shape (C x H x W) and normalize in the range [0.0, 1.0] + download=DOWNLOAD_MNIST, # download it if you don't have it +) + +# plot one example +print(train_data.train_data.size()) # (60000, 28, 28) +print(train_data.train_labels.size()) # (60000) +plt.imshow(train_data.train_data[0].numpy(), cmap='gray') +plt.title('%i' % train_data.train_labels[0]) +plt.show() + +# Data Loader for easy mini-batch return in training, the image batch shape will be (50, 1, 28, 28) +train_loader = Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True) + +# convert test data into Variable, pick 2000 samples to speed up testing +test_data = torchvision.datasets.MNIST(root='./mnist/', train=False) +test_x = Variable(torch.unsqueeze(test_data.test_data, dim=1), volatile=True).type(torch.FloatTensor)[:2000]/255. # shape from (2000, 28, 28) to (2000, 1, 28, 28), value in range(0,1) +test_y = test_data.test_labels[:2000] + + +class CNN(nn.Module): + def __init__(self): + super(CNN, self).__init__() + self.conv1 = nn.Sequential( # input shape (1, 28, 28) + nn.Conv2d( + in_channels=1, # input height + out_channels=16, # n_filters + kernel_size=5, # filter size + stride=1, # filter movement/step + padding=2, # if want same width and length of this image after con2d, padding=(kernel_size-1)/2 if stride=1 + ), # output shape (16, 28, 28) + nn.ReLU(), # activation + nn.MaxPool2d(kernel_size=2), # choose max value in 2x2 area, output shape (16, 14, 14) + ) + self.conv2 = nn.Sequential( # input shape (1, 28, 28) + nn.Conv2d(16, 32, 5, 1, 2), # output shape (32, 14, 14) + nn.ReLU(), # activation + nn.MaxPool2d(2), # output shape (32, 7, 7) + ) + self.out = nn.Linear(32 * 7 * 7, 10) # fully connected layer, output 10 classes + + def forward(self, x): + x = self.conv1(x) + x = self.conv2(x) + x = x.view(x.size(0), -1) # flatten the output of conv2 to (batch_size, 32 * 7 * 7) + output = self.out(x) + return output + + +cnn = CNN() +print(cnn) # net architecture + +optimizer = torch.optim.Adam(cnn.parameters(), lr=LR) # optimize all cnn parameters +loss_func = nn.CrossEntropyLoss() # the target label is not one-hotted + +# training and testing +for epoch in range(EPOCH): + for step, (x, y) in enumerate(train_loader): # gives batch data, normalize x when iterate train_loader + b_x = Variable(x) # batch x + b_y = Variable(y) # batch y + + output = cnn(b_x) # cnn output + loss = loss_func(output, b_y) # cross entropy loss + optimizer.zero_grad() # clear gradients for this training step + loss.backward() # backpropagation, compute gradients + optimizer.step() # apply gradients + + if step % 50 == 0: + test_output = cnn(test_x) + pred_y = torch.max(test_output, 1)[1].data.squeeze() + accuracy = sum(pred_y == test_y) / test_y.size(0) + print('Epoch: ', epoch, '| train loss: %.4f' % loss.data[0], '| test accuracy: %.2f' % accuracy) + + +# print 10 predictions from test data +test_output = cnn(test_x[:10]) +pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze() +print(pred_y, 'prediction number') +print(test_y[:10].numpy(), 'real number') diff --git a/tutorial-contents/402_RNN_classifier.py b/tutorial-contents/402_RNN_classifier.py new file mode 100644 index 0000000..6e08739 --- /dev/null +++ b/tutorial-contents/402_RNN_classifier.py @@ -0,0 +1,108 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +matplotlib +torchvision +""" +import torch +from torch import nn +from torch.autograd import Variable +import torchvision.datasets as dsets +import torchvision.transforms as transforms +import matplotlib.pyplot as plt + + +torch.manual_seed(1) # reproducible + +# Hyper Parameters +EPOCH = 1 # train the training data n times, to save time, we just train 1 epoch +BATCH_SIZE = 64 +TIME_STEP = 28 # rnn time step / image height +INPUT_SIZE = 28 # rnn input size / image width +LR = 0.01 # learning rate +DOWNLOAD_MNIST = False # set to True if haven't download the data + + +# Mnist digital dataset +train_data = dsets.MNIST( + root='./mnist/', + train=True, # this is training data + transform=transforms.ToTensor(), # Converts a PIL.Image or numpy.ndarray to + # torch.FloatTensor of shape (C x H x W) and normalize in the range [0.0, 1.0] + download=DOWNLOAD_MNIST, # download it if you don't have it +) + +# plot one example +print(train_data.train_data.size()) # (60000, 28, 28) +print(train_data.train_labels.size()) # (60000) +plt.imshow(train_data.train_data[0].numpy(), cmap='gray') +plt.title('%i' % train_data.train_labels[0]) +plt.show() + +# Data Loader for easy mini-batch return in training +train_loader = torch.utils.data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True) + +# convert test data into Variable, pick 2000 samples to speed up testing +test_data = dsets.MNIST(root='./mnist/', train=False, transform=transforms.ToTensor()) +test_x = Variable(test_data.test_data, volatile=True).type(torch.FloatTensor)[:2000]/255. # shape (2000, 28, 28) value in range(0,1) +test_y = test_data.test_labels.numpy().squeeze()[:2000] # covert to numpy array + + +class RNN(nn.Module): + def __init__(self): + super(RNN, self).__init__() + + self.rnn = nn.LSTM( # if use nn.RNN(), it hardly learns + input_size=28, + hidden_size=64, # rnn hidden unit + num_layers=1, # number of rnn layer + batch_first=True, # input & output will has batch size as 1s dimension. e.g. (batch, time_step, input_size) + ) + + self.out = nn.Linear(64, 10) + + def forward(self, x): + # x shape (batch, time_step, input_size) + # r_out shape (batch, time_step, output_size) + # h_n shape (n_layers, batch, hidden_size) + # h_c shape (n_layers, batch, hidden_size) + r_out, (h_n, h_c) = self.rnn(x, None) # None represents zero initial hidden state + + # choose r_out at the last time step + out = self.out(r_out[:, -1, :]) + return out + + +rnn = RNN() +print(rnn) + +optimizer = torch.optim.Adam(rnn.parameters(), lr=LR) # optimize all cnn parameters +loss_func = nn.CrossEntropyLoss() # the target label is not one-hotted + +# training and testing +for epoch in range(EPOCH): + for step, (x, y) in enumerate(train_loader): # gives batch data + b_x = Variable(x.view(-1, 28, 28)) # reshape x to (batch, time_step, input_size) + b_y = Variable(y) # batch y + + output = rnn(b_x) # rnn output + loss = loss_func(output, b_y) # cross entropy loss + optimizer.zero_grad() # clear gradients for this training step + loss.backward() # backpropagation, compute gradients + optimizer.step() # apply gradients + + if step % 50 == 0: + test_output = rnn(test_x) # (samples, time_step, input_size) + pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze() + accuracy = sum(pred_y == test_y) / test_y.size + print('Epoch: ', epoch, '| train loss: %.4f' % loss.data[0], '| test accuracy: %.2f' % accuracy) + +# print 10 predictions from test data +test_output = rnn(test_x[:10].view(-1, 28, 28)) +pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze() +print(pred_y, 'prediction number') +print(test_y[:10], 'real number') + diff --git a/tutorial-contents/403_RNN_regressor.py b/tutorial-contents/403_RNN_regressor.py new file mode 100644 index 0000000..7624676 --- /dev/null +++ b/tutorial-contents/403_RNN_regressor.py @@ -0,0 +1,96 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +matplotlib +numpy +""" +import torch +from torch import nn +from torch.autograd import Variable +import numpy as np +import matplotlib.pyplot as plt + +torch.manual_seed(1) # reproducible + +# Hyper Parameters +BATCH_SIZE = 64 +TIME_STEP = 5 # rnn time step +INPUT_SIZE = 1 # rnn input size +LR = 0.02 # learning rate + +# show data +steps = np.linspace(0, np.pi*2, 100, dtype=np.float32) +x_np = np.sin(steps) # float32 for converting torch FloatTensor +y_np = np.cos(steps) +plt.plot(steps, y_np, 'r-', label='target (cos)') +plt.plot(steps, x_np, 'b-', label='input (sin)') +plt.legend(loc='best') +plt.show() + + +class RNN(nn.Module): + def __init__(self): + super(RNN, self).__init__() + + self.rnn = nn.RNN( + input_size=1, + hidden_size=32, # rnn hidden unit + num_layers=1, # number of rnn layer + batch_first=True, # input & output will has batch size as 1s dimension. e.g. (batch, time_step, input_size) + ) + self.out = nn.Linear(32, 1) + + def forward(self, x, h_state): + # x (batch, time_step, input_size) + # h_state (n_layers, batch, hidden_size) + # r_out (batch, time_step, output_size) + r_out, h_state = self.rnn(x, h_state) + + outs = [] # save all predictions + for time_step in range(r_out.size(1)): # calculate output for each time step + outs.append(self.out(r_out[:, time_step, :])) + return torch.stack(outs, dim=1), h_state + + +rnn = RNN() +print(rnn) + +optimizer = torch.optim.Adam(rnn.parameters(), lr=LR) # optimize all cnn parameters +loss_func = nn.MSELoss() + +h_state = None # for initial hidden state + +plt.figure(1, figsize=(12, 5)) +plt.ion() # continuously plot +plt.show() + +for step in range(60): + start, end = step * np.pi, (step+1)*np.pi # time steps + # use sin predicts cos + steps = np.linspace(start, end, 10, dtype=np.float32) + x_np = np.sin(steps) # float32 for converting torch FloatTensor + y_np = np.cos(steps) + + x = Variable(torch.from_numpy(x_np[np.newaxis, :, np.newaxis])) # shape (batch, time_step, input_size) + y = Variable(torch.from_numpy(y_np[np.newaxis, :, np.newaxis])) + + prediction, h_state = rnn(x, h_state) # rnn output + # !! next step is important !! + h_state = Variable(h_state.data) # repack the hidden state, break the connection from last iteration + + loss = loss_func(prediction, y) # cross entropy loss + optimizer.zero_grad() # clear gradients for this training step + loss.backward() # backpropagation, compute gradients + optimizer.step() # apply gradients + + # plotting + plt.plot(steps, y_np.flatten(), 'r-') + plt.plot(steps, prediction.data.numpy().flatten(), 'b-') + plt.draw() + plt.pause(0.05) + +plt.ioff() +plt.show() diff --git a/tutorial-contents/404_autoencoder.py b/tutorial-contents/404_autoencoder.py new file mode 100644 index 0000000..17d1476 --- /dev/null +++ b/tutorial-contents/404_autoencoder.py @@ -0,0 +1,142 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +matplotlib +numpy +""" +import torch +import torch.nn as nn +from torch.autograd import Variable +import torch.utils.data as Data +import torchvision +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D +from matplotlib import cm +import numpy as np + + +torch.manual_seed(1) # reproducible + +# Hyper Parameters +EPOCH = 10 +BATCH_SIZE = 64 +LR = 0.005 # learning rate +DOWNLOAD_MNIST = False +N_TEST_IMG = 5 + +# Mnist digits dataset +train_data = torchvision.datasets.MNIST( + root='./mnist/', + train=True, # this is training data + transform=torchvision.transforms.ToTensor(), # Converts a PIL.Image or numpy.ndarray to + # torch.FloatTensor of shape (C x H x W) and normalize in the range [0.0, 1.0] + download=DOWNLOAD_MNIST, # download it if you don't have it +) + +# plot one example +print(train_data.train_data.size()) # (60000, 28, 28) +print(train_data.train_labels.size()) # (60000) +# plt.imshow(train_data.train_data[2].numpy(), cmap='gray') +# plt.title('%i' % train_data.train_labels[2]) +# plt.show() + +# Data Loader for easy mini-batch return in training, the image batch shape will be (50, 1, 28, 28) +train_loader = Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True) + + +class AutoEncoder(nn.Module): + def __init__(self): + super(AutoEncoder, self).__init__() + + self.encoder = nn.Sequential( + nn.Linear(28*28, 128), + nn.Tanh(), + nn.Linear(128, 64), + nn.Tanh(), + nn.Linear(64, 12), + nn.Tanh(), + nn.Linear(12, 3), # compress to 3 features which can be visualized in plt + ) + self.decoder = nn.Sequential( + nn.Linear(3, 12), + nn.Tanh(), + nn.Linear(12, 64), + nn.Tanh(), + nn.Linear(64, 128), + nn.Tanh(), + nn.Linear(128, 28*28), + nn.Sigmoid(), # compress to a range (0, 1) + ) + + def forward(self, x): + encoded = self.encoder(x) + decoded = self.decoder(encoded) + return encoded, decoded + + +autoencoder = AutoEncoder() + +optimizer = torch.optim.Adam(autoencoder.parameters(), lr=LR) +loss_func = nn.MSELoss() + +# initialize figure +f, a = plt.subplots(2, N_TEST_IMG, figsize=(5, 2)) +plt.ion() # continuously plot +plt.show() + +# original data (first row) for viewing +view_data = Variable(train_data.train_data[:N_TEST_IMG].view(-1, 28*28).type(torch.FloatTensor)/255.) +for i in range(N_TEST_IMG): + a[0][i].imshow(np.reshape(view_data.data.numpy()[i], (28, 28)), cmap='gray') + a[0][i].set_xticks(()) + a[0][i].set_yticks(()) + +for epoch in range(EPOCH): + for step, (x, y) in enumerate(train_loader): + b_x = Variable(x.view(-1, 28*28)) # batch x, shape (batch, 28*28) + b_y = Variable(x.view(-1, 28*28)) # batch y, shape (batch, 28*28) + b_label = Variable(y) # batch label + + encoded, decoded = autoencoder(b_x) + + loss = loss_func(decoded, b_y) # mean square error + optimizer.zero_grad() # clear gradients for this training step + loss.backward() # backpropagation, compute gradients + optimizer.step() # apply gradients + + if step % 100 == 0: + print('Epoch: ', epoch, '| train loss: %.4f' % loss.data[0]) + + # plotting decoded image (second row) + _, decoded_data = autoencoder(view_data) + for i in range(N_TEST_IMG): + a[1][i].clear() + a[1][i].imshow(np.reshape(decoded_data.data.numpy()[i], (28, 28)), cmap='gray') + a[1][i].set_xticks(()) + a[1][i].set_yticks(()) + plt.draw() + plt.pause(0.05) + +plt.ioff() +plt.show() + +# visualize in 3D plot +view_data = Variable(train_data.train_data[:200].view(-1, 28*28).type(torch.FloatTensor)/255.) +encoded_data, _ = autoencoder(view_data) +fig = plt.figure(2) +ax = Axes3D(fig) +X = encoded_data.data[:, 0].numpy() +Y = encoded_data.data[:, 1].numpy() +Z = encoded_data.data[:, 2].numpy() +values = train_data.train_labels[:200].numpy() +for x, y, z, s in zip(X, Y, Z, values): + c = cm.rainbow(int(255*s/9)) + ax.text(x, y, z, s, backgroundcolor=c) +ax.set_xlim(X.min(), X.max()) +ax.set_ylim(Y.min(), Y.max()) +ax.set_zlim(Z.min(), Z.max()) +plt.show() + diff --git a/tutorial-contents/405_DQN_Reinforcement_learning.py b/tutorial-contents/405_DQN_Reinforcement_learning.py new file mode 100644 index 0000000..0b0370b --- /dev/null +++ b/tutorial-contents/405_DQN_Reinforcement_learning.py @@ -0,0 +1,129 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +gym: 0.8.1 +numpy +""" +import torch +import torch.nn as nn +from torch.autograd import Variable +import torch.nn.functional as F +import numpy as np +import gym + +# Hyper Parameters +BATCH_SIZE = 32 +LR = 0.01 # learning rate +EPSILON = 0.9 # greedy policy +GAMMA = 0.9 # reward discount +TARGET_REPLACE_ITER = 100 # target update frequency +MEMORY_CAPACITY = 2000 +env = gym.make('CartPole-v0') +env = env.unwrapped +N_ACTIONS = env.action_space.n +N_STATES = env.observation_space.shape[0] + + +class Net(nn.Module): + def __init__(self, ): + super(Net, self).__init__() + self.fc1 = nn.Linear(N_STATES, 10) + self.fc1.weight.data.normal_(0, 0.1) # initialization + self.out = nn.Linear(10, N_ACTIONS) + self.out.weight.data.normal_(0, 0.1) # initialization + + def forward(self, x): + x = self.fc1(x) + x = F.relu(x) + actions_value = self.out(x) + return actions_value + + +class DQN(object): + def __init__(self): + self.eval_net, self.target_net = Net(), Net() + + self.learn_step_counter = 0 # for target updateing + self.memory_counter = 0 # for storing memory + self.memory = np.zeros((MEMORY_CAPACITY, N_STATES * 2 + 2)) # initialize memory + self.optimizer = torch.optim.Adam(self.eval_net.parameters(), lr=LR) + self.loss_func = nn.MSELoss() + + def choose_action(self, x): + x = Variable(torch.unsqueeze(torch.FloatTensor(x), 0)) + # input only one sample + if np.random.uniform() < EPSILON: # greedy + actions_value = self.eval_net.forward(x) + action = torch.max(actions_value, 1)[1].data.numpy()[0, 0] # return the argmax + else: # random + action = np.random.randint(0, N_ACTIONS) + return action + + def store_transition(self, s, a, r, s_): + transition = np.hstack((s, [a, r], s_)) + # replace the old memory with new memory + index = self.memory_counter % MEMORY_CAPACITY + self.memory[index, :] = transition + self.memory_counter += 1 + + def learn(self): + # target parameter update + if self.learn_step_counter % TARGET_REPLACE_ITER == 0: + self.target_net.load_state_dict(self.eval_net.state_dict()) + + # sample batch transitions + sample_index = np.random.choice(MEMORY_CAPACITY, BATCH_SIZE) + b_memory = self.memory[sample_index, :] + b_s = Variable(torch.FloatTensor(b_memory[:, :N_STATES])) + b_a = Variable(torch.LongTensor(b_memory[:, N_STATES:N_STATES+1].astype(int))) + b_r = Variable(torch.FloatTensor(b_memory[:, N_STATES+1:N_STATES+2])) + b_s_ = Variable(torch.FloatTensor(b_memory[:, -N_STATES:])) + + # q_eval w.r.t the action in experience + q_eval = self.eval_net(b_s).gather(1, b_a) # shape (batch, 1) + q_next = self.target_net(b_s_).detach() # detach from graph, don't backpropagate + q_target = b_r + GAMMA * q_next.max(1)[0] # shape (batch, 1) + loss = self.loss_func(q_eval, q_target) + + self.optimizer.zero_grad() + loss.backward() + self.optimizer.step() + +dqn = DQN() + +print('\nCollecting experience...') +for i_episode in range(400): + s = env.reset() + ep_r = 0 + while True: + env.render() + + a = dqn.choose_action(s) + + # take action + s_, r, done, info = env.step(a) + + # modify the reward + x, x_dot, theta, theta_dot = s_ + r1 = (env.x_threshold - abs(x)) / env.x_threshold - 0.8 + r2 = (env.theta_threshold_radians - abs(theta)) / env.theta_threshold_radians - 0.5 + r = r1 + r2 + + # store experience + dqn.store_transition(s, a, r, s_) + + ep_r += r + if dqn.memory_counter > MEMORY_CAPACITY: + dqn.learn() + if done: + print('Ep: ', i_episode, + '| Ep_r: ', round(ep_r, 2), + ) + + if done: + break + + s = s_ \ No newline at end of file diff --git a/tutorial-contents/501_why_torch_dynamic_graph.py b/tutorial-contents/501_why_torch_dynamic_graph.py new file mode 100644 index 0000000..6e42c9e --- /dev/null +++ b/tutorial-contents/501_why_torch_dynamic_graph.py @@ -0,0 +1,106 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +matplotlib +numpy +""" +import torch +from torch import nn +from torch.autograd import Variable +import numpy as np +import matplotlib.pyplot as plt + +torch.manual_seed(1) # reproducible + +# Hyper Parameters +BATCH_SIZE = 64 +TIME_STEP = 5 # rnn time step / image height +INPUT_SIZE = 1 # rnn input size / image width +LR = 0.02 # learning rate +DOWNLOAD_MNIST = False # set to True if haven't download the data + + +class RNN(nn.Module): + def __init__(self): + super(RNN, self).__init__() + + self.rnn = nn.RNN( + input_size=1, + hidden_size=32, # rnn hidden unit + num_layers=1, # number of rnn layer + batch_first=True, # input & output will has batch size as 1s dimension. e.g. (batch, time_step, input_size) + ) + self.out = nn.Linear(32, 1) + + def forward(self, x, h_state): + # x (batch, time_step, input_size) + # h_state (n_layers, batch, hidden_size) + # r_out (batch, time_step, output_size) + r_out, h_state = self.rnn(x, h_state) + + outs = [] # this is where you can find torch is dynamic + for time_step in range(r_out.size(1)): # calculate output for each time step + outs.append(self.out(r_out[:, time_step, :])) + return torch.stack(outs, dim=1), h_state + + +rnn = RNN() +print(rnn) + +optimizer = torch.optim.Adam(rnn.parameters(), lr=LR) # optimize all cnn parameters +loss_func = nn.MSELoss() # the target label is not one-hotted + +h_state = None # for initial hidden state + +plt.figure(1, figsize=(12, 5)) +plt.ion() # continuously plot +plt.show() + +######################## Below is different ######################### + +################ static time steps ########## +# for step in range(60): +# start, end = step * np.pi, (step+1)*np.pi # time steps +# # use sin predicts cos +# steps = np.linspace(start, end, 10, dtype=np.float32) + +################ dynamic time steps ######### +step = 0 +for i in range(60): + dynamic_steps = np.random.randint(1, 4) # has random time steps + start, end = step * np.pi, (step + dynamic_steps) * np.pi # different time steps length + step += dynamic_steps + + # use sin predicts cos + steps = np.linspace(start, end, 10 * dynamic_steps, dtype=np.float32) + +####################### Above is different ########################### + + print(len(steps)) # print how many time step feed to RNN + + x_np = np.sin(steps) # float32 for converting torch FloatTensor + y_np = np.cos(steps) + + x = Variable(torch.from_numpy(x_np[np.newaxis, :, np.newaxis])) # shape (batch, time_step, input_size) + y = Variable(torch.from_numpy(y_np[np.newaxis, :, np.newaxis])) + + prediction, h_state = rnn(x, h_state) # rnn output + # !! next step is important !! + h_state = Variable(h_state.data) # repack the hidden state, break the connection from last iteration + + loss = loss_func(prediction, y) # cross entropy loss + optimizer.zero_grad() # clear gradients for this training step + loss.backward() # backpropagation, compute gradients + optimizer.step() # apply gradients + + # plotting + plt.plot(steps, y_np.flatten(), 'r-') + plt.plot(steps, prediction.data.numpy().flatten(), 'b-') + plt.draw() + plt.pause(0.05) + +plt.ioff() +plt.show() diff --git a/tutorial-contents/502_GPU.py b/tutorial-contents/502_GPU.py new file mode 100644 index 0000000..9581f20 --- /dev/null +++ b/tutorial-contents/502_GPU.py @@ -0,0 +1,84 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +torchvision +""" +import torch +import torch.nn as nn +from torch.autograd import Variable +import torch.utils.data as Data +import torchvision + +torch.manual_seed(1) + +EPOCH = 1 +BATCH_SIZE = 50 +LR = 0.001 +DOWNLOAD_MNIST = False + +train_data = torchvision.datasets.MNIST(root='./mnist/', train=True, transform=torchvision.transforms.ToTensor(), download=DOWNLOAD_MNIST,) +train_loader = Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True) + +test_data = torchvision.datasets.MNIST(root='./mnist/', train=False) + +# !!!!!!!! Change in here !!!!!!!!! # +test_x = Variable(torch.unsqueeze(test_data.test_data, dim=1)).type(torch.FloatTensor)[:2000].cuda()/255. # Tensor on GPU +test_y = test_data.test_labels[:2000] + + +class CNN(nn.Module): + def __init__(self): + super(CNN, self).__init__() + self.conv1 = nn.Sequential(nn.Conv2d(in_channels=1, out_channels=16, kernel_size=5, stride=1, padding=2,), + nn.ReLU(), nn.MaxPool2d(kernel_size=2),) + self.conv2 = nn.Sequential(nn.Conv2d(16, 32, 5, 1, 2), nn.ReLU(), nn.MaxPool2d(2),) + self.out = nn.Linear(32 * 7 * 7, 10) + + def forward(self, x): + x = self.conv1(x) + x = self.conv2(x) + x = x.view(x.size(0), -1) + output = self.out(x) + return output + +cnn = CNN() + +# !!!!!!!! Change in here !!!!!!!!! # +cnn.cuda() # Moves all model parameters and buffers to the GPU. + +optimizer = torch.optim.Adam(cnn.parameters(), lr=LR) +loss_func = nn.CrossEntropyLoss() + +for epoch in range(EPOCH): + for step, (x, y) in enumerate(train_loader): + + # !!!!!!!! Change in here !!!!!!!!! # + b_x = Variable(x).cuda() # Tensor on GPU + b_y = Variable(y).cuda() # Tensor on GPU + + output = cnn(b_x) + loss = loss_func(output, b_y) + optimizer.zero_grad() + loss.backward() + optimizer.step() + + if step % 50 == 0: + test_output = cnn(test_x) + + # !!!!!!!! Change in here !!!!!!!!! # + pred_y = torch.max(test_output, 1)[1].cup().data.squeeze() # Move to CPU + + accuracy = sum(pred_y == test_y) / test_y.size(0) + print('Epoch: ', epoch, '| train loss: %.4f' % loss.data[0], '| test accuracy: %.2f' % accuracy) + + +test_output = cnn(test_x[:10]) + +# !!!!!!!! Change in here !!!!!!!!! # +pred_y = torch.max(test_output, 1)[1].cup().data.numpy().squeeze() # Move to CPU + +print(pred_y, 'prediction number') +print(test_y[:10].numpy(), 'real number') diff --git a/tutorial-contents/503_dropout.py b/tutorial-contents/503_dropout.py new file mode 100644 index 0000000..3f4f42f --- /dev/null +++ b/tutorial-contents/503_dropout.py @@ -0,0 +1,100 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +matplotlib +""" +import torch +from torch.autograd import Variable +import matplotlib.pyplot as plt + +torch.manual_seed(1) # reproducible + +N_SAMPLES = 20 +N_HIDDEN = 300 + +# training data +x = torch.unsqueeze(torch.linspace(-1, 1, N_SAMPLES), 1) +y = x + 0.3*torch.normal(torch.zeros(N_SAMPLES, 1), torch.ones(N_SAMPLES, 1)) +x, y = Variable(x), Variable(y) + +# test data +test_x = torch.unsqueeze(torch.linspace(-1, 1, N_SAMPLES), 1) +test_y = test_x + 0.3*torch.normal(torch.zeros(N_SAMPLES, 1), torch.ones(N_SAMPLES, 1)) +test_x, test_y = Variable(test_x, volatile=True), Variable(test_y, volatile=True) + +# show data +plt.scatter(x.data.numpy(), y.data.numpy(), c='magenta', s=50, alpha=0.5, label='train') +plt.scatter(test_x.data.numpy(), test_y.data.numpy(), c='cyan', s=50, alpha=0.5, label='test') +plt.legend(loc='upper left') +plt.ylim((-2.5, 2.5)) +plt.show() + +net_overfitting = torch.nn.Sequential( + torch.nn.Linear(1, N_HIDDEN), + torch.nn.ReLU(), + torch.nn.Linear(N_HIDDEN, N_HIDDEN), + torch.nn.ReLU(), + torch.nn.Linear(N_HIDDEN, 1), +) + +net_dropped = torch.nn.Sequential( + torch.nn.Linear(1, N_HIDDEN), + torch.nn.Dropout(0.5), # drop 50% of the neuron + torch.nn.ReLU(), + torch.nn.Linear(N_HIDDEN, N_HIDDEN), + torch.nn.Dropout(0.5), # drop 50% of the neuron + torch.nn.ReLU(), + torch.nn.Linear(N_HIDDEN, 1), +) + +print(net_overfitting) # net architecture +print(net_dropped) + +optimizer_ofit = torch.optim.Adam(net_overfitting.parameters(), lr=0.01) +optimizer_drop = torch.optim.Adam(net_dropped.parameters(), lr=0.01) +loss_func = torch.nn.MSELoss() + +plt.ion() # something about plotting +plt.show() + +for t in range(500): + pred_ofit = net_overfitting(x) + pred_drop = net_dropped(x) + loss_ofit = loss_func(pred_ofit, y) + loss_drop = loss_func(pred_drop, y) + + optimizer_ofit.zero_grad() + optimizer_drop.zero_grad() + loss_ofit.backward() + loss_drop.backward() + optimizer_ofit.step() + optimizer_drop.step() + + if t % 10 == 0: + # change to eval mode in order to fix drop out effect + net_overfitting.eval() + net_dropped.eval() # parameters for dropout differ from train mode + + # plotting + plt.cla() + test_pred_ofit = net_overfitting(test_x) + test_pred_drop = net_dropped(test_x) + plt.scatter(x.data.numpy(), y.data.numpy(), c='magenta', s=50, alpha=0.3, label='train') + plt.scatter(test_x.data.numpy(), test_y.data.numpy(), c='cyan', s=50, alpha=0.3, label='test') + plt.plot(test_x.data.numpy(), test_pred_ofit.data.numpy(), 'r-', lw=3, label='overfitting') + plt.plot(test_x.data.numpy(), test_pred_drop.data.numpy(), 'b--', lw=3, label='dropout(50%)') + plt.text(0, -1.2, 'overfitting loss=%.4f' % loss_func(test_pred_ofit, test_y).data[0], fontdict={'size': 20, 'color': 'red'}) + plt.text(0, -1.5, 'dropout loss=%.4f' % loss_func(test_pred_drop, test_y).data[0], fontdict={'size': 20, 'color': 'blue'}) + plt.legend(loc='upper left') + plt.ylim((-2.5, 2.5)) + plt.pause(0.1) + + # change back to train mode + net_overfitting.train() + net_dropped.train() + +plt.ioff() +plt.show() \ No newline at end of file diff --git a/tutorial-contents/504_batch_normalization.py b/tutorial-contents/504_batch_normalization.py new file mode 100644 index 0000000..e4bd046 --- /dev/null +++ b/tutorial-contents/504_batch_normalization.py @@ -0,0 +1,173 @@ +""" +Know more, visit 莫烦Python: https://morvanzhou.github.io/tutorials/ +My Youtube Channel: https://www.youtube.com/user/MorvanZhou + +Dependencies: +torch: 0.1.11 +matplotlib +numpy +""" +import torch +from torch.autograd import Variable +from torch import nn +from torch.nn import init +import torch.utils.data as Data +import torch.nn.functional as F +import matplotlib.pyplot as plt +import numpy as np + +torch.manual_seed(1) # reproducible +np.random.seed(1) + +# Hyper parameters +N_SAMPLES = 2000 +BATCH_SIZE = 64 +EPOCH = 12 +LR = 0.03 +N_HIDDEN = 8 +ACTIVATION = F.tanh +B_INIT = -0.2 # use a bad bias constant initializer + +# training data +x = np.linspace(-7, 10, N_SAMPLES)[:, np.newaxis] +noise = np.random.normal(0, 2, x.shape) +y = np.square(x) - 5 + noise + +# test data +test_x = np.linspace(-7, 10, 200)[:, np.newaxis] +noise = np.random.normal(0, 2, test_x.shape) +test_y = np.square(test_x) - 5 + noise + +train_x, train_y = torch.from_numpy(x).float(), torch.from_numpy(y).float() +test_x = Variable(torch.from_numpy(test_x).float(), volatile=True) # not for computing gradients +test_y = Variable(torch.from_numpy(test_y).float(), volatile=True) + +train_dataset = Data.TensorDataset(data_tensor=train_x, target_tensor=train_y) +train_loader = Data.DataLoader(dataset=train_dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=2,) + +# show data +plt.scatter(train_x.numpy(), train_y.numpy(), c='#FF9359', s=50, alpha=0.2, label='train') +plt.legend(loc='upper left') +plt.show() + +class Net(nn.Module): + def __init__(self, batch_normalization=False): + super(Net, self).__init__() + self.do_bn = batch_normalization + self.fcs = [] + self.bns = [] + self.bn_input = nn.BatchNorm1d(1, momentum=0.5) # for input data + + for i in range(N_HIDDEN): # build hidden layers and BN layers + input_size = 1 if i == 0 else 10 + fc = nn.Linear(input_size, 10) + setattr(self, 'fc%i' % i, fc) # IMPORTANT set layer to the Module + self._set_init(fc) # parameters initialization + self.fcs.append(fc) + if self.do_bn: + bn = nn.BatchNorm1d(10, momentum=0.5) + setattr(self, 'bn%i' % i, bn) # IMPORTANT set layer to the Module + self.bns.append(bn) + + self.predict = nn.Linear(10, 1) # output layer + self._set_init(self.predict) # parameters initialization + + def _set_init(self, layer): + init.normal(layer.weight, mean=0., std=.1) + init.constant(layer.bias, B_INIT) + + def forward(self, x): + pre_activation = [x] + if self.do_bn: x = self.bn_input(x) # input batch normalization + layer_input = [x] + for i in range(N_HIDDEN): + x = self.fcs[i](x) + pre_activation.append(x) + if self.do_bn: x = self.bns[i](x) # batch normalization + x = ACTIVATION(x) + layer_input.append(x) + out = self.predict(x) + return out, layer_input, pre_activation + +nets = [Net(batch_normalization=False), Net(batch_normalization=True)] + +print(*nets) # print net architecture + +opts = [torch.optim.Adam(net.parameters(), lr=LR) for net in nets] + +loss_func = torch.nn.MSELoss() + +f, axs = plt.subplots(4, N_HIDDEN+1, figsize=(10, 5)) +plt.ion() # something about plotting +plt.show() + +def plot_histogram(l_in, l_in_bn, pre_ac, pre_ac_bn): + for i, (ax_pa, ax_pa_bn, ax, ax_bn) in enumerate(zip(axs[0, :], axs[1, :], axs[2, :], axs[3, :])): + [a.clear() for a in [ax_pa, ax_pa_bn, ax, ax_bn]] + if i == 0: + p_range = (-7, 10) + the_range = (-7, 10) + else: + p_range = (-4, 4) + the_range = (-1, 1) + ax_pa.set_title('L' + str(i)) + ax_pa.hist(pre_ac[i].data.numpy().ravel(), bins=10, range=p_range, color='#FF9359', alpha=0.5) + ax_pa_bn.hist(pre_ac_bn[i].data.numpy().ravel(), bins=10, range=p_range, color='#74BCFF', alpha=0.5) + ax.hist(l_in[i].data.numpy().ravel(), bins=10, range=the_range, color='#FF9359') + ax_bn.hist(l_in_bn[i].data.numpy().ravel(), bins=10, range=the_range, color='#74BCFF') + for a in [ax_pa, ax, ax_pa_bn, ax_bn]: + a.set_yticks(()) + a.set_xticks(()) + ax_pa_bn.set_xticks(p_range) + ax_bn.set_xticks(the_range) + axs[0, 0].set_ylabel('PreAct') + axs[1, 0].set_ylabel('BN PreAct') + axs[2, 0].set_ylabel('Act') + axs[3, 0].set_ylabel('BN Act') + plt.pause(0.01) + +# training +losses = [[], []] # recode loss for two networks +for epoch in range(EPOCH): + print('Epoch: ', epoch) + layer_inputs, pre_acts = [], [] + for net, l in zip(nets, losses): + net.eval() # set eval mode to fix moving_mean and moving_var + pred, layer_input, pre_act = net(test_x) + l.append(loss_func(pred, test_y).data[0]) + layer_inputs.append(layer_input) + pre_acts.append(pre_act) + net.train() # free moving_mean and moving_var + plot_histogram(*layer_inputs, *pre_acts) # plot histogram + + for step, (b_x, b_y) in enumerate(train_loader): + b_x, b_y = Variable(b_x), Variable(b_y) + for net, opt in zip(nets, opts): # train for each network + pred, _, _ = net(b_x) + loss = loss_func(pred, b_y) + opt.zero_grad() + loss.backward() + opt.step() # it will also learn the parameters in Batch Normalization + + +plt.ioff() + +# plot training loss +plt.figure(2) +plt.plot(losses[0], c='#FF9359', lw=3, label='Original') +plt.plot(losses[1], c='#74BCFF', lw=3, label='Batch Normalization') +plt.xlabel('step') +plt.ylabel('test loss') +plt.ylim((0, 2000)) +plt.legend(loc='best') + +# evaluation +# set net to eval mode to freeze the parameters in batch normalization layers +[net.eval() for net in nets] # set eval mode to fix moving_mean and moving_var +preds = [net(test_x)[0] for net in nets] +plt.figure(3) +plt.plot(test_x.data.numpy(), preds[0].data.numpy(), c='#FF9359', lw=4, label='Original') +plt.plot(test_x.data.numpy(), preds[1].data.numpy(), c='#74BCFF', lw=4, label='Batch Normalization') +plt.scatter(test_x.data.numpy(), test_y.data.numpy(), c='r', s=50, alpha=0.2, label='train') +plt.legend(loc='best') +plt.show() diff --git a/tutorial-contents/mnist/processed/test.pt b/tutorial-contents/mnist/processed/test.pt new file mode 100644 index 0000000000000000000000000000000000000000..aa3d55f164f360f92bb88ae1d02abd4e5e69a845 GIT binary patch literal 7920408 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