Skip to content

Instantly share code, notes, and snippets.

@joshloyal
Created March 11, 2016 15:29
Show Gist options
  • Save joshloyal/4162e47df4f8c5a4150c to your computer and use it in GitHub Desktop.
Save joshloyal/4162e47df4f8c5a4150c to your computer and use it in GitHub Desktop.
Convolutional Network for Sentence Classification (Keras)
from keras.models import Graph
from keras.layers import containers
from keras.layers.core import Dense, Dropout, Activation, Reshape, Flatten
from keras.layers.embeddings import Embedding
from keras.layers.convolutional import Convolution2D, MaxPooling2D
def ngram_cnn(n_vocab, max_length, embedding_size, ngram_filters=[2, 3, 4, 5], n_feature_maps=100, dropout=0.5, n_hidden=15):
"""A single-layer convolutional network using different n-gram filters.
Parameters
----------
n_vocab: int
Number of words in the corpus vocabulary.
max_length: int
Maximum sentence length in the corpus.
embedding_size: int
Size of the dense embedding layer.
ngram_filters: iterable
N-gram filter sizes for the convolutional layers.
n_feature_maps: int
The number of feature maps used for each filter.
dropout: float
Dropout probability for the dropout layer after the conv layers.
n_hidden: int
Number of hidden units used in the fully-connected layer
References
----------
A Sensitivity Analysis of Convolutional Neural Networks for Sentence Classification.
Ye Zhang, Byron C. Wallace. <http://arxiv.org/pdf/1510.03820v3.pdf>
Convolutional Neural Networks for Sentence Classification.
Yoon Kim. <http://arxiv.org/pdf/1408.5882v2.pdf>
"""
model = Graph()
model.add_input(name='data', input_shape=(max_length,), dtype='int32')
model.add_node(Embedding(n_vocab, embedding_size, input_length=max_length),
name='embedding', input='data')
model.add_node(Reshape((1, max_length, embedding_size)),
name='reshape_embedding', input='embedding')
# convolutional n-grams
for n_gram in ngram_filters:
sequential = containers.Sequential()
sequential.add(Convolution2D(n_feature_maps, n_gram, embedding_size, input_shape=(1, max_length, embedding_size)))
sequential.add(Activation('relu'))
sequential.add(MaxPooling2D(pool_size=(max_length - n_gram + 1, 1)))
sequential.add(Flatten()) # this generates a single number from the n-gram level convolution
model.add_node(sequential, name=('unit_' + str(n_gram)), input='reshape_embedding')
model.add_node(Dropout(dropout), name='dropout', inputs=['unit_' + str(n) for n in ngram_filters])
# fully-connected module
fc = containers.Sequential()
fc.add(Dense(n_hidden, input_shape=(n_feature_maps * len(ngram_filters),)))
fc.add(Activation('relu'))
fc.add(Dense(1))
fc.add(Activation('sigmoid'))
model.add_node(fc, name='fully_connected', input='dropout')
model.add_output(name='output', input='fully_connected')
model.compile(loss={'output': 'binary_crossentropy'},
optimizer='adam')
return model
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment