model.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. import math
  2. import time
  3. from functools import wraps
  4. import numpy as np
  5. import tensorflow as tf
  6. from keras import Input, Model
  7. from keras.engine.base_layer import Layer
  8. from keras.layers import Lambda, Dense, Conv2D, Reshape, GlobalAveragePooling2D, BatchNormalization, Activation, Add, \
  9. Multiply, DepthwiseConv2D, LeakyReLU, MaxPooling2D, UpSampling2D, Concatenate, Dropout, concatenate, Embedding, \
  10. LSTM, \
  11. Bidirectional, CuDNNLSTM, Conv1D, MaxPooling1D, GlobalMaxPooling1D
  12. import keras.backend as K
  13. from keras.regularizers import l2
  14. from click_captcha.utils import compose
  15. def yolo_net(input_shape, anchors, num_classes, load_pretrained=True,
  16. weights_path='models/tiny_yolo_weights.h5'):
  17. """create the training model, for Tiny YOLOv3"""
  18. from loss import yolo_loss
  19. # get a new session
  20. # ops.reset_default_graph()
  21. K.clear_session()
  22. image_input = Input(shape=(None, None, 3))
  23. h, w = input_shape
  24. num_anchors = len(anchors)
  25. y_true = [Input(shape=(h//{0: 32, 1: 16}[l], w//{0: 32, 1: 16}[l],
  26. num_anchors//2, num_classes+5)) for l in range(2)]
  27. model_body = tiny_yolo_body(image_input, num_anchors//2, num_classes)
  28. print('Create Tiny YOLOv3 model with {} anchors and {} classes.'.format(num_anchors, num_classes))
  29. if load_pretrained:
  30. model_body.load_weights(weights_path)
  31. print('Load weights {}.'.format(weights_path))
  32. model_loss = Lambda(yolo_loss, output_shape=(1,), name='yolo_loss',
  33. arguments={'anchors': anchors, 'num_classes': num_classes, 'ignore_thresh': 1.})(
  34. [*model_body.output, *y_true])
  35. model = Model([model_body.input, *y_true], model_loss)
  36. model.summary(120)
  37. return model
  38. def mobile_net(input_shape, output_shape=2496):
  39. model = MobileNetV3Small(input_shape, output_shape).build()
  40. model.summary()
  41. return model
  42. def cnn_net(input_shape, output_shape=5710):
  43. _input = Input(input_shape)
  44. use_bias = False
  45. down0 = Conv2D(32, (3, 3), padding='same', use_bias=use_bias)(_input)
  46. down0 = BatchNormalization()(down0)
  47. down0 = LeakyReLU(alpha=0.1)(down0)
  48. down0 = Conv2D(32, (3, 3), padding='same', use_bias=use_bias)(down0)
  49. down0 = BatchNormalization()(down0)
  50. down0 = LeakyReLU(alpha=0.1)(down0)
  51. down0_pool = MaxPooling2D((2, 2), strides=(2, 2))(down0)
  52. down1 = Conv2D(64, (3, 3), padding='same', use_bias=use_bias)(down0_pool)
  53. down1 = BatchNormalization()(down1)
  54. down1 = LeakyReLU(alpha=0.1)(down1)
  55. down1 = Conv2D(64, (3, 3), padding='same', use_bias=use_bias)(down1)
  56. down1 = BatchNormalization()(down1)
  57. down1 = LeakyReLU(alpha=0.1)(down1)
  58. down1_pool = MaxPooling2D((2, 2), strides=(2, 2))(down1)
  59. down2 = Conv2D(128, (3, 3), padding='same', use_bias=use_bias)(down1_pool)
  60. down2 = BatchNormalization()(down2)
  61. down2 = LeakyReLU(alpha=0.1)(down2)
  62. down2 = Conv2D(128, (3, 3), padding='same', use_bias=use_bias)(down2)
  63. down2 = BatchNormalization()(down2)
  64. down2 = LeakyReLU(alpha=0.1)(down2)
  65. down2_pool = MaxPooling2D((2, 2), strides=(2, 2))(down2)
  66. conv = Conv2D(256, (3, 3))(down2_pool)
  67. bn = BatchNormalization()(conv)
  68. rl = LeakyReLU(alpha=0.1)(bn)
  69. conv = Conv2D(256, (3, 3))(rl)
  70. bn = BatchNormalization()(conv)
  71. rl = LeakyReLU(alpha=0.1)(bn)
  72. dense = Dense(128, activation="relu")(rl)
  73. drop = Dropout(0.2)(dense)
  74. dense = Dense(output_shape, activation="softmax")(drop)
  75. x = Reshape((output_shape,))(dense)
  76. model = Model(_input, x)
  77. model.summary()
  78. return model
  79. def cnn_net_drag(input_shape, output_shape=260):
  80. _input = Input(input_shape)
  81. use_bias = False
  82. down0 = Conv2D(16, (3, 3), use_bias=use_bias)(_input)
  83. down0 = BatchNormalization()(down0)
  84. down0 = LeakyReLU(alpha=0.1)(down0)
  85. down0 = Conv2D(16, (3, 3), use_bias=use_bias)(down0)
  86. down0 = BatchNormalization()(down0)
  87. down0 = LeakyReLU(alpha=0.1)(down0)
  88. down0_pool = MaxPooling2D((2, 2), strides=(2, 2))(down0)
  89. down1 = Conv2D(32, (3, 3), use_bias=use_bias)(down0_pool)
  90. down1 = BatchNormalization()(down1)
  91. down1 = LeakyReLU(alpha=0.1)(down1)
  92. down1 = Conv2D(32, (3, 3), use_bias=use_bias)(down1)
  93. down1 = BatchNormalization()(down1)
  94. down1 = LeakyReLU(alpha=0.1)(down1)
  95. down1_pool = MaxPooling2D((2, 2), strides=(2, 2))(down1)
  96. down2 = Conv2D(64, (3, 3), use_bias=use_bias)(down1_pool)
  97. down2 = BatchNormalization()(down2)
  98. down2 = LeakyReLU(alpha=0.1)(down2)
  99. down2 = Conv2D(64, (3, 3), use_bias=use_bias)(down2)
  100. down2 = BatchNormalization()(down2)
  101. down2 = LeakyReLU(alpha=0.1)(down2)
  102. down2_pool = MaxPooling2D((2, 2), strides=(2, 2))(down2)
  103. down3 = Conv2D(64, (3, 3), use_bias=use_bias)(down2_pool)
  104. down3 = BatchNormalization()(down3)
  105. down3 = LeakyReLU(alpha=0.1)(down3)
  106. down3 = Conv2D(64, (3, 3), use_bias=use_bias)(down3)
  107. down3 = BatchNormalization()(down3)
  108. down3 = LeakyReLU(alpha=0.1)(down3)
  109. down3_pool = MaxPooling2D((2, 2), strides=(2, 2))(down3)
  110. gap = GlobalAveragePooling2D()(down3_pool)
  111. dense = Dense(32, activation="relu")(gap)
  112. drop = Dropout(0.2)(dense)
  113. dense = Dense(output_shape, activation="softmax")(drop)
  114. model = Model(_input, dense)
  115. model.summary()
  116. return model
  117. def u_net_drag(input_shape, output_shape=260, cls_num=2):
  118. inputs = Input(shape=input_shape)
  119. use_bias = False
  120. # 128
  121. down1 = Conv2D(16, (3, 3), padding='same', use_bias=use_bias)(inputs)
  122. down1 = BatchNormalization()(down1)
  123. down1 = LeakyReLU(alpha=0.1)(down1)
  124. down1 = Conv2D(16, (1, 1), padding='same', use_bias=use_bias)(down1)
  125. down1 = BatchNormalization()(down1)
  126. down1 = LeakyReLU(alpha=0.1)(down1)
  127. down1_pool = MaxPooling2D((2, 2), strides=(2, 2))(down1)
  128. # 64
  129. down2 = Conv2D(32, (3, 3), padding='same', use_bias=use_bias)(down1_pool)
  130. down2 = BatchNormalization()(down2)
  131. down2 = LeakyReLU(alpha=0.1)(down2)
  132. down2 = Conv2D(32, (1, 1), padding='same', use_bias=use_bias)(down2)
  133. down2 = BatchNormalization()(down2)
  134. down2 = LeakyReLU(alpha=0.1)(down2)
  135. down2_pool = MaxPooling2D((2, 2), strides=(2, 2))(down2)
  136. # 32
  137. down3 = Conv2D(64, (3, 3), padding='same', use_bias=use_bias)(down2_pool)
  138. down3 = BatchNormalization()(down3)
  139. down3 = LeakyReLU(alpha=0.1)(down3)
  140. down3 = Conv2D(64, (1, 1), padding='same', use_bias=use_bias)(down3)
  141. down3 = BatchNormalization()(down3)
  142. down3 = LeakyReLU(alpha=0.1)(down3)
  143. down3_pool = MaxPooling2D((2, 2), strides=(2, 2))(down3)
  144. # 16
  145. center = Conv2D(64, (3, 3), padding='same', use_bias=use_bias)(down3_pool)
  146. center = BatchNormalization()(center)
  147. center = LeakyReLU(alpha=0.1)(center)
  148. center = Conv2D(64, (1, 1), padding='same', use_bias=use_bias)(center)
  149. center = BatchNormalization()(center)
  150. center = LeakyReLU(alpha=0.1)(center)
  151. # 32
  152. up3 = UpSampling2D((2, 2))(center)
  153. up3 = concatenate([down3, up3], axis=3)
  154. up3 = Conv2D(64, (3, 3), padding='same', use_bias=use_bias)(up3)
  155. up3 = BatchNormalization()(up3)
  156. up3 = LeakyReLU(alpha=0.1)(up3)
  157. up3 = Conv2D(64, (1, 1), padding='same', use_bias=use_bias)(up3)
  158. up3 = BatchNormalization()(up3)
  159. up3 = LeakyReLU(alpha=0.1)(up3)
  160. # 64
  161. up2 = UpSampling2D((2, 2))(up3)
  162. up2 = concatenate([down2, up2], axis=3)
  163. up2 = Conv2D(32, (3, 3), padding='same', use_bias=use_bias)(up2)
  164. up2 = BatchNormalization()(up2)
  165. up2 = LeakyReLU(alpha=0.1)(up2)
  166. up2 = Conv2D(32, (1, 1), padding='same', use_bias=use_bias)(up2)
  167. up2 = BatchNormalization()(up2)
  168. up2 = LeakyReLU(alpha=0.1)(up2)
  169. # 128
  170. up1 = UpSampling2D((2, 2))(up2)
  171. up1 = K.concatenate([down1, up1], axis=3)
  172. up1 = Conv2D(16, (3, 3), padding='same', use_bias=use_bias)(up1)
  173. up1 = BatchNormalization()(up1)
  174. up1 = LeakyReLU(alpha=0.1)(up1)
  175. up1 = Conv2D(16, (1, 1), padding='same', use_bias=use_bias)(up1)
  176. up1 = BatchNormalization()(up1)
  177. up1 = LeakyReLU(alpha=0.1)(up1)
  178. classify = Conv2D(1, (1, 1), activation='sigmoid')(up1)
  179. # classify = Dense(cls_num, activation="softmax")(up1)
  180. model = Model(inputs=inputs, outputs=classify)
  181. model.summary(line_length=100)
  182. return model
  183. def lstm_phrase(input_shape, output_shape=1):
  184. inputs = Input(shape=input_shape[0])
  185. x = Embedding(input_shape[1]+1, 16, input_length=input_shape[0])(inputs)
  186. # x = Dropout(0.2)(x)
  187. x = Bidirectional(LSTM(32))(x)
  188. # x = Dropout(0.2)(x)
  189. x = Dense(16)(x)
  190. x = Dense(output_shape, activation="sigmoid")(x)
  191. model = Model(inputs=inputs, outputs=x)
  192. model.summary(line_length=100)
  193. return model
  194. def text_cnn_phrase(input_shape, output_shape=1):
  195. inputs = Input(shape=input_shape[0])
  196. x = Embedding(input_shape[1]+1, 50, input_length=input_shape[0])(inputs)
  197. x1 = Conv1D(64, 3, activation="relu", padding="same")(x)
  198. x1 = GlobalMaxPooling1D()(x1)
  199. x2 = Conv1D(64, 4, activation="relu", padding="same")(x)
  200. x2 = GlobalMaxPooling1D()(x2)
  201. x3 = Conv1D(64, 5, activation="relu", padding="same")(x)
  202. x3 = GlobalMaxPooling1D()(x3)
  203. x = Concatenate()([x1, x2, x3])
  204. x = Dense(output_shape, activation="sigmoid")(x)
  205. model = Model(inputs=inputs, outputs=x)
  206. model.summary(line_length=100)
  207. return model
  208. def siamese_net(input_shape, output_shape=2):
  209. input_image_1 = Input(shape=input_shape, name="input_1")
  210. input_image_2 = Input(shape=input_shape, name="input_2")
  211. input_init = Input(shape=input_shape, name="input3")
  212. model = mobile_net_v3_tiny(input_init, n_class=500)
  213. model1 = model(input_image_1)
  214. model2 = model(input_image_2)
  215. l1_distance_layer = Lambda(lambda tensors: K.square(tensors[0] - tensors[1]))
  216. l1_distance = l1_distance_layer([model1, model2])
  217. out = Dense(100, activation='relu')(l1_distance)
  218. out = Dense(output_shape, activation='softmax', name='output')(out)
  219. model = Model([input_image_1, input_image_2], out)
  220. model.summary()
  221. return model
  222. class Vgg16:
  223. def __init__(self, vgg16_npy_path="./vgg16.npy"):
  224. if vgg16_npy_path is None:
  225. # path = inspect.getfile(Vgg16)
  226. # path = os.path.abspath(os.path.join(path, os.pardir))
  227. # path = os.path.join(path, "vgg16.npy")
  228. # vgg16_npy_path = path
  229. # print(path)
  230. print("there is no vgg_16_npy!")
  231. raise
  232. self.data_dict = np.load(vgg16_npy_path, encoding='latin1', allow_pickle=True).item()
  233. print("npy file loaded")
  234. def build(self, bgr):
  235. """
  236. load variable from npy to build the VGG
  237. :param rgb: rgb image [batch, height, width, 3] values scaled [0, 1]
  238. """
  239. start_time = time.time()
  240. print("build model started")
  241. bgr_scaled = bgr * 255.0
  242. # Convert RGB to BGR
  243. # red, green, blue = tf.split(axis=3, num_or_size_splits=3, value=rgb_scaled)
  244. # print("red", red)
  245. # assert red.get_shape().as_list()[1:] == [224, 224, 1]
  246. # assert green.get_shape().as_list()[1:] == [224, 224, 1]
  247. # assert blue.get_shape().as_list()[1:] == [224, 224, 1]
  248. # bgr = tf.concat(axis=3, values=[
  249. # blue - VGG_MEAN[0],
  250. # green - VGG_MEAN[1],
  251. # red - VGG_MEAN[2],
  252. # ])
  253. # assert bgr.get_shape().as_list()[1:] == [224, 224, 3]
  254. self.conv1_1 = self.conv_layer(bgr_scaled, "conv1_1")
  255. self.conv1_2 = self.conv_layer(self.conv1_1, "conv1_2")
  256. self.pool1 = self.max_pool(self.conv1_2, 'pool1')
  257. self.conv2_1 = self.conv_layer(self.pool1, "conv2_1")
  258. self.conv2_2 = self.conv_layer(self.conv2_1, "conv2_2")
  259. self.pool2 = self.max_pool(self.conv2_2, 'pool2')
  260. self.conv3_1 = self.conv_layer(self.pool2, "conv3_1")
  261. self.conv3_2 = self.conv_layer(self.conv3_1, "conv3_2")
  262. self.conv3_3 = self.conv_layer(self.conv3_2, "conv3_3")
  263. self.pool3 = self.max_pool(self.conv3_3, 'pool3')
  264. self.conv4_1 = self.conv_layer(self.pool3, "conv4_1")
  265. self.conv4_2 = self.conv_layer(self.conv4_1, "conv4_2")
  266. self.conv4_3 = self.conv_layer(self.conv4_2, "conv4_3")
  267. self.pool4 = self.max_pool(self.conv4_3, 'pool4')
  268. self.conv5_1 = self.conv_layer(self.pool4, "conv5_1")
  269. self.conv5_2 = self.conv_layer(self.conv5_1, "conv5_2")
  270. self.conv5_3 = self.conv_layer(self.conv5_2, "conv5_3")
  271. self.pool5 = self.max_pool(self.conv5_3, 'pool5')
  272. self.fc6 = self.fc_layer(self.pool5, "fc6")
  273. # assert self.fc6.get_shape().as_list()[1:] == [4096]
  274. self.relu6 = tf.nn.relu(self.fc6)
  275. self.fc7 = self.fc_layer(self.relu6, "fc7")
  276. self.relu7 = tf.nn.relu(self.fc7)
  277. self.fc8 = self.fc_layer(self.relu7, "fc8")
  278. self.prob = tf.nn.softmax(self.fc8, name="prob")
  279. # self.data_dict = None
  280. print(("build model finished: %ds" % (time.time() - start_time)))
  281. return self.prob
  282. def avg_pool(self, bottom, name):
  283. return tf.nn.avg_pool(bottom, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME', name=name)
  284. def max_pool(self, bottom, name):
  285. return tf.nn.max_pool(bottom, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME', name=name)
  286. def conv_layer(self, bottom, name):
  287. with tf.compat.v1.variable_scope(name):
  288. filt = self.get_conv_filter(name)
  289. conv = tf.nn.conv2d(bottom, filt, [1, 1, 1, 1], padding='SAME')
  290. conv_biases = self.get_bias(name)
  291. bias = tf.nn.bias_add(conv, conv_biases)
  292. relu = tf.nn.relu(bias)
  293. return relu
  294. def fc_layer(self, bottom, name):
  295. with tf.compat.v1.variable_scope(name):
  296. shape = bottom.get_shape().as_list()
  297. dim = 1
  298. for d in shape[1:]:
  299. dim *= d
  300. x = tf.reshape(bottom, [-1, dim])
  301. weights = self.get_fc_weight(name)
  302. biases = self.get_bias(name)
  303. # Fully connected layer. Note that the '+' operation automatically
  304. # broadcasts the biases.
  305. fc = tf.nn.bias_add(tf.matmul(x, weights), biases)
  306. return fc
  307. def get_conv_filter(self, name):
  308. return tf.constant(self.data_dict[name][0], name="filter")
  309. def get_bias(self, name):
  310. return tf.constant(self.data_dict[name][1], name="biases")
  311. def get_fc_weight(self, name):
  312. return tf.constant(self.data_dict[name][0], name="weights")
  313. def my_conv(inputs, output_shape=100):
  314. x = Conv2D(64, (3, 3), padding='same')(inputs)
  315. x = BatchNormalization()(x)
  316. x = LeakyReLU(alpha=0.1)(x)
  317. x = Conv2D(64, (3, 3), padding='same')(x)
  318. x = BatchNormalization()(x)
  319. x = LeakyReLU(alpha=0.1)(x)
  320. x = MaxPooling2D((2, 2), strides=(2, 2))(x)
  321. x = Conv2D(128, (3, 3), padding='same')(x)
  322. x = BatchNormalization()(x)
  323. x = LeakyReLU(alpha=0.1)(x)
  324. x = Conv2D(128, (3, 3), padding='same')(x)
  325. x = BatchNormalization()(x)
  326. x = LeakyReLU(alpha=0.1)(x)
  327. x = MaxPooling2D((2, 2), strides=(2, 2))(x)
  328. x = Conv2D(256, (3, 3), padding='same')(x)
  329. x = BatchNormalization()(x)
  330. x = LeakyReLU(alpha=0.1)(x)
  331. x = Conv2D(256, (3, 3), padding='same')(x)
  332. x = BatchNormalization()(x)
  333. x = LeakyReLU(alpha=0.1)(x)
  334. x = MaxPooling2D((2, 2), strides=(2, 2))(x)
  335. x = Conv2D(output_shape, (1, 1), activation='relu')(x)
  336. x = MaxPooling2D((5, 5))(x)
  337. x = Reshape((output_shape,))(x)
  338. model = Model(inputs, x)
  339. return model
  340. def mobile_net_v3_tiny(inputs, n_class=1000):
  341. # inputs = Input(shape)
  342. # 224,224,3 -> 112,112,16
  343. x = conv_block(inputs, 16, (3, 3), strides=(2, 2), nl='HS')
  344. # 112,112,16 -> 56,56,16
  345. x = bottleneck(x, 16, (3, 3), up_dim=16, stride=2, sq=True, nl='RE')
  346. # 56,56,16 -> 28,28,24
  347. x = bottleneck(x, 24, (3, 3), up_dim=32, stride=2, sq=False, nl='RE')
  348. x = bottleneck(x, 24, (3, 3), up_dim=32, stride=1, sq=False, nl='RE')
  349. # 28,28,24 -> 14,14,40
  350. x = bottleneck(x, 40, (5, 5), up_dim=64, stride=2, sq=True, nl='HS')
  351. x = bottleneck(x, 40, (5, 5), up_dim=64, stride=1, sq=True, nl='HS')
  352. # 14,14,40 -> 14,14,48
  353. x = bottleneck(x, 48, (5, 5), up_dim=128, stride=1, sq=True, nl='HS')
  354. x = bottleneck(x, 48, (5, 5), up_dim=128, stride=1, sq=True, nl='HS')
  355. x = conv_block(x, 256, (1, 1), strides=(1, 1), nl='HS')
  356. x = GlobalAveragePooling2D()(x)
  357. x = Reshape((1, 1, 256))(x)
  358. x = Conv2D(256, (1, 1), padding='same')(x)
  359. x = return_activation(x, 'HS')
  360. x = Conv2D(n_class, (1, 1), padding='same', activation='relu')(x)
  361. x = Reshape((n_class,))(x)
  362. model = Model(inputs, x)
  363. return model
  364. class MobileNetBase:
  365. def __init__(self, shape, n_class, alpha=1.0):
  366. """Init
  367. # Arguments
  368. input_shape: An integer or tuple/list of 3 integers, shape
  369. of input tensor.
  370. n_class: Integer, number of classes.
  371. alpha: Integer, width multiplier.
  372. """
  373. self.shape = shape
  374. self.n_class = n_class
  375. self.alpha = alpha
  376. def _relu6(self, x):
  377. """Relu 6
  378. """
  379. return K.relu(x, max_value=6.0)
  380. def _hard_swish(self, x):
  381. """Hard swish
  382. """
  383. return x * K.relu(x + 3.0, max_value=6.0) / 6.0
  384. def _return_activation(self, x, nl):
  385. """Convolution Block
  386. This function defines a activation choice.
  387. # Arguments
  388. x: Tensor, input tensor of conv layer.
  389. nl: String, nonlinearity activation type.
  390. # Returns
  391. Output tensor.
  392. """
  393. if nl == 'HS':
  394. x = Activation(self._hard_swish)(x)
  395. if nl == 'RE':
  396. x = Activation(self._relu6)(x)
  397. return x
  398. def _conv_block(self, inputs, filters, kernel, strides, nl):
  399. """Convolution Block
  400. This function defines a 2D convolution operation with BN and activation.
  401. # Arguments
  402. inputs: Tensor, input tensor of conv layer.
  403. filters: Integer, the dimensionality of the output space.
  404. kernel: An integer or tuple/list of 2 integers, specifying the
  405. width and height of the 2D convolution window.
  406. strides: An integer or tuple/list of 2 integers,
  407. specifying the strides of the convolution along the width and height.
  408. Can be a single integer to specify the same value for
  409. all spatial dimensions.
  410. nl: String, nonlinearity activation type.
  411. # Returns
  412. Output tensor.
  413. """
  414. channel_axis = 1 if K.image_data_format() == 'channels_first' else -1
  415. x = Conv2D(filters, kernel, padding='same', strides=strides)(inputs)
  416. x = BatchNormalization(axis=channel_axis)(x)
  417. return self._return_activation(x, nl)
  418. def _squeeze(self, inputs):
  419. """Squeeze and Excitation.
  420. This function defines a squeeze structure.
  421. # Arguments
  422. inputs: Tensor, input tensor of conv layer.
  423. """
  424. input_channels = int(inputs.shape[-1])
  425. x = GlobalAveragePooling2D()(inputs)
  426. x = Dense(input_channels, activation='relu')(x)
  427. x = Dense(input_channels, activation='hard_sigmoid')(x)
  428. x = Reshape((1, 1, input_channels))(x)
  429. x = Multiply()([inputs, x])
  430. return x
  431. def _bottleneck(self, inputs, filters, kernel, e, s, squeeze, nl):
  432. """Bottleneck
  433. This function defines a basic bottleneck structure.
  434. # Arguments
  435. inputs: Tensor, input tensor of conv layer.
  436. filters: Integer, the dimensionality of the output space.
  437. kernel: An integer or tuple/list of 2 integers, specifying the
  438. width and height of the 2D convolution window.
  439. e: Integer, expansion factor.
  440. t is always applied to the input size.
  441. s: An integer or tuple/list of 2 integers,specifying the strides
  442. of the convolution along the width and height.Can be a single
  443. integer to specify the same value for all spatial dimensions.
  444. squeeze: Boolean, Whether to use the squeeze.
  445. nl: String, nonlinearity activation type.
  446. # Returns
  447. Output tensor.
  448. """
  449. channel_axis = 1 if K.image_data_format() == 'channels_first' else -1
  450. input_shape = K.int_shape(inputs)
  451. tchannel = int(e)
  452. cchannel = int(self.alpha * filters)
  453. r = s == 1 and input_shape[3] == filters
  454. x = self._conv_block(inputs, tchannel, (1, 1), (1, 1), nl)
  455. x = DepthwiseConv2D(kernel, strides=(s, s), depth_multiplier=1, padding='same')(x)
  456. x = BatchNormalization(axis=channel_axis)(x)
  457. x = self._return_activation(x, nl)
  458. if squeeze:
  459. x = self._squeeze(x)
  460. x = Conv2D(cchannel, (1, 1), strides=(1, 1), padding='same')(x)
  461. x = BatchNormalization(axis=channel_axis)(x)
  462. if r:
  463. x = Add()([x, inputs])
  464. return x
  465. def build(self):
  466. pass
  467. class MobileNetV3Small(MobileNetBase):
  468. def __init__(self, shape, n_class, alpha=1.0, include_top=True):
  469. """Init.
  470. # Arguments
  471. input_shape: An integer or tuple/list of 3 integers, shape
  472. of input tensor.
  473. n_class: Integer, number of classes.
  474. alpha: Integer, width multiplier.
  475. include_top: if inculde classification layer.
  476. # Returns
  477. MobileNetv3 model.
  478. """
  479. super(MobileNetV3Small, self).__init__(shape, n_class, alpha)
  480. self.include_top = include_top
  481. def build(self):
  482. """build MobileNetV3 Small.
  483. # Arguments
  484. plot: Boolean, weather to plot model.
  485. # Returns
  486. model: Model, model.
  487. """
  488. inputs = Input(shape=self.shape)
  489. x = self._conv_block(inputs, 16, (3, 3), strides=(2, 2), nl='HS')
  490. x = self._bottleneck(x, 16, (3, 3), e=16, s=2, squeeze=True, nl='RE')
  491. x = self._bottleneck(x, 24, (3, 3), e=72, s=2, squeeze=False, nl='RE')
  492. x = self._bottleneck(x, 24, (3, 3), e=88, s=1, squeeze=False, nl='RE')
  493. x = self._bottleneck(x, 40, (5, 5), e=96, s=2, squeeze=True, nl='HS')
  494. x = self._bottleneck(x, 40, (5, 5), e=240, s=1, squeeze=True, nl='HS')
  495. x = self._bottleneck(x, 40, (5, 5), e=240, s=1, squeeze=True, nl='HS')
  496. x = self._bottleneck(x, 48, (5, 5), e=120, s=1, squeeze=True, nl='HS')
  497. x = self._bottleneck(x, 48, (5, 5), e=144, s=1, squeeze=True, nl='HS')
  498. x = self._bottleneck(x, 96, (5, 5), e=288, s=2, squeeze=True, nl='HS')
  499. x = self._bottleneck(x, 96, (5, 5), e=576, s=1, squeeze=True, nl='HS')
  500. x = self._bottleneck(x, 96, (5, 5), e=576, s=1, squeeze=True, nl='HS')
  501. x = self._conv_block(x, 576, (1, 1), strides=(1, 1), nl='HS')
  502. x = GlobalAveragePooling2D()(x)
  503. x = Reshape((1, 1, 576))(x)
  504. x = Conv2D(1280, (1, 1), padding='same')(x)
  505. x = self._return_activation(x, 'HS')
  506. if self.include_top:
  507. x = Conv2D(self.n_class, (1, 1), padding='same', activation='softmax')(x)
  508. x = Reshape((self.n_class,))(x)
  509. model = Model(inputs, x)
  510. return model
  511. def bottleneck(inputs, filters, kernel, up_dim, stride, sq, nl):
  512. channel_axis = 1 if K.image_data_format() == 'channels_first' else -1
  513. input_shape = K.int_shape(inputs)
  514. tchannel = int(up_dim)
  515. alpha = 1
  516. cchannel = int(alpha * filters)
  517. r = stride == 1 and input_shape[3] == filters
  518. # 1x1卷积调整通道数,通道数上升
  519. x = conv_block(inputs, tchannel, (1, 1), (1, 1), nl)
  520. # 进行3x3深度可分离卷积
  521. x = DepthwiseConv2D(kernel, strides=(stride, stride), depth_multiplier=1, padding='same')(x)
  522. x = BatchNormalization(axis=channel_axis)(x)
  523. x = return_activation(x, nl)
  524. # 引入注意力机制
  525. if sq:
  526. x = squeeze(x)
  527. # 下降通道数
  528. x = Conv2D(cchannel, (1, 1), strides=(1, 1), padding='same')(x)
  529. x = BatchNormalization(axis=channel_axis)(x)
  530. if r:
  531. x = Add()([x, inputs])
  532. return x
  533. def squeeze(inputs):
  534. # 注意力机制单元
  535. input_channels = int(inputs.shape[-1])
  536. x = GlobalAveragePooling2D()(inputs)
  537. x = Dense(int(input_channels/4))(x)
  538. x = Activation(relu6)(x)
  539. x = Dense(input_channels)(x)
  540. x = Activation(hard_swish)(x)
  541. x = Reshape((1, 1, input_channels))(x)
  542. x = Multiply()([inputs, x])
  543. return x
  544. def conv_block(inputs, filters, kernel, strides, nl):
  545. # 一个卷积单元,也就是conv2d + batchnormalization + activation
  546. channel_axis = 1 if K.image_data_format() == 'channels_first' else -1
  547. x = Conv2D(filters, kernel, padding='same', strides=strides)(inputs)
  548. x = BatchNormalization(axis=channel_axis)(x)
  549. return return_activation(x, nl)
  550. def return_activation(x, nl):
  551. # 用于判断使用哪个激活函数
  552. if nl == 'HS':
  553. x = Activation(hard_swish)(x)
  554. if nl == 'RE':
  555. x = Activation(relu6)(x)
  556. return x
  557. def relu6(x):
  558. # relu函数
  559. return K.relu(x, max_value=6.0)
  560. def hard_swish(x):
  561. # 利用relu函数乘上x模拟sigmoid
  562. return x * K.relu(x + 3.0, max_value=6.0) / 6.0
  563. def tiny_yolo_body(inputs, num_anchors, num_classes):
  564. """Create Tiny YOLO_v3 model CNN body in keras."""
  565. x1 = compose(
  566. DarknetConv2D_BN_Leaky(16, (3, 3), ),
  567. MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'),
  568. DarknetConv2D_BN_Leaky(32, (3, 3)),
  569. MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'),
  570. DarknetConv2D_BN_Leaky(64, (3, 3)),
  571. MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'),
  572. DarknetConv2D_BN_Leaky(128, (3, 3)),
  573. MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'),
  574. DarknetConv2D_BN_Leaky(256, (3, 3)))(inputs)
  575. x2 = compose(
  576. MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'),
  577. DarknetConv2D_BN_Leaky(512, (3, 3)),
  578. MaxPooling2D(pool_size=(2, 2), strides=(1, 1), padding='same'),
  579. DarknetConv2D_BN_Leaky(1024, (3, 3)),
  580. DarknetConv2D_BN_Leaky(256, (1, 1)))(x1)
  581. y1 = compose(
  582. DarknetConv2D_BN_Leaky(512, (3, 3)),
  583. DarknetConv2D(num_anchors*(num_classes+5), (1, 1)))(x2)
  584. x2 = compose(
  585. DarknetConv2D_BN_Leaky(128, (1, 1)),
  586. UpSampling2D(2))(x2)
  587. y2 = compose(
  588. Concatenate(),
  589. DarknetConv2D_BN_Leaky(256, (3, 3)),
  590. DarknetConv2D(num_anchors*(num_classes+5), (1, 1)))([x2, x1])
  591. return Model(inputs, [y1, y2])
  592. @wraps(Conv2D)
  593. def DarknetConv2D(*args, **kwargs):
  594. """Wrapper to set Darknet parameters for Convolution2D."""
  595. darknet_conv_kwargs = {'kernel_regularizer': l2(5e-4),
  596. 'padding': 'valid' if kwargs.get('strides') == (2, 2) else 'same'}
  597. darknet_conv_kwargs.update(kwargs)
  598. return Conv2D(*args, **darknet_conv_kwargs)
  599. def DarknetConv2D_BN_Leaky(*args, **kwargs):
  600. """Darknet Convolution2D followed by BatchNormalization and LeakyReLU."""
  601. no_bias_kwargs = {'use_bias': False}
  602. no_bias_kwargs.update(kwargs)
  603. return compose(
  604. DarknetConv2D(*args, **no_bias_kwargs),
  605. BatchNormalization(),
  606. LeakyReLU(alpha=0.1))
  607. if __name__ == "__main__":
  608. text_cnn_phrase((3, 5792))
  609. print(math.log(5792, 2))