Bộ mã hóa tự động trong TensorFlow với ví dụ
Bộ mã hóa tự động trong Deep Learning là gì?
An Tự động mã hóa là một công cụ để học mã hóa dữ liệu một cách hiệu quả theo cách không giám sát. Đây là một loại mạng nơ-ron nhân tạo giúp bạn tìm hiểu cách biểu diễn các tập dữ liệu để giảm kích thước bằng cách huấn luyện mạng nơ-ron bỏ qua nhiễu tín hiệu. Nó là một công cụ tuyệt vời để tạo lại đầu vào.
Nói một cách đơn giản, máy sẽ chụp một hình ảnh và có thể tạo ra một hình ảnh có liên quan chặt chẽ với nhau. Đầu vào trong loại mạng thần kinh này không được gắn nhãn, nghĩa là mạng có thể học mà không cần giám sát. Chính xác hơn, đầu vào được mạng mã hóa để chỉ tập trung vào tính năng quan trọng nhất. Đây là một trong những lý do tại sao bộ mã hóa tự động lại phổ biến để giảm kích thước. Ngoài ra, bộ mã hóa tự động có thể được sử dụng để sản xuất mô hình học tập sáng tạo. Ví dụ, mạng lưới thần kinh có thể được huấn luyện với một tập hợp các khuôn mặt và sau đó có thể tạo ra các khuôn mặt mới.
Bộ mã hóa tự động TensorFlow hoạt động như thế nào?
Mục đích của bộ mã hóa tự động là tạo ra giá trị đầu vào gần đúng bằng cách chỉ tập trung vào các tính năng thiết yếu. Bạn có thể nghĩ tại sao không đơn thuần học cách sao chép và dán đầu vào để tạo ra đầu ra. Trên thực tế, bộ mã hóa tự động là một tập hợp các ràng buộc buộc mạng phải học các cách mới để biểu diễn dữ liệu, khác với việc chỉ sao chép đầu ra.
Một bộ mã hóa tự động điển hình được xác định với đầu vào, biểu diễn bên trong và đầu ra (giá trị gần đúng của đầu vào). Việc học xảy ra trong các lớp gắn liền với biểu diễn bên trong. Trên thực tế, có hai khối lớp chính trông giống như mạng nơ-ron truyền thống. Điểm khác biệt nhỏ là lớp chứa đầu ra phải bằng đầu vào. Trong hình bên dưới, đầu vào ban đầu đi vào khối đầu tiên được gọi là mã hóa. Biểu diễn bên trong này nén (giảm) kích thước của đầu vào. Trong khối thứ hai xảy ra việc xây dựng lại đầu vào. Đây là giai đoạn giải mã.
Mô hình sẽ cập nhật các trọng số bằng cách giảm thiểu hàm mất mát. Mô hình sẽ bị phạt nếu đầu ra tái thiết khác với đầu vào.
Cụ thể, hãy tưởng tượng một bức ảnh có kích thước 50×50 (tức là 250 pixel) và một mạng lưới thần kinh chỉ có một lớp ẩn gồm một trăm nơ-ron. Việc học được thực hiện trên bản đồ đặc trưng nhỏ hơn hai lần so với đầu vào. Điều đó có nghĩa là mạng cần tìm cách tái tạo lại 250 pixel chỉ với một vectơ nơ-ron bằng 100.
Ví dụ về bộ mã hóa tự động xếp chồng
Trong hướng dẫn Autoencoder này, bạn sẽ học cách sử dụng autoencoder xếp chồng. Kiến trúc tương tự như mạng nơ-ron truyền thống. Đầu vào đi đến một lớp ẩn để được nén hoặc giảm kích thước, sau đó đến các lớp tái tạo. Mục tiêu là tạo ra hình ảnh đầu ra gần giống với hình ảnh gốc. Mô hình phải học cách thực hiện nhiệm vụ của mình trong một tập hợp các ràng buộc, tức là với chiều thấp hơn.
Ngày nay, bộ mã hóa tự động ở Học kĩ càng chủ yếu được sử dụng để khử nhiễu hình ảnh. Hãy tưởng tượng một hình ảnh có vết xước; con người vẫn có thể nhận ra nội dung. Ý tưởng của bộ mã hóa tự động khử nhiễu là thêm nhiễu vào hình ảnh để buộc mạng tìm hiểu mẫu đằng sau dữ liệu.
Nhóm hữu ích khác của Autoencoding Deep Learning là bộ mã hóa tự động biến thiên. Loại mạng này có thể tạo ra hình ảnh mới. Hãy tưởng tượng bạn huấn luyện một mạng lưới với hình ảnh một người đàn ông; một mạng lưới như vậy có thể tạo ra những gương mặt mới.
Cách xây dựng bộ mã hóa tự động với TensorFlow
Trong hướng dẫn này, bạn sẽ tìm hiểu cách xây dựng bộ mã hóa tự động xếp chồng để tái tạo lại hình ảnh.
Bạn sẽ sử dụng Bộ dữ liệu CIFAR-10 chứa 60000 hình ảnh màu 32 × 32. Bộ dữ liệu Autoencoding đã được phân chia thành 50000 hình ảnh để đào tạo và 10000 hình ảnh để thử nghiệm. Có tới mười lớp:
- Phi cơ
- Xe hơi
- Chim
- Cát
- Nai
- Dog
- Frog
- Ngựa
- Tàu Thuyền
- Xe tải
Bạn cần tải xuống hình ảnh trong URL này https://www.cs.toronto.edu/~kriz/cifar.html và giải nén nó. Thư mục for-10-batches-py chứa năm lô dữ liệu với 10000 hình ảnh theo thứ tự ngẫu nhiên.
Trước khi xây dựng và huấn luyện mô hình của mình, bạn cần áp dụng một số xử lý dữ liệu. Bạn sẽ tiến hành như sau:
- Nhập dữ liệu
- Chuyển đổi dữ liệu sang định dạng đen trắng
- Nối tất cả các lô
- Xây dựng tập dữ liệu huấn luyện
- Xây dựng trình hiển thị hình ảnh
Xử lý trước hình ảnh
Bước 1) Nhập dữ liệu
Theo trang web chính thức, bạn có thể tải dữ liệu lên bằng mã sau. Mã Autoencoder sẽ tải dữ liệu vào từ điển bằng dữ liệu và nhãn. Lưu ý rằng mã là một chức năng.
import numpy as np import tensorflow as tf import pickle def unpickle(file): import pickle with open(file, 'rb') as fo: dict = pickle.load(fo, encoding='latin1') return dict
Bước 2) Chuyển đổi dữ liệu sang định dạng đen trắng
Để đơn giản, bạn sẽ chuyển đổi dữ liệu sang thang độ xám. Nghĩa là, chỉ có một chiều so với ba chiều cho hình ảnh màu. Hầu hết mạng lưới thần kinh chỉ hoạt động với đầu vào một chiều.
def grayscale(im): return im.reshape(im.shape[0], 3, 32, 32).mean(1).reshape(im.shape[0], -1)
Bước 3) Nối tất cả các lô
Bây giờ cả hai hàm đã được tạo và tập dữ liệu được tải, bạn có thể viết một vòng lặp để nối dữ liệu vào bộ nhớ. Nếu bạn kiểm tra cẩn thận, tệp giải nén chứa dữ liệu có tên data_batch_ với số từ 1 đến 5. Bạn có thể lặp lại các tệp và nối nó vào dữ liệu.
Khi bước này hoàn tất, bạn chuyển đổi dữ liệu màu sang định dạng thang màu xám. Như bạn có thể thấy, hình dạng của dữ liệu là 50000 và 1024. Kích thước 32*32 pixel hiện đã được làm phẳng thành năm 2014.
# Load the data into memory data, labels = [], [] ## Loop over the b for i in range(1, 6): filename = './cifar-10-batches-py/data_batch_' + str(i) open_data = unpickle(filename) if len(data) > 0: data = np.vstack((data, open_data['data'])) labels = np.hstack((labels, open_data['labels'])) else: data = open_data['data'] labels = open_data['labels'] data = grayscale(data) x = np.matrix(data) y = np.array(labels) print(x.shape) (50000, 1024)
Lưu ý: Thay đổi './cifar-10-batches-py/data_batch_' thành vị trí thực tế của tệp của bạn. Ví dụ cho Windows máy, đường dẫn có thể là filename = 'E:\cifar-10-batches-py\data_batch_' + str(i)
Bước 4) Xây dựng tập dữ liệu huấn luyện
Để quá trình huấn luyện diễn ra nhanh hơn và dễ dàng hơn, bạn sẽ chỉ huấn luyện mô hình về hình ảnh con ngựa. Ngựa là hạng thứ bảy trong dữ liệu nhãn. Như đã đề cập trong tài liệu của bộ dữ liệu CIFAR-10, mỗi lớp chứa 5000 hình ảnh. Bạn có thể in hình dạng của dữ liệu để xác nhận có 5.000 hình ảnh với 1024 cột như hình bên dưới TensorFlow Bước ví dụ về bộ mã hóa tự động.
horse_i = np.where(y == 7)[0] horse_x = x[horse_i] print(np.shape(horse_x)) (5000, 1024)
Bước 5) Xây dựng trình hiển thị hình ảnh
Cuối cùng, bạn xây dựng một hàm để vẽ hình ảnh. Bạn sẽ cần chức năng này để in hình ảnh được tái tạo từ bộ mã hóa tự động.
Một cách dễ dàng để in hình ảnh là sử dụng đối tượng imshow từ thư viện matplotlib. Lưu ý rằng, bạn cần chuyển đổi hình dạng của dữ liệu từ 1024 sang 32*32 (tức là định dạng của hình ảnh).
# To plot pretty figures %matplotlib inline import matplotlib import matplotlib.pyplot as plt def plot_image(image, shape=[32, 32], cmap = "Greys_r"): plt.imshow(image.reshape(shape), cmap=cmap,interpolation="nearest") plt.axis("off")
Hàm này có 3 đối số:
- Hình ảnh: đầu vào
- Hình dạng: danh sách, kích thước của hình ảnh
- bản đồ: chọn bản đồ màu. Theo mặc định, màu xám
Bạn có thể thử vẽ hình ảnh đầu tiên trong tập dữ liệu. Bạn sẽ nhìn thấy một người đàn ông trên một con ngựa.
plot_image(horse_x[1], shape=[32, 32], cmap = "Greys_r")
Đặt công cụ ước tính tập dữ liệu
Được rồi, bây giờ tập dữ liệu đã sẵn sàng để sử dụng, bạn có thể bắt đầu sử dụng Tensorflow. Trước khi xây dựng mô hình, hãy sử dụng công cụ ước tính Tập dữ liệu của Tensorflow để cung cấp mạng.
Bạn sẽ xây dựng Bộ dữ liệu với công cụ ước tính TensorFlow. Để làm mới tâm trí, bạn cần sử dụng:
- từ_tensor_slices
- lặp lại
- hàng loạt
Mã đầy đủ để xây dựng tập dữ liệu là:
dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)
Lưu ý rằng x là một chỗ giữ chỗ có hình dạng sau:
- [None,n_inputs]: Đặt thành Không vì số lượng nguồn cấp hình ảnh vào mạng bằng với kích thước lô.
để biết chi tiết, vui lòng tham khảo hướng dẫn trên hồi quy tuyến tính.
Sau đó, bạn cần tạo iterator. Nếu không có dòng mã này, sẽ không có dữ liệu nào đi qua đường ống.
iter = dataset.make_initializable_iterator() # create the iteratorfeatures = iter.get_next()
Bây giờ đường dẫn đã sẵn sàng, bạn có thể kiểm tra xem hình ảnh đầu tiên có giống như trước không (tức là một người đàn ông cưỡi ngựa).
Bạn đặt kích thước lô là 1 vì bạn chỉ muốn đưa một hình ảnh vào tập dữ liệu. Bạn có thể xem kích thước của dữ liệu bằng lệnh print(sess.run(features).shape). Kích thước này bằng (1, 1024). 1 nghĩa là chỉ đưa một hình ảnh có kích thước 1024 vào mỗi hình ảnh. Nếu kích thước lô được đặt thành hai, thì hai hình ảnh sẽ đi qua đường ống. (Không thay đổi kích thước lô. Nếu không, nó sẽ báo lỗi. Chỉ có một hình ảnh tại một thời điểm có thể vào hàm plot_image().
## Parameters n_inputs = 32 * 32 BATCH_SIZE = 1 batch_size = tf.placeholder(tf.int64) # using a placeholder x = tf.placeholder(tf.float32, shape=[None,n_inputs]) ## Dataset dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size) iter = dataset.make_initializable_iterator() # create the iterator features = iter.get_next() ## Print the image with tf.Session() as sess: # feed the placeholder with data sess.run(iter.initializer, feed_dict={x: horse_x, batch_size: BATCH_SIZE}) print(sess.run(features).shape) plot_image(sess.run(features), shape=[32, 32], cmap = "Greys_r") (1, 1024)
Xây dựng mạng lưới
Đã đến lúc xây dựng mạng lưới. Bạn sẽ huấn luyện một bộ mã hóa tự động xếp chồng, tức là một mạng có nhiều lớp ẩn.
Mạng của bạn sẽ có một lớp đầu vào với 1024 điểm, tức là 32×32, hình dạng của hình ảnh.
Khối mã hóa sẽ có một lớp ẩn trên cùng với 300 nơ-ron, lớp trung tâm có 150 nơ-ron. Khối giải mã đối xứng với bộ mã hóa. Bạn có thể hình dung mạng trong hình dưới đây. Lưu ý rằng bạn có thể thay đổi giá trị của lớp ẩn và lớp trung tâm.
Việc xây dựng bộ mã hóa tự động rất giống với bất kỳ mô hình học sâu nào khác.
Bạn sẽ xây dựng mô hình theo các bước sau:
- Xác định các thông số
- Xác định các lớp
- Xác định kiến trúc
- Xác định tối ưu hóa
- Chạy mô hình
- Đánh giá mô hình
Trong phần trước, bạn đã học cách tạo một quy trình để cung cấp dữ liệu cho mô hình, do đó không cần phải tạo lại tập dữ liệu nữa. Bạn sẽ xây dựng một bộ mã hóa tự động với bốn lớp. Bạn sử dụng khởi tạo Xavier. Đây là một kỹ thuật để đặt trọng số ban đầu bằng phương sai của cả đầu vào và đầu ra. Cuối cùng, bạn sử dụng chức năng kích hoạt elu. Bạn thường xuyên hóa hàm mất bằng bộ điều chỉnh L2.
Bước 1) Xác định các thông số
Bước đầu tiên ngụ ý xác định số lượng nơ-ron trong mỗi lớp, tốc độ học tập và siêu tham số của bộ điều chỉnh.
Trước đó, bạn nhập một phần hàm. Đây là phương pháp tốt hơn để xác định các tham số của các lớp dày đặc. Mã bên dưới xác định các giá trị của kiến trúc autoencoder. Như đã liệt kê trước đó, autoencoder có hai lớp, với 300 neuron ở lớp đầu tiên và 150 neuron ở lớp thứ hai. Các giá trị của chúng được lưu trữ trong n_hidden_1 và n_hidden_2.
Bạn cần xác định tốc độ học tập và siêu tham số L2. Các giá trị được lưu trữ trong learning_rate và l2_reg
from functools import partial ## Encoder n_hidden_1 = 300 n_hidden_2 = 150 # codings ## Decoder n_hidden_3 = n_hidden_1 n_outputs = n_inputs learning_rate = 0.01 l2_reg = 0.0001
Kỹ thuật khởi tạo Xavier được gọi với đối tượng xavier_initializer từ phần đóng góp của công cụ ước tính. Trong cùng một công cụ ước tính, bạn có thể thêm bộ điều chỉnh bằng l2_regularizer
## Define the Xavier initialization xav_init = tf.contrib.layers.xavier_initializer() ## Define the L2 regularizer l2_regularizer = tf.contrib.layers.l2_regularizer(l2_reg)
Bước 2) Xác định các lớp
Tất cả các tham số của các lớp dày đặc đã được thiết lập; bạn có thể đóng gói mọi thứ trong biếndense_layer bằng cách sử dụng một phần đối tượng. dense_layer sử dụng kích hoạt ELU, khởi tạo Xavier và chuẩn hóa L2.
## Create the dense layer dense_layer = partial(tf.layers.dense, activation=tf.nn.elu, kernel_initializer=xav_init, kernel_regularizer=l2_regularizer)
Bước 3) Xác định kiến trúc
Nếu bạn nhìn vào hình ảnh kiến trúc, bạn sẽ thấy rằng mạng xếp chồng ba lớp với một lớp đầu ra. Trong mã bên dưới, bạn kết nối các lớp thích hợp. Ví dụ, lớp đầu tiên tính tích vô hướng giữa các đặc điểm ma trận đầu vào và các ma trận chứa 300 trọng số. Sau khi tích vô hướng được tính toán, đầu ra sẽ chuyển đến hàm kích hoạt Elu. Đầu ra trở thành đầu vào của lớp tiếp theo, đó là lý do tại sao bạn sử dụng nó để tính hidden_2, v.v. Phép nhân ma trận giống nhau cho mỗi lớp vì bạn sử dụng cùng một hàm kích hoạt. Lưu ý rằng lớp cuối cùng, đầu ra, không áp dụng hàm kích hoạt. Điều này có lý vì đây là đầu vào được tái tạo
## Make the mat mul hidden_1 = dense_layer(features, n_hidden_1) hidden_2 = dense_layer(hidden_1, n_hidden_2) hidden_3 = dense_layer(hidden_2, n_hidden_3) outputs = dense_layer(hidden_3, n_outputs, activation=None)
Bước 4) Xác định tối ưu hóa
Bước cuối cùng là xây dựng trình tối ưu hóa. Bạn sử dụng Lỗi bình phương trung bình làm hàm mất mát. Nếu bạn nhớ lại hướng dẫn về hồi quy tuyến tính, bạn biết rằng MSE được tính toán với sự khác biệt giữa đầu ra dự đoán và nhãn thực. Ở đây, nhãn là đặc điểm vì mô hình cố gắng xây dựng lại đầu vào. Do đó, bạn muốn giá trị trung bình của tổng chênh lệch bình phương giữa đầu ra và đầu vào được dự đoán. Với TensorFlow, bạn có thể mã hóa hàm mất như sau:
loss = tf.reduce_mean(tf.square(outputs - features))
Sau đó, bạn cần tối ưu hóa hàm mất. Bạn sử dụng trình tối ưu hóa Adam để tính toán độ dốc. Hàm mục tiêu là giảm thiểu tổn thất.
## Optimize loss = tf.reduce_mean(tf.square(outputs - features)) optimizer = tf.train.AdamOptimizer(learning_rate) train = optimizer.minimize(loss)
Thêm một cài đặt nữa trước khi đào tạo mô hình. Bạn muốn sử dụng kích thước lô là 150, nghĩa là cung cấp cho quy trình 150 hình ảnh mỗi lần lặp. Bạn cần tính toán số lần lặp theo cách thủ công. Đây là chuyện nhỏ để làm:
Nếu bạn muốn truyền 150 hình ảnh mỗi lần và bạn biết có 5000 hình ảnh trong tập dữ liệu, số lần lặp lại bằng . Trong python, bạn có thể chạy các mã sau và đảm bảo đầu ra là 33:
BATCH_SIZE = 150 ### Number of batches : length dataset / batch size n_batches = horse_x.shape[0] // BATCH_SIZE print(n_batches) 33
Bước 5) Chạy mô hình
Cuối cùng nhưng không kém phần quan trọng, hãy đào tạo mô hình. Bạn đang đào tạo mô hình với 100 kỷ nguyên. Nghĩa là, mô hình sẽ nhìn thấy hình ảnh gấp 100 lần với trọng số được tối ưu hóa.
Bạn đã quen với các đoạn mã để huấn luyện mô hình trong Tensorflow. Sự khác biệt nhỏ là sắp xếp dữ liệu trước khi chạy chương trình đào tạo. Bằng cách này, mô hình đào tạo nhanh hơn.
Bạn quan tâm đến việc in tổn thất sau mười kỷ nguyên để xem liệu mô hình có đang học được điều gì không (tức là tổn thất đang giảm dần). Quá trình đào tạo mất từ 2 đến 5 phút, tùy thuộc vào phần cứng máy của bạn.
## Set params n_epochs = 100 ## Call Saver to save the model and re-use it later during evaluation saver = tf.train.Saver() with tf.Session() as sess: sess.run(tf.global_variables_initializer()) # initialise iterator with train data sess.run(iter.initializer, feed_dict={x: horse_x, batch_size: BATCH_SIZE}) print('Training...') print(sess.run(features).shape) for epoch in range(n_epochs): for iteration in range(n_batches): sess.run(train) if epoch % 10 == 0: loss_train = loss.eval() # not shown print("\r{}".format(epoch), "Train MSE:", loss_train) #saver.save(sess, "./my_model_all_layers.ckpt") save_path = saver.save(sess, "./model.ckpt") print("Model saved in path: %s" % save_path) Training... (150, 1024) 0 Train MSE: 2934.455 10 Train MSE: 1672.676 20 Train MSE: 1514.709 30 Train MSE: 1404.3118 40 Train MSE: 1425.058 50 Train MSE: 1479.0631 60 Train MSE: 1609.5259 70 Train MSE: 1482.3223 80 Train MSE: 1445.7035 90 Train MSE: 1453.8597 Model saved in path: ./model.ckpt
Bước 6) Đánh giá mô hình
Bây giờ bạn đã huấn luyện xong mô hình của mình, đã đến lúc đánh giá nó. Bạn cần nhập sert kiểm tra từ tệp /cifar-10-batches-py/.
test_data = unpickle('./cifar-10-batches-py/test_batch') test_x = grayscale(test_data['data']) #test_labels = np.array(test_data['labels'])
LƯU Ý: Cho một Windows máy, mã sẽ trở thành test_data = unpickle(r”E:\cifar-10-batches-py\test_batch”)
Bạn có thể thử in hình ảnh số 13, đó là con ngựa
plot_image(test_x[13], shape=[32, 32], cmap = "Greys_r")
Để đánh giá mô hình, bạn sẽ sử dụng giá trị pixel của hình ảnh này và xem liệu bộ mã hóa có thể tái tạo lại hình ảnh tương tự sau khi thu nhỏ 1024 pixel hay không. Lưu ý rằng, bạn xác định một hàm để đánh giá mô hình trên các ảnh khác nhau. Mô hình chỉ hoạt động tốt hơn trên ngựa.
Hàm này có hai đối số:
- df: Nhập dữ liệu thử nghiệm
- số_hình ảnh: cho biết hình ảnh nào cần nhập
Chức năng được chia thành ba phần:
- Định hình lại hình ảnh theo đúng kích thước tức là 1, 1024
- Cung cấp cho mô hình hình ảnh chưa nhìn thấy, mã hóa/giải mã hình ảnh
- In ảnh thật và ảnh tái tạo
def reconstruct_image(df, image_number = 1): ## Part 1: Reshape the image to the correct dimension i.e 1, 1024 x_test = df[image_number] x_test_1 = x_test.reshape((1, 32*32)) ## Part 2: Feed the model with the unseen image, encode/decode the image with tf.Session() as sess: sess.run(tf.global_variables_initializer()) sess.run(iter.initializer, feed_dict={x: x_test_1, batch_size: 1}) ## Part 3: Print the real and reconstructed image # Restore variables from disk. saver.restore(sess, "./model.ckpt") print("Model restored.") # Reconstruct image outputs_val = outputs.eval() print(outputs_val.shape) fig = plt.figure() # Plot real ax1 = fig.add_subplot(121) plot_image(x_test_1, shape=[32, 32], cmap = "Greys_r") # Plot estimated ax2 = fig.add_subplot(122) plot_image(outputs_val, shape=[32, 32], cmap = "Greys_r") plt.tight_layout() fig = plt.gcf()
Bây giờ hàm đánh giá đã được xác định, bạn có thể xem hình ảnh được xây dựng lại số mười ba
reconstruct_image(df =test_x, image_number = 13)
INFO:tensorflow:Restoring parameters from ./model.ckpt Model restored. (1, 1024)
Tổng kết
- Mục đích chính của bộ mã hóa tự động là nén dữ liệu đầu vào, sau đó giải nén nó thành đầu ra trông gần giống với dữ liệu gốc.
- Kiến trúc của bộ mã hóa tự động đối xứng với một lớp trục được gọi là lớp trung tâm.
- Bạn có thể tạo bộ mã hóa tự động bằng cách sử dụng:
Một phần: để tạo các lớp dày đặc với cài đặt điển hình:
tf.layers.dense, activation=tf.nn.elu, kernel_initializer=xav_init, kernel_regularizer=l2_regularizer
dày đặc_layer(): thực hiện phép nhân ma trận
loss = tf.reduce_mean(tf.square(outputs - features)) optimizer = tf.train.AdamOptimizer(learning_rate) train = optimizer.minimize(loss)