You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

VdCnn.cs 6.8 kB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using Tensorflow;
  4. using static Tensorflow.Binding;
  5. namespace TensorFlowNET.Examples.Text
  6. {
  7. public class VdCnn : ITextModel
  8. {
  9. private int embedding_size;
  10. private int[] filter_sizes;
  11. private int[] num_filters;
  12. private int[] num_blocks;
  13. private float learning_rate;
  14. private IInitializer cnn_initializer;
  15. private IInitializer fc_initializer;
  16. public Tensor x { get; private set; }
  17. public Tensor y { get; private set; }
  18. public Tensor is_training { get; private set; }
  19. private RefVariable global_step;
  20. private RefVariable embeddings;
  21. private Tensor x_emb;
  22. private Tensor x_expanded;
  23. private Tensor logits;
  24. private Tensor predictions;
  25. private Tensor loss;
  26. public VdCnn(int alphabet_size, int document_max_len, int num_class)
  27. {
  28. embedding_size = 16;
  29. filter_sizes = new int[] { 3, 3, 3, 3, 3 };
  30. num_filters = new int[] { 64, 64, 128, 256, 512 };
  31. num_blocks = new int[] { 2, 2, 2, 2 };
  32. learning_rate = 0.001f;
  33. cnn_initializer = tensorflow.keras.initializers.he_normal();
  34. fc_initializer = tf.truncated_normal_initializer(stddev: 0.05f);
  35. x = tf.placeholder(tf.int32, new TensorShape(-1, document_max_len), name: "x");
  36. y = tf.placeholder(tf.int32, new TensorShape(-1), name: "y");
  37. is_training = tf.placeholder(tf.@bool, new TensorShape(), name: "is_training");
  38. global_step = tf.Variable(0, trainable: false);
  39. // Embedding Layer
  40. tf_with(tf.name_scope("embedding"), delegate
  41. {
  42. var init_embeddings = tf.random_uniform(new int[] { alphabet_size, embedding_size }, -1.0f, 1.0f);
  43. embeddings = tf.get_variable("embeddings", initializer: init_embeddings);
  44. x_emb = tf.nn.embedding_lookup(embeddings, x);
  45. x_expanded = tf.expand_dims(x_emb, -1);
  46. });
  47. Tensor conv0 = null;
  48. Tensor conv1 = null;
  49. Tensor conv2 = null;
  50. Tensor conv3 = null;
  51. Tensor conv4 = null;
  52. Tensor h_flat = null;
  53. Tensor fc1_out = null;
  54. Tensor fc2_out = null;
  55. // First Convolution Layer
  56. tf_with(tf.variable_scope("conv-0"), delegate
  57. {
  58. conv0 = tf.layers.conv2d(x_expanded,
  59. filters: num_filters[0],
  60. kernel_size: new int[] { filter_sizes[0], embedding_size },
  61. kernel_initializer: cnn_initializer,
  62. activation: tf.nn.relu());
  63. conv0 = tf.transpose(conv0, new int[] { 0, 1, 3, 2 });
  64. });
  65. tf_with(tf.name_scope("conv-block-1"), delegate {
  66. conv1 = conv_block(conv0, 1);
  67. });
  68. tf_with(tf.name_scope("conv-block-2"), delegate {
  69. conv2 = conv_block(conv1, 2);
  70. });
  71. tf_with(tf.name_scope("conv-block-3"), delegate {
  72. conv3 = conv_block(conv2, 3);
  73. });
  74. tf_with(tf.name_scope("conv-block-4"), delegate
  75. {
  76. conv4 = conv_block(conv3, 4, max_pool: false);
  77. });
  78. // ============= k-max Pooling =============
  79. tf_with(tf.name_scope("k-max-pooling"), delegate
  80. {
  81. var h = tf.transpose(tf.squeeze(conv4, new int[] { -1 }), new int[] { 0, 2, 1 });
  82. var top_k = tf.nn.top_k(h, k: 8, sorted: false)[0];
  83. h_flat = tf.reshape(top_k, new int[] { -1, 512 * 8 });
  84. });
  85. // ============= Fully Connected Layers =============
  86. tf_with(tf.name_scope("fc-1"), scope =>
  87. {
  88. fc1_out = tf.layers.dense(h_flat, 2048, activation: tf.nn.relu(), kernel_initializer: fc_initializer);
  89. });
  90. tf_with(tf.name_scope("fc-2"), scope =>
  91. {
  92. fc2_out = tf.layers.dense(fc1_out, 2048, activation: tf.nn.relu(), kernel_initializer: fc_initializer);
  93. });
  94. tf_with(tf.name_scope("fc-3"), scope =>
  95. {
  96. logits = tf.layers.dense(fc2_out, num_class, activation: null, kernel_initializer: fc_initializer);
  97. predictions = tf.argmax(logits, -1, output_type: tf.int32);
  98. });
  99. // ============= Loss and Accuracy =============
  100. tf_with(tf.name_scope("loss"), delegate
  101. {
  102. var y_one_hot = tf.one_hot(y, num_class);
  103. loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits: logits, labels: y_one_hot));
  104. var update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) as List<object>;
  105. tf_with(tf.control_dependencies(update_ops.Select(x => (Operation)x).ToArray()), delegate
  106. {
  107. var adam = tf.train.AdamOptimizer(learning_rate);
  108. adam.minimize(loss, global_step: global_step);
  109. });
  110. });
  111. }
  112. private Tensor conv_block(Tensor input, int i, bool max_pool = true)
  113. {
  114. return tf_with(tf.variable_scope($"conv-block-{i}"), delegate
  115. {
  116. Tensor conv = null;
  117. // Two "conv-batch_norm-relu" layers.
  118. foreach (var j in Enumerable.Range(0, 2))
  119. {
  120. tf_with(tf.variable_scope($"conv-{j}"), delegate
  121. {
  122. // convolution
  123. conv = tf.layers.conv2d(
  124. input,
  125. filters: num_filters[i],
  126. kernel_size: new int[] { filter_sizes[i], num_filters[i - 1] },
  127. kernel_initializer: cnn_initializer,
  128. activation: null);
  129. // batch normalization
  130. conv = tf.layers.batch_normalization(conv, training: is_training);
  131. // relu
  132. conv = tf.nn.relu(conv);
  133. conv = tf.transpose(conv, new int[] { 0, 1, 3, 2 });
  134. });
  135. }
  136. if (max_pool)
  137. {
  138. // Max pooling
  139. return tf.layers.max_pooling2d(
  140. conv,
  141. pool_size: new int[] { 3, 1 },
  142. strides: new int[] { 2, 1 },
  143. padding: "SAME");
  144. }
  145. else
  146. {
  147. return conv;
  148. }
  149. });
  150. }
  151. }
  152. }