"""Neural network embedding model.
"""
# Coding: utf-8
# File name: embeddings.py
# Created: 2016-07-21
# Description:
## v0.0: File created. Simple Sequential model.

from __future__ import division
from __future__ import print_function

import keras
import theano

from keras.models import Sequential
from keras.layers import Dense, Activation

class EmbeddingNet(Sequential):
  """
  Contain computation graph for embedding operations.
  The basic default model is similar to deepwalk with negative
  node sampling. This model only perform embedding based
  on graph structure (explain the 'Net' name).
  """

  def __init__(self, graph=None,
               name='EmbeddingNet', layers=[],
               emb_dim=200, learning_rate=0.01,
               batch_size=100, neg_samp=5, 
               save_file='EmbeddingNet.keras'):
    """
    Initialize a basic embedding neural network model with
    settings in kwargs.

    Parameters
    ----------
      graph: Graph instance contains graph adj list.
      name: Name of the model.
      layers: List of layer instances for model initialization.
      emb_dim: Embedding size.
      learning_rate: Learning rate (lr).
      batch_size: Size of each training batch.
      neg_samp: Number of negative samples for each target.
      save_file: File location to save the model.
      
    Behavior
    --------
      Create basic object to store neural network parameters.

    """
    # Initialize with super proxy
    super(self).__init__(layers=layers, name=name)

    # General hyperparameters for embeddings
    self._emb_dim = emb_dim
    self._learning_rate = learning_rate
    self._batch_size = batch_size
    self._neg_samp = neg_samp
    self._save_file = save_file

    # Status flags
    self._built = False
    self._compiled = False

    # Data 
    self._graph = graph
    
  def build(self, config=None):
    """
    Build the neural network.
    
    Parameters
    ----------
      config: List of Keras layers to build. If None, a
              default embedding model is loaded.

    Returns
    -------
      None.

    Behavior
    --------
      Add 
    """
    
    if not config:
      self.add(Dense(32, input_dim=784))
      self.add(Activation('relu'))

  def compile(self):
    """
    Compile the graph builded
    


@@ -1848,16 +1848,22 @@
 ef build
+_model
 (self, c
@@ -1962,20 +1962,26 @@
 config: 
-List
+Dictionary
  of Kera
@@ -2003,18 +2003,8 @@
 ld. 
-If None, a
 %0A   
@@ -2014,16 +2014,27 @@
         
+If None, a 
 default 
@@ -2052,16 +2052,31 @@
 odel is 
+%0A              
 loaded.%0A
@@ -2110,13 +2110,31 @@
     
-None.
+List of layer instances
 %0A%0A  
@@ -2171,179 +2171,1445 @@
 Add 
-%0A    %22%22%22%0A    %0A    if not config:%0A      self.add(Dense(32, input_dim=784))%0A      self.add(Activation('relu'))%0A%0A  def compile(self):%0A    %22%22%22%0A    Compile the graph builded%0A    
+layers to the model. Each model should only%0A      be built once. Print warning when trying to build%0A      the built model.%0A    %22%22%22%0A    if self._built:%0A      print('WARNING: Model was built.'%0A            ' Performing more than one build...')%0A    if not config:%0A      self.add(Dense(32, input_dim=784))%0A      self.add(Activation('relu'))%0A      self.add(Dense(1000, input_dim=1000))%0A    else:%0A      for layer in config:%0A        self.add(layer)%0A    self._built = True%0A%0A  def compile_model(self, loss='categorical_crossentropy', %0A              optimizer='adam',%0A              metrics=%5B'accuracy'%5D):%0A    %22%22%22%0A    Compile the model by adding loss functions and%0A    optimizer. %0A%0A    Parameters%0A    ----------%0A      loss: String identifier for the loss function.%0A      optimizer: String identifier for the optimizer.%0A      metric: A list of metrics setting. Only 'accuracy'%0A              for now.%0A%0A    Returns%0A    -------%0A      None.%0A%0A    Behavior%0A    --------%0A      Compile the model and add appropriate loss and%0A      optimization operation. Since this is a simple%0A      sequential model, the input is the first layer%0A      and loss function is computed at the last layer.%0A    %22%22%22%0A    if self._compiled:%0A      print('Model is compiled.')%0A    else:%0A      self.compile(loss=loss, optimizer=optimizer, %0A                   metrics=metrics)%0A      self._compiled = True%0A%0A  def fit_data(x, y, nb_epoch):%0A    %0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A%0A
 %0A%0A

add loss and fit func