From 573e8aadc6dec073c4b7305b63f89e94e05ba144 Mon Sep 17 00:00:00 2001 From: Tom Rijntjes Date: Tue, 20 Nov 2018 17:26:25 +0100 Subject: [PATCH 1/4] added docker & docker-compose for standardized deployment --- .gitignore | 3 ++- Dockerfile | 37 +++++++++++++++++++++++++++++++++++++ data/twitter/__init__.py | 0 data/twitter/data.py | 8 +++----- docker-compose.yml | 7 +++++++ main.py | 23 ++++++++++++----------- 6 files changed, 61 insertions(+), 17 deletions(-) create mode 100644 Dockerfile create mode 100644 data/twitter/__init__.py create mode 100644 docker-compose.yml diff --git a/.gitignore b/.gitignore index 96f40c19..1382b49b 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ data/.DS_Store *.gz .spyproject/ .vscode/* -model.npz \ No newline at end of file +model.npz +/models diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..9ffcbb67 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,37 @@ +FROM tensorflow/tensorflow:latest-py3 + +ARG TL_VERSION + +RUN echo "Container Tag: ${TF_CONTAINER_VERSION}" \ + && apt-get update \ + && case $TF_CONTAINER_VERSION in \ + latest-py3 | latest-gpu-py3) apt-get install -y python3-tk ;; \ + *) apt-get install -y python-tk ;; \ + esac \ + && if [ -z "$TL_VERSION" ]; then \ + echo "Building a Nightly Release" \ + && apt-get install -y git \ + && mkdir /dist/ && cd /dist/ \ + && git clone https://github.com/tensorlayer/tensorlayer.git \ + && cd tensorlayer \ + && pip install --disable-pip-version-check --no-cache-dir --upgrade -e .[all]; \ + else \ + echo "Building Tag Release: $TL_VERSION" \ + && pip install --disable-pip-version-check --no-cache-dir --upgrade tensorlayer[all]=="$TL_VERSION"; \ + fi \ + && apt-get autoremove -y \ + && rm -rf /var/lib/apt/lists/* + +#Environment Variables for Click +ENV LC_ALL=C.UTF-8 +ENV LANG=C.UTF-8 + +COPY requirements.txt /tmp/ +RUN pip3 install --requirement /tmp/requirements.txt + +COPY . /chatbot + +WORKDIR /chatbot +#RUN python3 main.py --batch-size 32 --num-epochs 1 -lr 0.001 + +CMD python3 main.py --inference-mode diff --git a/data/twitter/__init__.py b/data/twitter/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/data/twitter/data.py b/data/twitter/data.py index 22ca4be9..ffcd682f 100644 --- a/data/twitter/data.py +++ b/data/twitter/data.py @@ -202,11 +202,9 @@ def process_data(): def load_data(PATH=''): # read data control dictionaries - try: - with open(PATH + 'metadata.pkl', 'rb') as f: - metadata = pickle.load(f) - except: - metadata = None + with open(PATH + 'metadata.pkl', 'rb') as f: + metadata = pickle.load(f) + # read numpy arrays idx_q = np.load(PATH + 'idx_q.npy') idx_a = np.load(PATH + 'idx_a.npy') diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..0a546b64 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,7 @@ +version: '2.1' + +services: + chatbot: + build: . + volumes: + - ./models:/chatbot/models/ diff --git a/main.py b/main.py index 0cafee6a..3e8a283a 100644 --- a/main.py +++ b/main.py @@ -84,7 +84,7 @@ def train(data_corpus, batch_size, num_epochs, learning_rate, inference_mode): encode_seqs = tf.placeholder(dtype=tf.int64, shape=[batch_size, None], name="encode_seqs") decode_seqs = tf.placeholder(dtype=tf.int64, shape=[batch_size, None], name="decode_seqs") target_seqs = tf.placeholder(dtype=tf.int64, shape=[batch_size, None], name="target_seqs") - target_mask = tf.placeholder(dtype=tf.int64, shape=[batch_size, None], name="target_mask") + target_mask = tf.placeholder(dtype=tf.int64, shape=[batch_size, None], name="target_mask") net_out, _ = create_model(encode_seqs, decode_seqs, src_vocab_size, emb_dim, is_train=True, reuse=False) net_out.print_params(False) @@ -97,7 +97,7 @@ def train(data_corpus, batch_size, num_epochs, learning_rate, inference_mode): y = tf.nn.softmax(net.outputs) # Loss Function - loss = tl.cost.cross_entropy_seq_with_mask(logits=net_out.outputs, target_seqs=target_seqs, + loss = tl.cost.cross_entropy_seq_with_mask(logits=net_out.outputs, target_seqs=target_seqs, input_mask=target_mask, return_details=False, name='cost') # Optimizer @@ -107,14 +107,14 @@ def train(data_corpus, batch_size, num_epochs, learning_rate, inference_mode): sess.run(tf.global_variables_initializer()) # Load Model - tl.files.load_and_assign_npz(sess=sess, name='model.npz', network=net) + tl.files.load_and_assign_npz(sess=sess, name='/chatbot/models/chatbot.npz', network=net) """ Inference using pre-trained model """ def inference(seed): seed_id = [word2idx.get(w, unk_id) for w in seed.split(" ")] - + # Encode and get state state = sess.run(net_rnn.final_state_encode, {encode_seqs2: [seed_id]}) @@ -150,7 +150,7 @@ def inference(seed): for epoch in range(num_epochs): trainX, trainY = shuffle(trainX, trainY, random_state=0) total_loss, n_iter = 0, 0 - for X, Y in tqdm(tl.iterate.minibatches(inputs=trainX, targets=trainY, batch_size=batch_size, shuffle=False), + for X, Y in tqdm(tl.iterate.minibatches(inputs=trainX, targets=trainY, batch_size=batch_size, shuffle=False), total=n_step, desc='Epoch[{}/{}]'.format(epoch + 1, num_epochs), leave=False): X = tl.prepro.pad_sequences(X) @@ -174,17 +174,17 @@ def inference(seed): # printing average loss after every epoch print('Epoch [{}/{}]: loss {:.4f}'.format(epoch + 1, num_epochs, total_loss / n_iter)) - + # inference after every epoch for seed in seeds: print("Query >", seed) for _ in range(5): sentence = inference(seed) print(" >", ' '.join(sentence)) - + # saving the model - tl.files.save_npz(net.all_params, name='model.npz', sess=sess) - + tl.files.save_npz(net.all_params, name='/chatbot/models/chatbot.npz', sess=sess) + # session cleanup sess.close() @@ -207,7 +207,7 @@ def create_model(encode_seqs, decode_seqs, src_vocab_size, emb_dim, is_train=Tru vocabulary_size = src_vocab_size, embedding_size = emb_dim, name = 'seq_embedding') - + net_rnn = Seq2Seq(net_encode, net_decode, cell_fn = tf.nn.rnn_cell.LSTMCell, n_hidden = emb_dim, @@ -227,7 +227,8 @@ def create_model(encode_seqs, decode_seqs, src_vocab_size, emb_dim, is_train=Tru Initial Setup """ def initial_setup(data_corpus): - metadata, idx_q, idx_a = data.load_data(PATH='data/{}/'.format(data_corpus)) + #metadata, idx_q, idx_a = data.load_data(PATH='data/{}/'.format(data_corpus)) + metadata, idx_q, idx_a = data.load_data(PATH='./data/twitter/') (trainX, trainY), (testX, testY), (validX, validY) = data.split_dataset(idx_q, idx_a) trainX = tl.prepro.remove_pad_sequences(trainX.tolist()) trainY = tl.prepro.remove_pad_sequences(trainY.tolist()) From efe3bc3e412256cd978f519be5e2d6c1924207fa Mon Sep 17 00:00:00 2001 From: Tom Rijntjes Date: Tue, 20 Nov 2018 17:26:46 +0100 Subject: [PATCH 2/4] added docker & docker-compose for standardized deployment --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 9ffcbb67..b243e0a6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,6 +32,6 @@ RUN pip3 install --requirement /tmp/requirements.txt COPY . /chatbot WORKDIR /chatbot -#RUN python3 main.py --batch-size 32 --num-epochs 1 -lr 0.001 +RUN python3 main.py --batch-size 32 --num-epochs 1 -lr 0.001 CMD python3 main.py --inference-mode From 4208a42731d140f0f44b6b5fab655cc70db17705 Mon Sep 17 00:00:00 2001 From: Tom Rijntjes Date: Tue, 20 Nov 2018 17:34:53 +0100 Subject: [PATCH 3/4] fixed gitignore to include models dir --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 1382b49b..d6587947 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,4 @@ data/.DS_Store *.gz .spyproject/ .vscode/* -model.npz -/models +chatbot.npz From b9683fd8935c68f4cb0a39c37b9b60d498cffe2f Mon Sep 17 00:00:00 2001 From: Tom Rijntjes Date: Tue, 20 Nov 2018 17:37:09 +0100 Subject: [PATCH 4/4] adding empty models dir --- models/.gitignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 models/.gitignore diff --git a/models/.gitignore b/models/.gitignore new file mode 100644 index 00000000..5e7d2734 --- /dev/null +++ b/models/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore