Pour construire un CNN dans Theano, j'ai fait des recherches sur la fonction de convolution bidimensionnelle de Theano theano.tensor.nnet.conv () ''. Par rapport à la fonction de convolution à N dimensions
scipy.signal.fftconvolve () '', qui est probablement couramment utilisée dans le traitement du signal.
Tout d'abord, essayons de convoluer de simples tableaux bidimensionnels.
import theano
import theano.tensor as T
import theano.tensor.signal as signal
import scipy.signal as s
m = T.matrix()
w = T.matrix()
#Doit être de rang 4.
o_full = nnet.conv.conv2d(m[None,None,:,:], w[None, None,:,:],
border_mode='full')
o_valid = nnet.conv.conv2d(m[None,None,:,:], w[None, None,:,:],
border_mode='valid')
m_arr = arange(25.).reshape((5,5)).astype(float32)
w_arr = ones((3,3)).astype(float32)
print("m_arr =")
print(m_arr)
print("w_arr =")
print(w_arr)
print("Output for Theano.")
print("full:")
print(o_full.eval({m:m_arr, w:w_arr}).round().astype(int))
print("valid:")
print(o_valid.eval({m:m_arr, w:w_arr}).round().astype(int))
print("Output for scipy.")
print("full:")
print(s.fftconvolve(m_arr, w_arr, "full").round().astype(int))
print("valid:")
print(s.fftconvolve(m_arr, w_arr, "valid").round().astype(int))
Tableau alambiquém_arr
Fonction de fenêtre à plier avec(ou noyau ou filtre)w_arr
Àtheano.tensor.nnet.conv.conv2d()Quand
scipy.signal.fftconvolve()```
Il coule vers chacun. ici,
# Doit être de rang 4.
o_full = nnet.conv.conv2d(m[None,None,:,:], w[None, None,:,:],
border_mode='full')
o_valid = nnet.conv.conv2d(m[None,None,:,:], w[None, None,:,:],
border_mode='valid')
comme,m[None,None,:,:], w[None, None,:,:]
Le format de l'entrée et du tableau du noyau est[Nombre d'images, nombre de canaux, hauteur, largeur]
Parce que c'est.m,w
Est le rang 2T.matrix()
Parce qu'il a été défini comme[None, None,:,:]
En faisant comme, nous avons augmenté le premier rang de deux.Cette diffusion est la même que celle de NumpyC'est donc très facile à utiliser personnellement.
La sortie ressemble à ceci:
m_arr =
[[ 0. 1. 2. 3. 4.]
[ 5. 6. 7. 8. 9.]
[ 10. 11. 12. 13. 14.]
[ 15. 16. 17. 18. 19.]
[ 20. 21. 22. 23. 24.]]
w_arr =
[[ 1. 1. 1.]
[ 1. 1. 1.]
[ 1. 1. 1.]]
Output for Theano.
full:
[[[[ 0 1 3 6 9 7 4]
[ 5 12 21 27 33 24 13]
[ 15 33 54 63 72 51 27]
[ 30 63 99 108 117 81 42]
[ 45 93 144 153 162 111 57]
[ 35 72 111 117 123 84 43]
[ 20 41 63 66 69 47 24]]]]
valid:
[[[[ 54 63 72]
[ 99 108 117]
[144 153 162]]]]
Output for scipy.
full:
[[ 0 1 3 6 9 7 4]
[ 5 12 21 27 33 24 13]
[ 15 33 54 63 72 51 27]
[ 30 63 99 108 117 81 42]
[ 45 93 144 153 162 111 57]
[ 35 72 111 117 123 84 43]
[ 20 41 63 66 69 47 24]]
valid:
[[ 54 63 72]
[ 99 108 117]
[144 153 162]]
La sortie de la convolution est arrondie pour une visualisation facile, puis convertie en int.
theano.tensor.nnet.conv()Puis frontière_Il y avait un argument appelé mode. Vous pouvez sélectionner complet ou valide pour cela. Le pliage prend la somme en multipliant l'image tout en déplaçant le filtre, mais plein est un mode qui inclut le résultat dans l'état où au moins un des éléments chevauche l'image même si le filtre dépasse de l'image, valide est Ce mode produit uniquement le résultat lorsque le filtre ne s'étend pas au-delà de l'image. Image d'un certain axe et taille de filtre respectivement$M,m$À ce moment-là, la taille de l'axe avec le tableau de sortie est pleine$M+(m-1)$, Valide$M-(m-1)$Sera. Hauteur dans l'exemple ci-dessus(ou largeur)Mais$M=5,m=3$Par conséquent, il est 7 lorsqu'il est plein et 3 lorsqu'il est valide.
Lorsque vous vérifiez la sortie,```theano.tensor.nnet.conv()```Quand```scipy.signal.fftconvolve()```alors(Sauf pour le rang du tableau)等しいこQuandが確認alorsきます。
Cependant, les deux sorties ont des significations différentes.```scipy.signal.fftconvolve()```Renvoie le résultat d'une pure convolution à N dimensions, alors que```theano.tensor.nnet.conv()```Renvoie le résultat de la convolution pour chaque nombre d'images et chaque filtre. Le tableau de sortie est```[Nombre d'images, nombre de fichiers, hauteur, largeur]```est. De plus, comme cela sera décrit plus loin```theano.tensor.nnet.conv()```Doit avoir le même nombre de canaux pour l'image et le filtre.
#Convolution lors de l'ajout des dimensions du nombre d'images et du nombre de canaux
Ensuite, nous allons effectuer une convolution qui ajoute les dimensions du nombre d'images et le nombre de canaux. Pliez un filtre 3x3 avec 1 image et 3 canaux pour une image 5x5 avec 2 images et 3 canaux. Le programme ressemble à ceci:
```python
m = T.tensor4()
w = T.tensor4()
# Doit être de rang 4.
o_full = nnet.conv.conv2d(m, w,
border_mode='full')
o_valid = nnet.conv.conv2d(m, w,
border_mode='valid')
m_arr = arange(2*3*5*5).reshape((2, 3, 5, 5)).astype(float32)
w_arr = ones((1,3,3,3)).astype(float32)
print("m_arr =")
print(m_arr)
print("w_arr =")
print(w_arr)
print("Output for Theano.")
print("full:")
print(o_full.eval({m:m_arr, w:w_arr}).round().astype(int))
print("valid:")
print(o_valid.eval({m:m_arr, w:w_arr}).round().astype(int))
print("Output for scipy.")
print("full:")
print(s.fftconvolve(m_arr, w_arr, "full").round().astype(int))
print("valid:")
print(s.fftconvolve(m_arr, w_arr, "valid").round().astype(int))
Pour définir un tenseur de rang 4m
Quandw
ÀT.tensor4()
Est réglé.
m_arr =
[[[[ 0. 1. 2. 3. 4.]
[ 5. 6. 7. 8. 9.]
[ 10. 11. 12. 13. 14.]
[ 15. 16. 17. 18. 19.]
[ 20. 21. 22. 23. 24.]]
[[ 25. 26. 27. 28. 29.]
[ 30. 31. 32. 33. 34.]
[ 35. 36. 37. 38. 39.]
[ 40. 41. 42. 43. 44.]
[ 45. 46. 47. 48. 49.]]
[[ 50. 51. 52. 53. 54.]
[ 55. 56. 57. 58. 59.]
[ 60. 61. 62. 63. 64.]
[ 65. 66. 67. 68. 69.]
[ 70. 71. 72. 73. 74.]]]
[[[ 75. 76. 77. 78. 79.]
[ 80. 81. 82. 83. 84.]
[ 85. 86. 87. 88. 89.]
[ 90. 91. 92. 93. 94.]
[ 95. 96. 97. 98. 99.]]
[[ 100. 101. 102. 103. 104.]
[ 105. 106. 107. 108. 109.]
[ 110. 111. 112. 113. 114.]
[ 115. 116. 117. 118. 119.]
[ 120. 121. 122. 123. 124.]]
[[ 125. 126. 127. 128. 129.]
[ 130. 131. 132. 133. 134.]
[ 135. 136. 137. 138. 139.]
[ 140. 141. 142. 143. 144.]
[ 145. 146. 147. 148. 149.]]]]
w_arr =
[[[[ 1. 1. 1.]
[ 1. 1. 1.]
[ 1. 1. 1.]]
[[ 1. 1. 1.]
[ 1. 1. 1.]
[ 1. 1. 1.]]
[[ 1. 1. 1.]
[ 1. 1. 1.]
[ 1. 1. 1.]]]]
Output for Theano.
full:
[[[[ 75 153 234 243 252 171 87]
[ 165 336 513 531 549 372 189]
[ 270 549 837 864 891 603 306]
[ 315 639 972 999 1026 693 351]
[ 360 729 1107 1134 1161 783 396]
[ 255 516 783 801 819 552 279]
[ 135 273 414 423 432 291 147]]]
[[[ 300 603 909 918 927 621 312]
[ 615 1236 1863 1881 1899 1272 639]
[ 945 1899 2862 2889 2916 1953 981]
[ 990 1989 2997 3024 3051 2043 1026]
[1035 2079 3132 3159 3186 2133 1071]
[ 705 1416 2133 2151 2169 1452 729]
[ 360 723 1089 1098 1107 741 372]]]]
valid:
[[[[ 837 864 891]
[ 972 999 1026]
[1107 1134 1161]]]
[[[2862 2889 2916]
[2997 3024 3051]
[3132 3159 3186]]]]
Output for scipy.
full:
[[[[ 0 1 3 6 9 7 4]
[ 5 12 21 27 33 24 13]
[ 15 33 54 63 72 51 27]
[ 30 63 99 108 117 81 42]
[ 45 93 144 153 162 111 57]
[ 35 72 111 117 123 84 43]
[ 20 41 63 66 69 47 24]]
[[ 25 52 81 87 93 64 33]
[ 60 124 192 204 216 148 76]
[ 105 216 333 351 369 252 129]
[ 135 276 423 441 459 312 159]
[ 165 336 513 531 549 372 189]
[ 120 244 372 384 396 268 136]
[ 65 132 201 207 213 144 73]]
[[ 75 153 234 243 252 171 87]
[ 165 336 513 531 549 372 189]
[ 270 549 837 864 891 603 306]
[ 315 639 972 999 1026 693 351]
[ 360 729 1107 1134 1161 783 396]
[ 255 516 783 801 819 552 279]
[ 135 273 414 423 432 291 147]]
[[ 75 152 231 237 243 164 83]
[ 160 324 492 504 516 348 176]
[ 255 516 783 801 819 552 279]
[ 285 576 873 891 909 612 309]
[ 315 636 963 981 999 672 339]
[ 220 444 672 684 696 468 236]
[ 115 232 351 357 363 244 123]]
[[ 50 101 153 156 159 107 54]
[ 105 212 321 327 333 224 113]
[ 165 333 504 513 522 351 177]
[ 180 363 549 558 567 381 192]
[ 195 393 594 603 612 411 207]
[ 135 272 411 417 423 284 143]
[ 70 141 213 216 219 147 74]]]
[[[ 75 151 228 231 234 157 79]
[ 155 312 471 477 483 324 163]
[ 240 483 729 738 747 501 252]
[ 255 513 774 783 792 531 267]
[ 270 543 819 828 837 561 282]
[ 185 372 561 567 573 384 193]
[ 95 191 288 291 294 197 99]]
[[ 175 352 531 537 543 364 183]
[ 360 724 1092 1104 1116 748 376]
[ 555 1116 1683 1701 1719 1152 579]
[ 585 1176 1773 1791 1809 1212 609]
[ 615 1236 1863 1881 1899 1272 639]
[ 420 844 1272 1284 1296 868 436]
[ 215 432 651 657 663 444 223]]
[[ 300 603 909 918 927 621 312]
[ 615 1236 1863 1881 1899 1272 639]
[ 945 1899 2862 2889 2916 1953 981]
[ 990 1989 2997 3024 3051 2043 1026]
[1035 2079 3132 3159 3186 2133 1071]
[ 705 1416 2133 2151 2169 1452 729]
[ 360 723 1089 1098 1107 741 372]]
[[ 225 452 681 687 693 464 233]
[ 460 924 1392 1404 1416 948 476]
[ 705 1416 2133 2151 2169 1452 729]
[ 735 1476 2223 2241 2259 1512 759]
[ 765 1536 2313 2331 2349 1572 789]
[ 520 1044 1572 1584 1596 1068 536]
[ 265 532 801 807 813 544 273]]
[[ 125 251 378 381 384 257 129]
[ 255 512 771 777 783 524 263]
[ 390 783 1179 1188 1197 801 402]
[ 405 813 1224 1233 1242 831 417]
[ 420 843 1269 1278 1287 861 432]
[ 285 572 861 867 873 584 293]
[ 145 291 438 441 444 297 149]]]]
valid:
[[[[ 837 864 891]
[ 972 999 1026]
[1107 1134 1161]]]
[[[2862 2889 2916]
[2997 3024 3051]
[3132 3159 3186]]]]
C'est long et difficile à comparer,valid
C'est pareil, maisfull
Les résultats sont différents entre les deux. Alors, regardons la forme du tableau après la sortie.
print("Output for Theano.")
print("full:")
print(o_full.eval({m:m_arr, w:w_arr}).round().astype(int).shape)
print("valid:")
print(o_valid.eval({m:m_arr, w:w_arr}).round().astype(int).shape)
print("Output for scipy.")
print("full:")
print(s.fftconvolve(m_arr, w_arr, "full").round().astype(int).shape)
print("valid:")
print(s.fftconvolve(m_arr, w_arr, "valid").round().astype(int).shape)
Output for Theano.
full:
(2, 1, 7, 7)
valid:
(2, 1, 3, 3)
Output for scipy.
full:
(2, 5, 7, 7)
valid:
(2, 1, 3, 3)
c'est,scipy.signal.fftconvolve()
On effectue également l'opération de pliage sur les axes du nombre d'images et du nombre de canaux.theano.tensor.nnet.conv()
Cela est dû au fait que seules les dimensions de largeur et de hauteur de l'image sont utilisées et que le nombre d'images et le nombre de canaux sont traités indépendamment. Ettheano.tensor.nnet.conv()
La sortie de[Nombre d'images, nombre de filtres, hauteur, largeur]
La deuxième forme est donc 1. Aussi,theano.tensor.nnet.conv()
Il est nécessaire de faire correspondre le nombre de canaux avec l'image et le filtre comme décrit ci-dessus. Par exemple
m_arr = arange(2*3*5*5).reshape((2, 3, 5, 5)).astype(float32)
w_arr = ones((1,1,3,3)).astype(float32)
Lorsque le nombre de canaux de l'image est de 3 et le nombre de canaux du filtre est de 1, comme danstheano.tensor.nnet.conv()
Affiche l'erreur suivante.
ValueError: GpuDnnConv images and kernel must have the same stack size
cependant,scipy.signal.fftconvolve()
Ensuite, la forme du tableau est
Output for scipy.
full:
(2, 3, 7, 7)
valid:
(2, 3, 3, 3)
Renvoie le résultat de.full
Puisvalid
Puis
Enfin, essayez avec 2 images, 3 filtres et 1 canal. Nous avons également réduit le nombre d'éléments dans le tableau.
m = T.tensor4()
w = T.tensor4()
# Doit être de rang 4.
o_full = nnet.conv.conv2d(m, w,
border_mode='full')
o_valid = nnet.conv.conv2d(m, w,
border_mode='valid')
m_arr = arange(2*1*3*3).reshape((2, 1, 3, 3)).astype(float32)
w_arr = ones((3,1,1,1)).astype(float32)
print("m_arr =")
print(m_arr)
print("w_arr =")
print(w_arr)
print("Output for Theano.")
print("full:")
print(o_full.eval({m:m_arr, w:w_arr}).round().astype(int))
print("valid:")
print(o_valid.eval({m:m_arr, w:w_arr}).round().astype(int))
print("Output for scipy.")
print("full:")
print(s.fftconvolve(m_arr, w_arr, "full").round().astype(int))
print("valid:")
print(s.fftconvolve(m_arr, w_arr, "valid").round().astype(int))
m_arr =
[[[[ 0. 1. 2.]
[ 3. 4. 5.]
[ 6. 7. 8.]]]
[[[ 9. 10. 11.]
[ 12. 13. 14.]
[ 15. 16. 17.]]]]
w_arr =
[[[[ 1.]]]
[[[ 1.]]]
[[[ 1.]]]]
Output for Theano.
full:
[[[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]]
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]]
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]]]
[[[ 9 10 11]
[12 13 14]
[15 16 17]]
[[ 9 10 11]
[12 13 14]
[15 16 17]]
[[ 9 10 11]
[12 13 14]
[15 16 17]]]]
valid:
[[[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]]
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]]
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]]]
[[[ 9 10 11]
[12 13 14]
[15 16 17]]
[[ 9 10 11]
[12 13 14]
[15 16 17]]
[[ 9 10 11]
[12 13 14]
[15 16 17]]]]
Output for scipy.
full:
[[[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]]]
[[[ 9 11 13]
[15 17 19]
[21 23 25]]]
[[[ 9 11 13]
[15 17 19]
[21 23 25]]]
[[[ 9 10 11]
[12 13 14]
[15 16 17]]]]
valid:
ValueError: For 'valid' mode, one must be at least as large as the other in every dimension
scipy.signal.fftconvolve()devalid
A entraîné une erreur.valid
de場合、画像とフィルタdeいずれかが片方よりもすべてde次元で大きくないといけないようです。
La forme du tableau est la suivante.
Output for Theano.
full:
(2, 3, 3, 3)
valid:
(2, 3, 3, 3)
Output for scipy.
full:
(4, 1, 3, 3)
valid:
theano.tensor.nnet.conv()
Est 1 de forme,Le second est le nombre d'images et le nombre de filtres, respectivement, et le restefull
Puisvalid
Puisscipy.signal.fftconvolve()
Pour tous les axesfull
Puis
#foulée