├── LICENSE ├── README.md ├── appendix ├── broad_1.py ├── broad_2.py ├── concat_1.py ├── concat_2.py ├── cumsum_1.py ├── enum_1.py ├── max_1.py ├── max_2.py ├── mult_1.py ├── mult_2.py ├── numpy_1.py ├── numpy_2.py ├── rand_1.py ├── rand_2.py ├── rand_3.py ├── rand_4.py ├── rand_5.py ├── rand_6.py ├── rand_7.py ├── rand_8.py ├── rand_9.py ├── reshape_1.py ├── searchsorted_1.py ├── slice_1.py ├── slice_2.py ├── trans_1.py ├── trans_2.py └── zip_1.py ├── chapter05 └── Q3_ans.py ├── chapter07 └── Q3_ans.py ├── chapter08 ├── Q2_ans.py ├── Q3_ans.py └── Q5_ans.py ├── chapter11 ├── Q2_ans.py ├── Q3_ans.py ├── Q4_ans.py └── common │ └── functions.py ├── chapter12 ├── Q1_ans.py └── Q3_ans.py ├── chapter13 └── Q2_ans.py ├── chapter14 ├── Q2_ans.py ├── Q4_ans.py └── Q8_ans.py ├── chapter15 ├── Q3_ans.py └── layers.py └── chapter19 ├── Q12.py ├── Q13.py ├── Q17.py ├── Q22.py ├── Q8.py └── my_functions.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Skillupai 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 徹底攻略 ディープラーニングE資格エンジニア問題集 2 | 3 | [徹底攻略 ディープラーニングE資格エンジニア問題集](https://book.impress.co.jp/books/1118101176)の問題文中に登場するソースコードのリポジトリです。 4 | 誤記に関しては、[こちら](https://book.impress.co.jp/books/1118101176)で管理しています。 5 | -------------------------------------------------------------------------------- /appendix/broad_1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | x = np.array([1, 3, 5]) 4 | y = 2 5 | 6 | print(x + y) 7 | 8 | ''' 9 | [3 5 7] 10 | ''' -------------------------------------------------------------------------------- /appendix/broad_2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | x = np.array([[1, 3, 5], [2, 4, 6]]) #二次元 array とスカラーの和 4 | y = 2 5 | 6 | print(x + y) 7 | 8 | ''' 9 | [[3 5 7] 10 | [4 6 8]] 11 | ''' 12 | 13 | x = np.array([[1, 3, 5], [2, 4, 6]]) #二次元 array と一次元 array の和 14 | y = np.array([10, 20, 30]) 15 | 16 | print(x + y) 17 | 18 | ''' 19 | [[11 23 35] 20 | [12 24 36]] 21 | ''' -------------------------------------------------------------------------------- /appendix/concat_1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | a = np.array([[0, 1, 2, 3], 4 | [4, 5, 6, 7], 5 | [8, 9, 10, 11]]) 6 | b = np.array([[10, 11, 12, 13], 7 | [14, 15, 16, 17], 8 | [18, 19, 20, 21]]) 9 | 10 | print(np.concatenate([a, b], axis=0)) # 垂直方向に結合 11 | 12 | ''' 13 | [[ 0 1 2 3] 14 | [ 4 5 6 7] 15 | [ 8 9 10 11] 16 | [10 11 12 13] 17 | [14 15 16 17] 18 | [18 19 20 21]] 19 | ''' 20 | 21 | print(np.concatenate([a, b], axis=1)) # 水平方向に結合 22 | 23 | ''' 24 | [[ 0 1 2 3 10 11 12 13] 25 | [ 4 5 6 7 14 15 16 17] 26 | [ 8 9 10 11 18 19 20 21]] 27 | ''' -------------------------------------------------------------------------------- /appendix/concat_2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | a = np.array([[0, 1, 2, 3], 4 | [4, 5, 6, 7], 5 | [8, 9, 10, 11]]) 6 | b = np.array([[10, 11, 12, 13], 7 | [14, 15, 16, 17], 8 | [18, 19, 20, 21]]) 9 | 10 | print(np.stack([a, b])) # 新たな軸の方向に結合 11 | 12 | ''' 13 | [[[ 0 1 2 3] 14 | [ 4 5 6 7] 15 | [ 8 9 10 11]] 16 | 17 | [[10 11 12 13] 18 | [14 15 16 17] 19 | [18 19 20 21]]] 20 | ''' 21 | 22 | print(np.vstack([a, b])) # 垂直方向に結合 23 | 24 | ''' 25 | [[[ 0 1 2 3] 26 | [ 4 5 6 7] 27 | [ 8 9 10 11] 28 | [10 11 12 13] 29 | [14 15 16 17] 30 | [18 19 20 21]] 31 | ''' 32 | 33 | print(np.hstack([a, b])) # 水平方向に結合 34 | 35 | ''' 36 | [[ 0 1 2 3 10 11 12 13] 37 | [ 4 5 6 7 14 15 16 17] 38 | [ 8 9 10 11 18 19 20 21]] 39 | ''' -------------------------------------------------------------------------------- /appendix/cumsum_1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | a = np.array([[0, 1, 2, 3], 4 | [4, 5, 6, 7], 5 | [8, 9, 10, 11]]) 6 | 7 | print(np.cumsum(a)) # 1 次元 array に変換してから累積和を計算 8 | 9 | ''' 10 | [ 0 1 3 6 10 15 21 28 36 45 55 66] 11 | ''' 12 | 13 | print(np.cumsum(a, axis=0)) # 縦方向に累積和を計算 14 | 15 | ''' 16 | [[ 0 1 2 3] 17 | [ 4 6 8 10] 18 | [12 15 18 21]] 19 | ''' 20 | 21 | print(np.cumsum(a, axis=1)) # 横方向に累積和を計算 22 | 23 | ''' 24 | [[ 0 1 3 6] 25 | [ 4 9 15 22] 26 | [ 8 17 27 38]] 27 | ''' 28 | -------------------------------------------------------------------------------- /appendix/enum_1.py: -------------------------------------------------------------------------------- 1 | list_1 = ["a", "b", "c", "d"] 2 | 3 | for i, foo in enumerate(list_1): 4 | print(f"{i}, {foo}") 5 | 6 | ''' 7 | 0, a 8 | 1, b 9 | 2, c 10 | 3, d 11 | ''' -------------------------------------------------------------------------------- /appendix/max_1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | a = np.array([[1, 3, 5, 7, 9, 11, 13], 4 | [2, 4, 6, 8, 10, 12, 14], 5 | [3, 5, 7, 9, 11, 13, 15], 6 | [2, 4, 6, 8, 10, 12, 14], 7 | [1, 3, 5, 7, 9, 11, 13]]) 8 | 9 | print(np.max(a)) #最大値 10 | 11 | ''' 12 | 15 13 | ''' 14 | 15 | print(np.amax(a)) #最大値 16 | 17 | ''' 18 | 15 19 | ''' 20 | 21 | print(a.max()) #最大値 22 | 23 | ''' 24 | 15 25 | ''' 26 | 27 | print(np.maximum(a, 6)) #ブロードキャストつき maximum 28 | 29 | ''' 30 | [[ 6 6 6 7 9 11 13] 31 | [ 6 6 6 8 10 12 14] 32 | [ 6 6 7 9 11 13 15] 33 | [ 6 6 6 8 10 12 14] 34 | [ 6 6 6 7 9 11 13]] 35 | ''' 36 | 37 | print(np.argmax(a)) #最大値をとるインデックス(1 次元 array に引き伸ばされている) 38 | 39 | ''' 40 | 20 41 | ''' -------------------------------------------------------------------------------- /appendix/max_2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | a = np.array([[1, 3, 5, 7, 9, 11, 13], 4 | [2, 4, 6, 8, 10, 12, 14], 5 | [3, 5, 7, 9, 11, 13, 15], 6 | [2, 4, 6, 8, 10, 12, 14], 7 | [1, 3, 5, 7, 9, 11, 13]]) 8 | 9 | print(np.argmax(a)) #最大値をとるインデックス(1 次元 array に引き伸ばされている) 10 | 11 | ''' 12 | 20 13 | ''' 14 | 15 | print(np.argmax(a, axis=0)) 16 | 17 | ''' 18 | [2 2 2 2 2 2 2] 19 | ''' 20 | 21 | print(np.argmax(a, axis=1)) 22 | 23 | ''' 24 | [6 6 6 6 6] 25 | ''' 26 | -------------------------------------------------------------------------------- /appendix/mult_1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | x = np.array([[1, 3, 5], [7, 9, 11]]) 4 | y = np.array([[1, 2], [3, 4], [5, 6]]) 5 | 6 | print(np.dot(x, y)) #行列積 7 | 8 | ''' 9 | [[ 35 44] 10 | [ 89 116]] 11 | ''' 12 | 13 | print(x.dot(y)) #行列積 14 | 15 | ''' 16 | [[ 35 44] 17 | [ 89 116]] 18 | ''' 19 | 20 | print(x @ y) #行列積 21 | 22 | ''' 23 | [[ 35 44] 24 | [ 89 116]] 25 | ''' -------------------------------------------------------------------------------- /appendix/mult_2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | u = np.array([1, 3, 5]) 4 | v = np.array([7, 9, 11]) 5 | 6 | print(np.dot(u, v)) #内積 7 | 8 | ''' 9 | 89 10 | ''' 11 | 12 | print(np.dot(v, u)) #内積 13 | 14 | ''' 15 | 89 16 | ''' 17 | 18 | print(u.dot(v)) #内積 19 | 20 | ''' 21 | 89 22 | ''' 23 | 24 | print(u @ v) #内積 25 | 26 | ''' 27 | 89 28 | ''' -------------------------------------------------------------------------------- /appendix/numpy_1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | a = np.array([[1, 3], [5, 7]]) 4 | b = np.array([[1, 2], [3, 4]]) 5 | 6 | print(a * b) #乗算(アダマール積):np.multiply(a, b) でも同様の結果が得られる 7 | 8 | ''' 9 | [[ 1 6] 10 | [15 28]] 11 | ''' 12 | 13 | print(np.square(a)) #二乗:a ** 2 でも同様の結果が得られる 14 | 15 | ''' 16 | [[ 1 9] 17 | [25 49]] 18 | ''' 19 | 20 | print(np.power(a, 3)) #べき乗:a ** 3 でも同様の結果が得られる 21 | 22 | ''' 23 | [[ 1 27] 24 | [125 343]] 25 | ''' -------------------------------------------------------------------------------- /appendix/numpy_2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | x_1 = np.array([1, 2, 3]) 4 | x_2 = np.array([[1, 2, 3]]) 5 | 6 | 7 | print(x_1.ndim) #一次元 array 8 | 9 | ''' 10 | 1 11 | ''' 12 | 13 | print(x_2.ndim) #二次元 array 14 | 15 | ''' 16 | 2 17 | ''' 18 | 19 | print(x_1.T) 20 | 21 | ''' 22 | [1 2 3] 23 | ''' 24 | 25 | print(x_2.T) 26 | 27 | ''' 28 | [[1] 29 | [2] 30 | [3]] 31 | ''' -------------------------------------------------------------------------------- /appendix/rand_1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | np.random.seed(1000) # シードの固定 4 | 5 | print(np.random.randint(100, 1000)) # 100 以上 1000 未満の整数一様乱数 6 | 7 | ''' 8 | 535 9 | ''' 10 | 11 | print(np.random.randint(100, 1000, 10)) # 100 以上 1000 未満の整数一様乱数を 10 個 12 | 13 | ''' 14 | [699 171 804 351 450 448 869 545 740 957] 15 | ''' -------------------------------------------------------------------------------- /appendix/rand_2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | np.random.seed(1000) # シードの固定 4 | 5 | print(np.random.rand()) # 0 以上 1 未満 の一様乱数 6 | 7 | ''' 8 | 0.6535895854646095 9 | ''' 10 | 11 | print(np.random.rand(10)) # 0 以上 1 未満の一様乱数を 10 個 12 | 13 | ''' 14 | [0.11500694 0.95028286 0.4821914 0.87247454 0.21233268 15 | 0.04070962 0.39719446 0.2331322 0.84174072 0.20708234] 16 | ''' -------------------------------------------------------------------------------- /appendix/rand_3.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | np.random.seed(1000) # シードの固定 4 | 5 | print(np.random.normal(2.0, 0.5)) # 平均が 2.0 標準偏差が 0.5 の正規乱数 6 | 7 | ''' 8 | 1.5977708482375974 9 | ''' 10 | 11 | print(np.random.normal(2.0, 1.5, 10)) # 平均が 2.0 標準偏差が 0.5 の正規乱数を 10 個 12 | 13 | ''' 14 | [2.48139732 1.96177568 2.96648574 1.54880499 2.58421183 15 | 1.83884405 1.28002539 2.89255325 1.30299871 3.00092196] 16 | ''' -------------------------------------------------------------------------------- /appendix/rand_4.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | np.random.seed(1000) # シードの固定 4 | 5 | print(np.random.randn()) # 平均が 0 標準偏差が 1 の正規乱数 6 | 7 | ''' 8 | -0.8044583035248052 9 | ''' 10 | 11 | print(np.random.randn(10)) # 平均が 0 標準偏差が 1 の正規乱数を 10 個 12 | 13 | ''' 14 | [ 0.32093155 -0.02548288 0.64432383 -0.30079667 0.38947455 15 | -0.1074373 -0.47998308 0.5950355 -0.46466753 0.66728131] 16 | ''' -------------------------------------------------------------------------------- /appendix/rand_5.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | np.random.seed(1000) # シードの固定 4 | 5 | print(np.random.binomial(100, 0.3)) # n=100, p=0.3 の二項乱数 6 | 7 | ''' 8 | 32 9 | ''' 10 | 11 | print(np.random.binomial(100, 0.3, 10)) # n=100, p=0.3 の二項乱数を 10 個 12 | 13 | ''' 14 | [25 38 30 35 26 22 29 27 35 26] 15 | ''' -------------------------------------------------------------------------------- /appendix/rand_6.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | np.random.seed(1000) # シードの固定 4 | 5 | s = ['a', 'b', 'c', 'd', 'e'] 6 | 7 | np.random.shuffle(s) #シャッフルしたリストで置き換える 8 | 9 | print(s) 10 | 11 | ''' 12 | ['c', 'b', 'a', 'e', 'd'] 13 | ''' -------------------------------------------------------------------------------- /appendix/rand_7.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | np.random.seed(1000) # シードの固定 4 | 5 | s = ['a', 'b', 'c', 'd', 'e'] 6 | 7 | a = np.random.permutation(s) 8 | 9 | print(s) # 元のリストは置き換わっていない 10 | 11 | ''' 12 | ['a', 'b', 'c', 'd', 'e'] 13 | ''' 14 | 15 | print(a) 16 | 17 | ''' 18 | ['c', 'b', 'a', 'e', 'd'] 19 | ''' -------------------------------------------------------------------------------- /appendix/rand_8.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | np.random.seed(1000) # シードの固定 4 | 5 | a = np.random.permutation(10) # 0 以上 10 未満の整数列をシャッフル 6 | 7 | print(a) 8 | 9 | ''' 10 | [2 6 5 1 4 9 0 8 7 3] 11 | ''' -------------------------------------------------------------------------------- /appendix/rand_9.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | np.random.seed(1000) # シードの固定 4 | 5 | s = ['a', 'b', 'c', 'd', 'e'] 6 | 7 | a = np.random.choice(s, 10) 8 | 9 | print(a) 10 | 11 | ''' 12 | ['d' 'a' 'd' 'e' 'b' 'a' 'b' 'a' 'b' 'e'] 13 | ''' -------------------------------------------------------------------------------- /appendix/reshape_1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | a = np.array([[0, 1, 2, 3], 4 | [4, 5, 6, 7], 5 | [8, 9, 10, 11]]) 6 | print(a) 7 | 8 | ''' 9 | [[ 0 1 2 3] 10 | [ 4 5 6 7] 11 | [ 8 9 10 11]] 12 | ''' 13 | 14 | print(a.reshape(2, 6)) # 形状変換 15 | 16 | ''' 17 | [[ 0 1 2 3 4 5] 18 | [ 6 7 8 9 10 11]] 19 | ''' 20 | 21 | b = np.arange(24).reshape(2, 3, 4) 22 | # np.arange(24) は 0 以上 24 未満の整数を 1 次元 array として生成 23 | print(b) # 3 次元 array 24 | 25 | ''' 26 | [[[ 0 1 2 3] 27 | [ 4 5 6 7] 28 | [ 8 9 10 11]] 29 | 30 | [[12 13 14 15] 31 | [16 17 18 19] 32 | [20 21 22 23]]] 33 | ''' 34 | 35 | print(b.reshape(2, 3, 2, -1)) # 形状変換 36 | 37 | ''' 38 | [[[[ 0 1] 39 | [ 2 3]] 40 | 41 | [[ 4 5] 42 | [ 6 7]] 43 | 44 | [[ 8 9] 45 | [10 11]]] 46 | 47 | 48 | [[[12 13] 49 | [14 15]] 50 | 51 | [[16 17] 52 | [18 19]] 53 | 54 | [[20 21] 55 | [22 23]]]] 56 | ''' 57 | 58 | print(b.reshape(-1)) # 1 次元 array への変換 59 | 60 | ''' 61 | [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23] 62 | ''' -------------------------------------------------------------------------------- /appendix/searchsorted_1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | a = np.array([1,2,3,4,5]) 4 | 5 | print(np.searchsorted(a, 3)) # a[2] の左に挿入すると順序を破壊しない 6 | 7 | ''' 8 | 2 9 | ''' 10 | 11 | print(np.searchsorted(a, [-10, 10, 2, 3])) # 4 つの要素それぞれに対して挿入すべきインデックスを返す 12 | 13 | ''' 14 | [0, 5, 1, 2] 15 | ''' -------------------------------------------------------------------------------- /appendix/slice_1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | a = np.array([1, 3, 5, 7, 9, 11, 13]) 4 | 5 | print(a[2:5]) #スライス 6 | 7 | ''' 8 | [5 7 9] 9 | ''' 10 | 11 | print(a[:5]) #始点の省略 12 | 13 | ''' 14 | [1 3 5 7 9] 15 | ''' 16 | 17 | print(a[2:]) #終点の省略 18 | 19 | ''' 20 | [ 5 7 9 11 13] 21 | ''' 22 | 23 | print(a[2:5:2]) #刻み幅の指定 24 | 25 | ''' 26 | [5 9] 27 | ''' 28 | 29 | print(a[::-1]) #逆順 30 | 31 | ''' 32 | [13 11 9 7 5 3 1] 33 | ''' 34 | 35 | print(a[-3:0:-1]) #逆順 36 | 37 | ''' 38 | [9 7 5 3] 39 | ''' -------------------------------------------------------------------------------- /appendix/slice_2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | a = np.array([[1, 3, 5, 7, 9, 11, 13], 4 | [2, 4, 6, 8, 10, 12, 14], 5 | [3, 5, 7, 9, 11, 13, 15], 6 | [4, 6, 8, 10, 12, 14, 16], 7 | [5, 7, 9, 11, 13, 15, 17]]) 8 | 9 | print(a[2:4, :]) #スライス 10 | 11 | ''' 12 | [[ 3 5 7 9 11 13 15] 13 | [ 4 6 8 10 12 14 16]] 14 | ''' 15 | 16 | print(a[:, 2:4]) #スライス 17 | 18 | ''' 19 | [[ 5 7] 20 | [ 6 8] 21 | [ 7 9] 22 | [ 8 10] 23 | [ 9 11]] 24 | ''' 25 | 26 | print(a[2:4, 2:4]) #スライス 27 | 28 | ''' 29 | [[ 7 9] 30 | [ 8 10]] 31 | ''' 32 | 33 | print(a[:4:2, -2:1:-2]) #刻み幅の指定 34 | 35 | ''' 36 | [[11 7] 37 | [13 9]] 38 | ''' 39 | -------------------------------------------------------------------------------- /appendix/trans_1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | a = np.arange(12).reshape(3, 4) 4 | print(a) 5 | 6 | ''' 7 | [[ 0 1 2 3] 8 | [ 4 5 6 7] 9 | [ 8 9 10 11]] 10 | ''' 11 | 12 | print(a.T) #転置 13 | 14 | ''' 15 | [[ 0 4 8] 16 | [ 1 5 9] 17 | [ 2 6 10] 18 | [ 3 7 11]] 19 | ''' 20 | 21 | b = np.arange(24).reshape(2, 3, 4) 22 | print(b) # 3 次元 array 23 | 24 | ''' 25 | [[[ 0 1 2 3] 26 | [ 4 5 6 7] 27 | [ 8 9 10 11]] 28 | 29 | [[12 13 14 15] 30 | [16 17 18 19] 31 | [20 21 22 23]]] 32 | ''' 33 | 34 | print(b.transpose(0, 2, 1)) # 軸の入れ替え 35 | 36 | ''' 37 | [[[ 0 4 8] 38 | [ 1 5 9] 39 | [ 2 6 10] 40 | [ 3 7 11]] 41 | 42 | [[12 16 20] 43 | [13 17 21] 44 | [14 18 22] 45 | [15 19 23]]] 46 | ''' -------------------------------------------------------------------------------- /appendix/trans_2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | a = np.array([[0, 1, 2, 3], 4 | [4, 5, 6, 7], 5 | [8, 9, 10, 11]]) 6 | print(a) 7 | 8 | ''' 9 | [[ 0 1 2 3] 10 | [ 4 5 6 7] 11 | [ 8 9 10 11]] 12 | ''' 13 | 14 | print(a.reshape(-1, 2).T) # [0, 1, 2, 3,...] の順で並べたあとに転置している 15 | 16 | ''' 17 | [[ 0 2 4 6 8 10] 18 | [ 1 3 5 7 9 11]] 19 | ''' 20 | 21 | print(a.T.reshape(2, -1)) # 先に転置しているので,[0, 4, 8, 1, ...] の順で並べられる 22 | 23 | ''' 24 | [[ 0 4 8 1 5 9] 25 | [ 2 6 10 3 7 11]] 26 | ''' -------------------------------------------------------------------------------- /appendix/zip_1.py: -------------------------------------------------------------------------------- 1 | list_1 = ["a", "b", "c", "d"] 2 | list_2 = ["x", "y", "z", "w"] 3 | 4 | for foo, bar in zip(list_1, list_2): 5 | print(f"{foo}, {bar}") 6 | 7 | ''' 8 | a, x 9 | b, y 10 | c, z 11 | d, w 12 | ''' -------------------------------------------------------------------------------- /chapter05/Q3_ans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | class Standardization: 4 | def fit_transform(self, X): 5 | """ 6 | X.shape = (データ数, 次元数) 7 | """ 8 | 9 | self.mean_ = X.mean(axis=0) 10 | self.std_ = X.std(axis=0) 11 | Xsd = (X - self.mean_) / self.std_ 12 | return Xsd 13 | 14 | def transform(self, X): 15 | """ 16 | X.shape = (データ数, 次元数) 17 | """ 18 | 19 | Xsd = (X - self.mean_) / self.std_ 20 | return Xsd 21 | 22 | def inverse_transform(self, Xsd): 23 | """ 24 | Xsd.shape = (データ数, 次元数) 25 | """ 26 | 27 | X = (Xsd * self.std_) + self.mean_ 28 | return X 29 | 30 | 31 | if __name__=="__main__": 32 | 33 | std = Standardization() 34 | 35 | X = np.array([[1,2,3], 36 | [4,5,6]]) 37 | print("X\n", X) 38 | 39 | Xsd = std.fit_transform(X) 40 | print("Xsd\n", Xsd) 41 | 42 | Xsd = std.transform(X) 43 | print("Xsd\n", Xsd) 44 | 45 | X_ = std.inverse_transform(Xsd) 46 | print("X_\n", X_) 47 | -------------------------------------------------------------------------------- /chapter07/Q3_ans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | class Sigmoid: 4 | def forward(self, x, w, b): 5 | """ 6 | x.shape = (データ数, 次元数) 7 | w.shape = (1, 次元数) 8 | b.shape = (1,) 9 | """ 10 | self.x = x 11 | z = np.sum(w * x, axis=1) + b 12 | y_pred = 1 / (1 + np.exp(-z)) 13 | self.y_pred = y_pred 14 | return y_pred 15 | 16 | def backward(self, dy): 17 | """ 18 | dy.shape = (データ数, ) 19 | """ 20 | dz = dy * (1.0 - self.y_pred) * self.y_pred 21 | dw = np.sum(self.x * dz.reshape(-1,1), axis=0) 22 | db = np.sum(dz) 23 | return dw, db 24 | 25 | 26 | class NegativeLogLikelihood: 27 | def forward(self, y_pred, y_true): 28 | """ 29 | y_pred.shape = (データ数,) 30 | y_true.shape = (データ数,) 31 | """ 32 | self.y_pred = y_pred 33 | self.y_true = y_true 34 | loss = - (y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred)) 35 | return loss.sum() 36 | 37 | def backward(self): 38 | dy = - (self.y_true / self.y_pred) + ((1 - self.y_true) / (1 - self.y_pred)) 39 | return dy 40 | 41 | 42 | if __name__=="__main__": 43 | 44 | sg = Sigmoid() 45 | 46 | x = np.random.randn(10, 3) 47 | w = np.random.randn(1, 3) 48 | b = np.array([1.0]) 49 | print("x\n", x) 50 | print("w\n", w) 51 | print("b\n", b) 52 | 53 | y_pred = sg.forward(x, w, b) 54 | print("y_pred\n", y_pred) 55 | 56 | nll = NegativeLogLikelihood() 57 | y_true = x[:, 0] > 0 58 | print("y_true\n", y_true) 59 | 60 | loss = nll.forward(y_pred, y_true) 61 | print("loss",loss) 62 | 63 | dy = nll.backward() 64 | print("dy", dy) 65 | 66 | dw, db = sg.backward(dy) 67 | print("dw\n",dw) 68 | print("db\n",db) 69 | 70 | # パラメータw,bを勾配法によって最適化する 71 | lr = 0.1 72 | for i in range(1000): 73 | y_pred = sg.forward(x, w, b) 74 | loss = nll.forward(y_pred, y_true) 75 | print("loss=", loss) 76 | dy = nll.backward() 77 | dw, db = sg.backward(dy) 78 | w -= lr * dw 79 | b -= lr * db 80 | print(w,b) 81 | print("w[0]の値だけ大きくなっていたら学習成功\n") 82 | 83 | print("訓練データに対する予測結果") 84 | y_pred = sg.forward(x, w, b) 85 | y_pred = y_pred > 0.5 86 | print("y_pred\n", y_pred) 87 | print("y_true\n", y_true) -------------------------------------------------------------------------------- /chapter08/Q2_ans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def init_centroid(X, n_data, k): 4 | # 各データ点の中からクラスタの重心となる点をk個ランダムに選択 5 | idx = np.random.permutation(n_data)[:k] 6 | centroids = X[idx] 7 | return centroids 8 | 9 | 10 | def compute_distances(X, k, n_data, centroids): 11 | distances = np.zeros((n_data, k)) 12 | for idx_centroids in range(k): 13 | dist = np.sqrt(np.sum((X - centroids[idx_centroids]) ** 2, axis=1)) 14 | distances[:, idx_centroids] = dist 15 | return distances 16 | 17 | 18 | def k_means(k, X, max_iter=300): 19 | """ 20 | X.shape = (データ数, 次元数) 21 | k = クラスタ数 22 | """ 23 | n_data, n_features = X.shape 24 | 25 | # 重心の初期値 26 | centroids = init_centroid(X, n_data, k) 27 | 28 | # 新しいクラスタを格納するための配列 29 | new_cluster = np.zeros(n_data) 30 | 31 | # 各データの所属クラスタを保存する配列 32 | cluster = np.zeros(n_data) 33 | 34 | for epoch in range(max_iter): 35 | # 各データ点と重心との距離を計算 36 | distances = compute_distances(X, k, n_data, centroids) 37 | 38 | # 新たな所属クラスタを計算 39 | new_cluster = np.argmin(distances, axis=1) 40 | 41 | # すべてのクラスタに対して重心を再計算 42 | for idx_centroids in range(k): 43 | centroids[idx_centroids] = X[new_cluster == idx_centroids].mean(axis=0) 44 | 45 | # クラスタによるグループ分けに変化がなかったら終了 46 | if (new_cluster == cluster).all(): 47 | break 48 | 49 | cluster = new_cluster 50 | 51 | return cluster 52 | 53 | 54 | if __name__=="__main__": 55 | X = np.arange(10*5).reshape(10, 5) 56 | print("X\n", X) 57 | k = 3 58 | print("k=",k) 59 | 60 | cluster = k_means(k, X, max_iter=300) 61 | print("cluster", cluster) 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /chapter08/Q3_ans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from Q2_ans import compute_distances 3 | 4 | 5 | def init_centroid(X, n_data, k): 6 | # 1つ目の重心をランダムに選択 7 | idx = np.random.choice(n_data, 1) 8 | centroids = X[idx] 9 | for i in range(k - 1): 10 | # 各データ点と重心との距離を計算 11 | distances = compute_distances(X, len(centroids), n_data, centroids) 12 | 13 | # 各データ点と最も近い重心との距離の二乗を計算 14 | closest_dist_sq = np.min(distances ** 2, axis=1) 15 | 16 | # 距離の二乗の和を計算 17 | weights = closest_dist_sq.sum() 18 | 19 | # [0,1)の乱数と距離の二乗和を掛ける 20 | rand_vals = np.random.random_sample() * weights 21 | 22 | # 距離の二乗の累積和を計算し,rand_valと最も値が近いデータ点のindexを取得 23 | candidate_ids = np.searchsorted(np.cumsum(closest_dist_sq), rand_vals) 24 | 25 | # 選ばれた点を新たな重心として追加 26 | centroids = np.vstack([centroids, X[candidate_ids]]) 27 | return centroids 28 | 29 | if __name__=="__main__": 30 | X = np.arange(10*5).reshape(10, 5) 31 | print("X\n", X) 32 | 33 | k = 3 34 | print("k=",k) 35 | 36 | n_data = X.shape[0] 37 | centroids = init_centroid(X, n_data, k) 38 | print("centroids", centroids) -------------------------------------------------------------------------------- /chapter08/Q5_ans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def pca(X, n_components=2): 4 | 5 | # データから平均を引く 6 | X = X - X.mean(axis=0) 7 | 8 | # 共分散行列の作成 9 | cov = np.cov(X, rowvar=False) 10 | 11 | # 固有値や主成分方向を計算 12 | l, v = np.linalg.eig(cov) 13 | 14 | # 固有値の大きい順に並び替え 15 | l_index = np.argsort(l)[::-1] 16 | v_ = v[:,l_index] 17 | 18 | # n_components分,主成分方向を取得 19 | components = v_[:,:n_components] 20 | 21 | # データを低次元空間へ射影 22 | T = np.dot(X, components) 23 | 24 | return T 25 | 26 | 27 | if __name__=="__main__": 28 | X = np.arange(10*5).reshape(10, 5) 29 | print("X\n", X) 30 | 31 | T =pca(X, n_components=2) 32 | print("T\n", T) -------------------------------------------------------------------------------- /chapter11/Q2_ans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from common.functions import softmax 3 | 4 | class Softmax: 5 | def __init__(self): 6 | self.params, self.grads = [], [] 7 | self.out = None 8 | 9 | def forward(self, x): 10 | self.out = softmax(x) 11 | return self.out 12 | 13 | def backward(self, dout): 14 | dx = self.out*dout 15 | sumdx = np.sum(dx,axis=1,keepdims=True) 16 | dx -= self.out*sumdx 17 | return dx 18 | 19 | 20 | if __name__=="__main__": 21 | x = np.arange(2*3).reshape(2, 3) 22 | print("x\n", x) 23 | 24 | sf = Softmax() 25 | out = sf.forward(x) 26 | print("out\n", out) 27 | 28 | dout = np.arange(2*3).reshape(2, 3) 29 | print("dout\n", dout) 30 | dx = sf.backward(dout) 31 | print("dx\n", dx) -------------------------------------------------------------------------------- /chapter11/Q3_ans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from common.functions import softmax 3 | 4 | 5 | def cross_entropy_error(y, t): 6 | """ 7 | y : ソフトマックス関数の出力 8 | y.shape=(k,)またはy.shape=(N,k) 9 | t : 正解ラベル(ワンホット表現) 10 | t.shape=(k,)またはt.shape=(N,k) 11 | """ 12 | if y.ndim==1: 13 | t = t.reshape(1,-1) 14 | y = y.reshape(1,-1) 15 | 16 | batch_size = y.shape[0] 17 | delta = 1e-7 18 | return -np.sum(t*np.log(y + delta))/ batch_size 19 | 20 | 21 | class SoftmaxWithLoss: 22 | def __init__(self): 23 | self.loss = None 24 | self.y = None # ソフトマックス関数の出力を格納するインスタンス変数 25 | self.t = None # 正解ラベルを格納するインスタンス変数 26 | 27 | def forward(self, x, t): 28 | self.t = t 29 | self.y = softmax(x) 30 | self.loss = cross_entropy_error(self.y, self.t) 31 | return self.loss 32 | 33 | def backward(self): 34 | batch_size = self.t.shape[0] 35 | dx = (self.y-self.t)/batch_size 36 | return dx 37 | 38 | 39 | if __name__=="__main__": 40 | x = np.arange(2*3).reshape(2, 3) 41 | print("x\n", x) 42 | 43 | t = np.arange(2).reshape(-1, 1) 44 | print("t\n", t) 45 | 46 | sl = SoftmaxWithLoss() 47 | 48 | loss = sl.forward(x,t) 49 | print("loss\n", loss) 50 | 51 | dx = sl.backward() 52 | print("dx\n", dx) 53 | -------------------------------------------------------------------------------- /chapter11/Q4_ans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def relu(X): 4 | return np.maximum(0, X) 5 | 6 | def softmax(X): 7 | X = X - np.max(X, axis=1, keepdims=True) 8 | return np.exp(X) / np.sum(np.exp(X), axis=1, keepdims=True) 9 | 10 | def relu_backward(Z, delta): 11 | delta[Z <= 0] = 0 12 | 13 | def cross_entropy_error(y, t): 14 | batch_size = y.shape[0] 15 | return -np.sum(t * np.log(y + 1e-7)) / batch_size 16 | 17 | 18 | class FullyConnectedNeuralNetwork(): 19 | 20 | def __init__(self, layer_units): 21 | """ 22 | layer_units : list, 各層のノード数を格納したリスト 23 | """ 24 | self.n_iter_ = 0 25 | self.t_ = 0 26 | self.layer_units = layer_units 27 | self.n_layers_ = len(layer_units) 28 | 29 | # パラメータの初期化 30 | self.coefs_ = [] 31 | self.intercepts_ = [] 32 | for i in range(self.n_layers_ - 1): 33 | coef_init, intercept_init = self._init_coef(layer_units[i],layer_units[i+1]) 34 | self.coefs_.append(coef_init) 35 | self.intercepts_.append(intercept_init) 36 | 37 | # 勾配の初期化 38 | self.coef_grads_ = [np.empty((n_in_, n_out_)) for n_in_,n_out_ 39 | in zip(layer_units[:-1],layer_units[1:])] 40 | self.intercept_grads_ = [np.empty(n_out_) for n_out_ in layer_units[1:]] 41 | 42 | 43 | def _init_coef(self, n_in, n_out): 44 | """ 45 | ある層間のパラメータを初期化するメソッド 46 | n_in : int, 入力側のノード数 47 | n_out : int, 出力側のノード数 48 | """ 49 | std = np.sqrt(2/n_in) 50 | coef_init = np.random.randn(n_in, n_out) * std 51 | intercept_init = np.zeros(n_out) 52 | return coef_init, intercept_init 53 | 54 | 55 | def _forward(self, activations): 56 | """ 57 | 順伝播処理を行うメソッド 58 | activations : list, 各層の出力を納めたリスト 59 |                     activations[0]は入力データ 60 |        activations[i].shape=(バッチサイズ,ノード数) 61 | """ 62 | affine = [None] * (self.n_layers_ - 1) 63 | for i in range(self.n_layers_ - 1): 64 | 65 | # アフィン変換 66 | affine[i] = np.dot(activations[i], self.coefs_[i]) + self.intercepts_[i] 67 | 68 | if (i + 1) == ( self.n_layers_ - 1 ): 69 | """ 70 | 出力層の場合 71 | """ 72 | activations[i + 1] = softmax(affine[i]) 73 | else: 74 | """ 75 | 隠れ層の場合 76 | """ 77 | activations[i + 1] = relu(affine[i]) 78 | 79 | return activations 80 | 81 | 82 | def _grad(self, j, activations, deltas): 83 | """ 84 | 各パラメータの勾配を算出するメソッド 85 | j : int, アフィンの番号 86 | activations : list, 各層の出力を納めたリスト 87 | deltas : list, 出力層側から伝わってきた勾配を納めたリスト 88 | """ 89 | self.coef_grads_[j] = np.dot(activations[j].T,deltas[j]) 90 | self.intercept_grads_[j] = np.sum(deltas[j], axis=0) 91 | 92 | 93 | def _backward(self, t, activations): 94 | """ 95 | 逆伝播処理を行うメソッド 96 | t : array-like, 正解ラベル, t.shape=(バッチサイズ, 出力層ノード数) 97 | activations : list, 各層の出力を納めたリスト 98 | """ 99 | deltas = [None] * (self.n_layers_ - 1) 100 | last = self.n_layers_ - 2 101 | 102 | # 交差エントロピー誤差とソフトマックス関数を合わせて勾配を算出 103 | n_samples = t.shape[0] 104 | deltas[last] = (activations[-1] - t)/n_samples 105 | 106 | # 出力層の1つ手前のパラメータの勾配を算出 107 | self._grad(last, activations, deltas) 108 | 109 | # 残りのパラメータの勾配を算出 110 | for i in range(self.n_layers_ - 2, 0, -1): 111 | # 入力(activations)の勾配を算出 112 | deltas[i - 1] = np.dot(deltas[i], self.coefs_[i].T) 113 | 114 | # 活性化関数ReLUの勾配を算出 115 | relu_backward(activations[i], deltas[i - 1]) 116 | 117 | # パラメータの勾配を算出 118 | self._grad(i-1, activations, deltas) 119 | 120 | return 121 | 122 | 123 | def _forward_and_back(self, x, t): 124 | """ 125 | 順伝播処理を実行した後、逆伝播処理を実行するメソッド 126 | x : array-like, 入力データ, x.shape=(バッチサイズ, 入力層ノード数) 127 | t : array-like, 正解ラベル, t.shape=(バッチサイズ, 出力層ノード数) 128 | """ 129 | activations = [x] + [None] * (self.n_layers_ - 1) 130 | 131 | # 順伝播 132 | activations = self._forward(activations) 133 | loss = cross_entropy_error(activations[-1], t) 134 | 135 | # 逆伝播 136 | self._backward(t, activations) 137 | 138 | return loss 139 | 140 | 141 | if __name__=="__main__": 142 | X = np.arange(21).reshape(3,7) 143 | print("X=\n",X) 144 | 145 | t = np.array([[0,1,0],[0,1,0],[1,0,0]]) 146 | print("t=\n",t) 147 | 148 | layer_units=[7,4,3] 149 | 150 | mp = FullyConnectedNeuralNetwork(layer_units=layer_units) 151 | loss = mp._forward_and_back(X, t) 152 | print("loss=",loss) 153 | 154 | -------------------------------------------------------------------------------- /chapter11/common/functions.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def softmax(x): 4 | if x.ndim == 2: 5 | x = x - x.max(axis=1,keepdims=True) 6 | x = np.exp(x) 7 | x /= x.sum(axis=1,keepdims=True) 8 | elif x.ndim == 1: 9 | x = x - np.max(x) 10 | x = np.exp(x) / np.sum(np.exp(x)) 11 | return x -------------------------------------------------------------------------------- /chapter12/Q1_ans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | class SGD: 4 | def __init__(self, lr=0.01): 5 | self.lr = lr 6 | 7 | def update(self, params, grads): 8 | for key in params.keys(): 9 | params[key] -= self.lr * grads[key] 10 | 11 | 12 | class Momentum: 13 | def __init__(self, lr=0.01, momentum=0.9): 14 | self.lr = lr 15 | self.momentum = momentum 16 | self.v = None 17 | 18 | def update(self, params, grads): 19 | if self.v is None: 20 | self.v = {} 21 | for key, val in params.items(): 22 | self.v[key] = np.zeros_like(val) 23 | 24 | for key in params.keys(): 25 | self.v[key] = self.momentum*self.v[key] - self.lr*grads[key] 26 | params[key] += self.v[key] 27 | 28 | 29 | class Nesterov: 30 | def __init__(self, lr=0.01, momentum=0.9): 31 | self.lr = lr 32 | self.momentum = momentum 33 | self.v = None 34 | 35 | def update(self, params, grads): 36 | if self.v is None: 37 | self.v = {} 38 | for key, val in params.items(): 39 | self.v[key] = np.zeros_like(val) 40 | 41 | for key in params.keys(): 42 | params[key] += self.momentum * self.momentum * self.v[key] 43 | params[key] -= (1 + self.momentum) * self.lr * grads[key] 44 | self.v[key] *= self.momentum 45 | self.v[key] -= self.lr * grads[key] 46 | 47 | 48 | class AdaGrad: 49 | def __init__(self, lr=0.01): 50 | self.lr = lr 51 | self.h = None 52 | 53 | def update(self, params, grads): 54 | if self.h is None: 55 | self.h = {} 56 | for key, val in params.items(): 57 | self.h[key] = np.zeros_like(val) 58 | 59 | for key in params.keys(): 60 | self.h[key] += grads[key] * grads[key] 61 | params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7) 62 | 63 | 64 | class RMSProp: 65 | def __init__(self, lr=0.01, decay_rate = 0.99): 66 | self.lr = lr 67 | self.decay_rate = decay_rate 68 | self.h = None 69 | 70 | def update(self, params, grads): 71 | if self.h is None: 72 | self.h = {} 73 | for key, val in params.items(): 74 | self.h[key] = np.zeros_like(val) 75 | 76 | for key in params.keys(): 77 | self.h[key] *= self.decay_rate 78 | self.h[key] += (1 - self.decay_rate) * grads[key] * grads[key] 79 | params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key] + 1e-7)) 80 | 81 | 82 | class Adam: 83 | def __init__(self, lr=0.001, rho1=0.9, rho2=0.999): 84 | self.lr = lr 85 | self.rho1 = rho1 86 | self.rho2 = rho2 87 | self.iter = 0 88 | self.m = None 89 | self.v = None 90 | self.epsilon = 1e-8 91 | 92 | def update(self, params, grads): 93 | if self.m is None: 94 | self.m, self.v = {}, {} 95 | for key, val in params.items(): 96 | self.m[key] = np.zeros_like(val) 97 | self.v[key] = np.zeros_like(val) 98 | 99 | self.iter += 1 100 | 101 | for key in params.keys(): 102 | self.m[key] = self.rho1*self.m[key] + (1-self.rho1)*grads[key] 103 | self.v[key] = self.rho2*self.v[key] + (1-self.rho2)*(grads[key]**2) 104 | 105 | m = self.m[key] / (1 - self.rho1**self.iter) 106 | v = self.v[key] / (1 - self.rho2**self.iter) 107 | 108 | params[key] -= self.lr * m / (np.sqrt(v) + self.epsilon) 109 | 110 | 111 | if __name__=="__main__": 112 | 113 | for CLS in [SGD, Momentum, Nesterov, AdaGrad, RMSProp, Adam]: 114 | print(CLS) 115 | 116 | cls = CLS() 117 | 118 | params = {"affine1":np.random.randn(6).reshape(2,3), 119 | "affine2":np.random.randn(6).reshape(2,3) 120 | } 121 | grads = {"affine1":np.random.randn(6).reshape(2,3), 122 | "affine2":np.random.randn(6).reshape(2,3) 123 | } 124 | 125 | print("params\n", params) 126 | print("grads\n", grads) 127 | cls.update(params, grads) 128 | print("params after\n", params) 129 | 130 | -------------------------------------------------------------------------------- /chapter12/Q3_ans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | class Dropout: 4 | def __init__(self, dropout_ratio=0.5): 5 | self.dropout_ratio = dropout_ratio 6 | self.mask = None 7 | 8 | def forward(self, x, train_flg=True): 9 | if train_flg: 10 | self.mask = np.random.rand(*x.shape) > self.dropout_ratio 11 | return x * self.mask 12 | else: 13 | return x * (1.0 - self.dropout_ratio) 14 | 15 | def backward(self, dout): 16 | return dout * self.mask 17 | 18 | 19 | if __name__=="__main__": 20 | x = np.arange(2*3).reshape(2, 3) 21 | print("x\n", x) 22 | 23 | do = Dropout() 24 | out = do.forward(x) 25 | print("out\n", out) 26 | 27 | out = do.forward(x, train_flg=False) 28 | print("out\n", out) 29 | 30 | dout = np.arange(2*3).reshape(2, 3) 31 | print("dout\n", dout) 32 | dx = do.backward(dout) 33 | print("dx", dx) -------------------------------------------------------------------------------- /chapter13/Q2_ans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def im2col(input_data, filter_h, filter_w, stride, pad, constant_values=0): 5 | """ 6 | input_data : (データ数, チャンネル数, 高さ, 幅)の4次元配列 7 | filter_h : フィルタの高さ 8 | filter_w : フィルタの幅 9 | stride : ストライドサイズ 10 | pad : パディングサイズ 11 | constant_values : パディング処理で埋める際の値 12 | """ 13 | 14 | # 入力データのデータ数, チャンネル数, 高さ, 幅を取得 15 | N, C, H, W = input_data.shape 16 | 17 | # 出力データの高さ(端数は切り捨てる) 18 | out_h = (H + 2 * pad - filter_h) // stride + 1 19 | 20 | # 出力データの幅(端数は切り捨てる) 21 | out_w = (W + 2 * pad - filter_w) // stride + 1 22 | 23 | # パディング処理 24 | img = np.pad( 25 | input_data, 26 | [(0, 0), (0, 0), (pad, pad), (pad, pad)], 27 | "constant", 28 | constant_values=constant_values, 29 | ) 30 | 31 | # 配列の初期化 32 | col = np.zeros((N, C, filter_h, filter_w, out_h, out_w)) 33 | 34 | # フィルタ内のある1要素に対応する画像中の画素を取り出してcolに代入 35 | for y in range(filter_h): 36 | y_max = y + stride * out_h 37 | for x in range(filter_w): 38 | x_max = x + stride * out_w 39 | col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride] 40 | 41 | # 軸を入れ替えて、2次元配列(行列)に変換する 42 | col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N * out_h * out_w, -1) 43 | 44 | return col 45 | 46 | 47 | def maxpooling_forward(x, pad, stride, pool_h, pool_w): 48 | """ 49 | x : 入力データ, 配列形状 = (データ数, チャンネル数, 高さ, 幅) 50 | pad : パディングサイズ 51 | stride : ストライドサイズ 52 | pool_h : プーリング領域の縦 53 | pool_w : プーリング領域の横 54 | """ 55 | 56 | N, C, H, W = x.shape 57 | 58 | # 出力の高さ(端数は切り捨てる) 59 | out_h = (H + 2 * pad - pool_h) // stride + 1 60 | 61 | # 出力の幅(端数は切り捨てる) 62 | out_w = (W + 2 * pad - pool_w) // stride + 1 63 | 64 | # 2次元配列に変換する 65 | col = im2col(x, pool_h, pool_w, stride, pad, constant_values=0) 66 | 67 | # チャンネル方向のデータが横に並んでいるので、縦に並べ替える 68 | col = col.reshape(-1, pool_h * pool_w) 69 | 70 | # 最大値と最大値のインデックス(逆伝播時に使用)を求める 71 | out_idx = np.argmax(col, axis=1) 72 | 73 | # 最大値を求める 74 | out = np.max(col, axis=1) 75 | 76 | # 画像形式に戻して、チャンネルの軸を2番目に移動させる 77 | out = out.reshape(N, out_h, out_w, C). transpose(0, 3, 1, 2) 78 | 79 | return out_idx, out 80 | 81 | 82 | def convolution_forward(x, W, b, pad, stride): 83 | """ 84 | x : 入力データ, 配列形状 = (データ数, チャンネル数, 高さ, 幅) 85 | W : フィルタ, 配列形状 = (出力チャンネル数, 入力チャンネル数, 高さ, 幅) 86 | b : バイアス 87 | pad : パディングサイズ 88 | stride : ストライドサイズ 89 | """ 90 | 91 | FN, C, FH, FW = W.shape 92 | N, C, IH, IW = x.shape 93 | 94 | # 出力の高さ(端数は切り捨てる) 95 | out_h = (IH + 2 * pad - FH) // stride + 1 96 | 97 | # 出力の幅(端数は切り捨てる) 98 | out_w = (IW + 2 * pad - FW) // stride + 1 99 | 100 | # 畳み込み演算を効率的に行えるようにするため、入力xを行列colに変換する 101 | col = im2col(x, FH, FW, stride, pad) 102 | 103 | # フィルタを2次元配列に変換する 104 | col_W = W.reshape(FN, -1).T 105 | 106 | # 行列の積を計算し、バイアスを足す 107 | out = np.dot(col, col_W) + b 108 | 109 | # 画像形式に戻して、チャンネルの軸を2番目に移動させる 110 | out = out.reshape(N, out_h, out_w, -1). transpose(0, 3, 1, 2) 111 | 112 | return out 113 | 114 | 115 | if __name__=="__main__": 116 | x = np.arange(2*3*28*28).reshape(2, 3, 28 ,28) 117 | print("x\n", x) 118 | pad = 1 119 | stride = 1 120 | pool_h = 3 121 | pool_w = 3 122 | out_idx, out = maxpooling_forward(x, pad, stride, pool_h, pool_w) 123 | print("out_idx\n", out_idx) 124 | print("out\n", out) 125 | 126 | x = np.arange(2*3*28*28).reshape(2, 3, 28 ,28) 127 | print("x\n", x) 128 | W = np.arange(5*3*3*3).reshape(5, 3, 3, 3) 129 | print("W\n", W) 130 | b = np.array([1]) 131 | print("b\n", b) 132 | pad = 1 133 | stride = 1 134 | out = convolution_forward(x, W, b, pad, stride) -------------------------------------------------------------------------------- /chapter14/Q2_ans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | class RNN: 4 | def __init__(self, Wx, Wh, h0): 5 | """ 6 | Wx : 入力xにかかる重み(1,隠れ層のノード数) 7 | Wh : 1時刻前のhにかかる重み(隠れ層のノード数, 隠れ層のノード数) 8 | h0 : 隠れ層の初期値(1,隠れ層のノード数) 9 | """ 10 | 11 | # パラメータのリスト 12 | self.params = [Wx, Wh] 13 | 14 | # 隠れ層の初期値を設定 15 | self.h_prev = h0 16 | 17 | def forward(self, x): 18 | """ 19 | 順伝播計算 20 | x : 入力(データ数,1) 21 | """ 22 | Wx, Wh = self.params 23 | h_prev = self.h_prev 24 | 25 | t = np.dot(h_prev, Wh) + np.dot(x, Wx) 26 | 27 | # 活性化関数は恒等写像関数とする 28 | h_next = t 29 | 30 | # 隠れ層の状態の保存 31 | self.h_prev = h_next 32 | 33 | return h_next 34 | 35 | 36 | if __name__=="__main__": 37 | Wx = np.arange(1*5).reshape(1, 5) 38 | print("Wx\n", Wx) 39 | Wh = np.arange(5*5).reshape(5, 5) 40 | print("Wh\n", Wh) 41 | h0 = np.arange(5).reshape(1, 5) 42 | print("h0\n", h0) 43 | 44 | rnn = RNN(Wx, Wh, h0) 45 | 46 | x = np.arange(3*1).reshape(3, 1) 47 | print("x\n", x) 48 | 49 | h_next = rnn.forward(x) 50 | print("h_next\n", h_next) 51 | -------------------------------------------------------------------------------- /chapter14/Q4_ans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def forward(x, h_prev, c_prev, Wx, Wh, b): 4 | """ 5 | 順伝播計算 6 | x: 入力 (データ数, 特徴量の数) 7 | h_prev: 前時刻の隠れ層の出力 (データ数, 隠れ層のノード数) 8 | c_prev: 前時刻のメモリの状態 (データ数, 隠れ層のノード数) 9 | Wx: 入力x用の重みパラメータ (特徴量の数, 4×隠れ層のノード数) 10 | Wh: 隠れ状態h用の重みパラメータ(隠れ層のノード数, 4×隠れ層のノード数) 11 | b: バイアス (4×隠れ層のノード数) 12 | """ 13 | 14 | N, H = h_prev.shape 15 | 16 | A = np.dot(x, Wx) + np.dot(h_prev, Wh) + b 17 | 18 | f = A[:, :H] 19 | g = A[:, H:2*H] 20 | i = A[:, 2*H:3*H] 21 | o = A[:, 3*H:] 22 | 23 | f = sigmoid(f) 24 | g = np.tanh(g) 25 | i = sigmoid(i) 26 | o = sigmoid(o) 27 | 28 | print(f.shape, c_prev.shape, g.shape, i.shape) 29 | c_next = f * c_prev + g * i 30 | h_next = o * np.tanh (c_next) 31 | 32 | return h_next, c_next 33 | 34 | 35 | def sigmoid(x): 36 | return 1 / (1 + np.exp(-x)) 37 | 38 | 39 | if __name__=="__main__": 40 | N = 2 41 | D = 3 42 | H = 4 43 | x = np.random.randn(N, D) 44 | print("x\n", x) 45 | 46 | h_prev = np.random.randn(N, H) 47 | print("h_prev\n", h_prev) 48 | 49 | c_prev = np.random.randn(N, H) 50 | print("c_prev\n", c_prev) 51 | 52 | Wx = np.random.randn(D, 4*H) 53 | print("Wx\n", Wx) 54 | 55 | Wh = np.random.randn(H, 4*H) 56 | print("Wh\n", Wh) 57 | 58 | b = np.random.randn(4*H) 59 | print("b\n", b) 60 | 61 | h_next, c_next = forward(x, h_prev, c_prev, Wx, Wh, b) 62 | print("h_next\n", h_next) 63 | print("c_next\n", c_next) -------------------------------------------------------------------------------- /chapter14/Q8_ans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def forward(hs, h): 4 | """ 5 | 順伝播 6 | 重みベクトルを求めるための関数 7 | hs : エンコーダにおけるすべての隠れ状態(データ数,時刻数,隠れ層のノード数) 8 | h : デコーダにおける、ある時刻の隠れ状態(データ数,隠れ層のノード数) 9 | """ 10 | N, T, H = hs.shape 11 | 12 | # デコーダのある場所の隠れ状態を3次元配列に変形する 13 | hr = h.reshape(N, 1, H).repeat(T, axis=1) 14 | 15 | # エンコーダの隠れ状態とコーダの隠れ状態を掛けて足し合わせることで内積をとる 16 | # ほかの実装例として、hsとhrを結合し、重みWを掛けるという方法もある 17 | t = hs * hr 18 | s = np.sum(t, axis=2) 19 | 20 | # ソフトマックス関数に通すことで、正規化する 21 | a = softmax(s) # aは重みベクトルを並べた行列 (N * T) 22 | 23 | return a 24 | 25 | 26 | def softmax(x): 27 | if x.ndim == 2: 28 | x = x - x.max(axis=1, keepdims=True) 29 | x = np.exp(x) 30 | x /= x.sum(axis=1, keepdims=True) 31 | elif x.ndim == 1: 32 | x = x - np.max(x) 33 | x = np.exp(x) / np.sum(np.exp(x)) 34 | return x 35 | 36 | 37 | if __name__=="__main__": 38 | N = 2 39 | T = 3 40 | H = 4 41 | hs = np.random.randn(N, T, H) 42 | print("hs\n", hs) 43 | 44 | h = np.random.randn(N, H) 45 | print("h\n", h) 46 | 47 | a = forward(hs, h) 48 | print("a\n", a) -------------------------------------------------------------------------------- /chapter15/Q3_ans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from layers import TimeEmbedding, TimeSoftmaxWithLoss 3 | 4 | 5 | class SimpleRnnlm: 6 | def __init__(self, vocab_size, wordvec_size, hidden_size): 7 | V, D, H = vocab_size, wordvec_size, hidden_size 8 | rn = np.random.randn 9 | 10 | # 重みの初期化 11 | embed_W = rn(V, D).astype('f') 12 | rnn_Wx = rn(D, H).astype('f') 13 | rnn_Wh = rn(H, H).astype('f') 14 | rnn_b = np.zeros(H).astype('f') 15 | affine_W = rn(H, V).astype('f') 16 | affine_b = np.zeros(V).astype('f') 17 | 18 | # レイヤの生成 19 | self.layers = [ 20 | TimeEmbedding(embed_W), 21 | TimeRNN(rnn_Wx, rnn_Wh, rnn_b), 22 | TimeAffine(affine_W, affine_b) 23 | ] 24 | self.loss_layer = TimeSoftmaxWithLoss() 25 | self.rnn_layer = self.layers[1] 26 | 27 | # すべての重みと勾配をリストにまとめる 28 | self.params, self.grads = [], [] 29 | for layer in self.layers: 30 | self.params += layer.params 31 | self.grads += layer.grads 32 | 33 | def forward(self, xs, ts): 34 | for layer in self.layers: 35 | xs = layer.forward(xs) 36 | loss = self.loss_layer.forward(xs, ts) 37 | return loss 38 | 39 | 40 | class RNN: 41 | def __init__(self, Wx, Wh, b): 42 | self.params = [Wx, Wh, b] 43 | self.grads = [np.zeros_like(Wx), np.zeros_like(Wh), np.zeros_like(b)] 44 | self.cache = None 45 | 46 | def forward(self, x, h_prev): 47 | Wx, Wh, b = self.params 48 | t = np.dot(h_prev, Wh) + np.dot(x, Wx) + b 49 | h_next = np.tanh(t) 50 | 51 | self.cache = (x, h_prev, h_next) 52 | return h_next 53 | 54 | 55 | class TimeRNN: 56 | def __init__(self, Wx, Wh, b): 57 | self.params = [Wx, Wh, b] 58 | self.grads = [np.zeros_like(Wx), np.zeros_like(Wh), np.zeros_like(b)] 59 | self.layers = None 60 | self.h, self.dh = None, None 61 | 62 | def forward(self, xs): 63 | Wx, Wh, b = self.params 64 | N, T, D = xs.shape 65 | (D, H) = Wx.shape 66 | 67 | self.layers = [] 68 | hs = np.empty((N, T, H), dtype='f') 69 | 70 | if self.h is None: 71 | self.h = np.zeros((N, H), dtype='f') 72 | 73 | for t in range(T): 74 | layer = RNN(*self.params) 75 | self.h = layer.forward(xs[:, t, :], self.h) 76 | hs[:, t, :] = self.h 77 | self.layers.append(layer) 78 | 79 | return hs 80 | 81 | 82 | class TimeAffine: 83 | def __init__(self, W, b): 84 | self.params = [W, b] 85 | self.grads = [np.zeros_like(W), np.zeros_like(b)] 86 | self.x = None 87 | 88 | def forward(self, x): 89 | N, T, H = x.shape 90 | W, b = self.params 91 | 92 | rx = x.reshape(N*T, -1) 93 | out = np.dot(rx, W) + b 94 | self.x = x 95 | return out.reshape(N, T, -1) 96 | 97 | 98 | if __name__=="__main__": 99 | N = 2 100 | V = 20 101 | T = 10 102 | D = 3 103 | H = 4 104 | xs = np.random.randint(0, V, size=(N, T)) 105 | print("xs\n", xs) 106 | 107 | ts = np.random.randint(0, V, size=(N, T)) 108 | print("ts\n", ts) 109 | 110 | sr = SimpleRnnlm(vocab_size=V, wordvec_size=D, hidden_size=H) 111 | loss = sr.forward(xs, ts) 112 | print("loss\n", loss) 113 | 114 | -------------------------------------------------------------------------------- /chapter15/layers.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def softmax(x): 4 | if x.ndim == 2: 5 | x = x - x.max(axis=1, keepdims=True) 6 | x = np.exp(x) 7 | x /= x.sum(axis=1, keepdims=True) 8 | elif x.ndim == 1: 9 | x = x - np.max(x) 10 | x = np.exp(x) / np.sum(np.exp(x)) 11 | return x 12 | 13 | 14 | class Embedding: 15 | def __init__(self, W): 16 | """ 17 | W : 重み行列, word2vecの埋め込み行列に相当する。配列形状は、(語彙数、埋め込みベクトルの要素数) 18 | """ 19 | self.params = [W] 20 | self.grads = [np.zeros_like(W)] 21 | self.idx = None 22 | 23 | def forward(self, idx): 24 | """ 25 | 順伝播計算 26 | """ 27 | W, = self.params # dWの後の,はリストから1つだけを抜き出すためにつけている 28 | self.idx = idx 29 | 30 | # 埋め込み行列から埋め込みベクトルを取り出す 31 | out = W[idx] 32 | 33 | return out 34 | 35 | 36 | class TimeEmbedding: 37 | def __init__(self, W): 38 | """ 39 | W : 重み行列, word2vecの埋め込み行列に相当する。配列形状は、(語彙数、埋め込みベクトルの要素数) 40 | """ 41 | self.params = [W] 42 | self.grads = [np.zeros_like(W)] 43 | self.layers = None 44 | self.W = W 45 | 46 | def forward(self, xs): 47 | """ 48 | 順伝播計算 49 | xs : 入力の単語ID, 配列形状は(バッチサイズ、時間数) 50 | """ 51 | N, T = xs.shape # バッチサイズ、時間数 52 | V, D = self.W.shape # 語彙数、埋め込みベクトルの要素数 53 | 54 | # 初期化 55 | out = np.empty((N, T, D), dtype='f') 56 | self.layers = [] 57 | 58 | # 時間方向に計算を進める 59 | for t in range(T): 60 | 61 | # Embeddigレイヤを生成し、順伝播計算を行う 62 | layer = Embedding(self.W) 63 | out[:, t, :] = layer.forward(xs[:, t]) 64 | 65 | # Embeddigレイヤを保持しておく 66 | self.layers.append(layer) 67 | 68 | return out 69 | 70 | 71 | class TimeSoftmaxWithLoss: 72 | def __init__(self): 73 | self.params, self.grads = [], [] 74 | self.cache = None 75 | self.ignore_label = -1 76 | 77 | def forward(self, xs, ts): 78 | N, T, V = xs.shape 79 | 80 | if ts.ndim == 3: # 教師ラベルがone-hotベクトルの場合 81 | ts = ts.argmax(axis=2) 82 | 83 | mask = (ts != self.ignore_label) 84 | 85 | # バッチ分と時系列分をまとめる(reshape) 86 | xs = xs.reshape(N * T, V) 87 | ts = ts.reshape(N * T) 88 | mask = mask.reshape(N * T) 89 | 90 | ys = softmax(xs) 91 | ls = np.log(ys[np.arange(N * T), ts]) 92 | ls *= mask # ignore_labelに該当するデータは損失を0にする 93 | loss = -np.sum(ls) 94 | loss /= mask.sum() 95 | 96 | self.cache = (ts, ys, mask, (N, T, V)) 97 | return loss -------------------------------------------------------------------------------- /chapter19/Q12.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def gradients(weights, X_batch, y_batch): 4 | """ 5 | 勾配を計算する関数のダミー 6 | """ 7 | return np.random.randn(weights.shape[0]) 8 | 9 | def main(X_train, y_train): 10 | epoch = 100 # エポック数 11 | batch_size = 32 12 | learning_rate = 0.01 13 | 14 | # 訓練データの数を取得 15 | train_size = X_train.shape[0] 16 | 17 | # 1エポックにおけるイテレーションの回数を計算 18 | iter_per_epoch = max(train_size//batch_size, 1) 19 | 20 | # パラメータの初期化 21 | weights = np.random.randn(X_train.shape[1]) 22 | 23 | # 学習 24 | for i in range(epoch): 25 | # 訓練データを全件、入出力の対応関係を保ったままシャッフルする 26 | p = np.random.permutation(train_size) 27 | X_train = X_train[p] 28 | y_train = y_train[p] 29 | 30 | for j in range(iter_per_epoch): 31 | # シャッフルしてきた訓練データの中から、先頭から順にミニバッチを取得してくる 32 | batch_start_index = j * batch_size 33 | batch_end_index = batch_start_index + batch_size 34 | if batch_end_index > train_size: 35 | batch_end_index = train_size 36 | X_batch = X_train[batch_start_index: batch_end_index] 37 | y_batch = y_train[batch_start_index: batch_end_index] 38 | 39 | # 勾配の計算 40 | grads = gradients(weights, X_batch, y_batch) 41 | # 重みの更新 42 | weights = weights - learning_rate * grads 43 | 44 | 45 | if __name__=="__main__": 46 | X_train = np.random.randn(10, 5) 47 | print("X_train\n", X_train) 48 | 49 | y_train = np.zeros((10, 5)) 50 | print("y_train\n", y_train) 51 | 52 | main(X_train, y_train) 53 | -------------------------------------------------------------------------------- /chapter19/Q13.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | class Adam: 4 | """ 5 | Adam 6 | """ 7 | def __init__(self, lr=0.001, rho1=0.9, rho2=0.999): 8 | self.lr = lr 9 | self.rho1 = rho1 10 | self.rho2 = rho2 11 | self.iter = 0 12 | self.m = None # 1次モーメント. 勾配の平均に相当する 13 | self.v = None # 2次モーメント. 勾配の分散に相当する(中心化されていない) 14 | self.epsilon = 1e-8 15 | 16 | def update(self, params, grads): 17 | if self.m is None: 18 | self.m, self.v = {}, {} 19 | for key, val in params.items(): 20 | self.m[key] = np.zeros_like(val) 21 | self.v[key] = np.zeros_like(val) 22 | 23 | self.iter += 1 24 | 25 | for key in params.keys(): 26 | self.m[key] = self.rho1 * self.m[key] + (1 - self.rho1) * grads[key] # 1次モーメント 27 | self.v[key] = self.rho2 * self.v[key] + (1 - self.rho2) * (grads[key] ** 2) #2次モーメント 28 | 29 | # モーメントのバイアス補正 30 | # 計算初期の頃のモーメントを補正することが目的 31 | # 計算が進行する(self.iterが大きくなる)と、分母は1に近づく 32 | m = self.m[key] / (1 - self.rho1 ** self.iter) # 1次モーメント 33 | v = self.v[key] / (1 - self.rho2 ** self.iter) # 2次モーメント 34 | 35 | # 重みの更新 36 | params[key] -= self.lr * m / (np.sqrt(v) + self.epsilon) 37 | 38 | 39 | if __name__=="__main__": 40 | 41 | cls = Adam() 42 | 43 | params = {"affine1":np.random.randn(6).reshape(2,3), 44 | "affine2":np.random.randn(6).reshape(2,3) 45 | } 46 | grads = {"affine1":np.random.randn(6).reshape(2,3), 47 | "affine2":np.random.randn(6).reshape(2,3) 48 | } 49 | 50 | print("params\n", params) 51 | print("grads\n", grads) 52 | cls.update(params, grads) 53 | print("params after\n", params) 54 | 55 | -------------------------------------------------------------------------------- /chapter19/Q17.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def im2col(input_data, filter_h, filter_w, stride=1, pad=0): 5 | """ 6 | Parameters 7 | ---------- 8 | input_data : (データ数, チャンネル, 高さ, 幅)の4次元配列からなる入力データ 9 | filter_h : 畳み込みカーネルの高さ 10 | filter_w : 畳み込みカーネルの幅 11 | stride : 畳み込みのストライド幅 12 | pad : 畳み込みのパディングサイズ 13 | Returns 14 | ------- 15 | col : 2次元配列 16 | """ 17 | 18 | N, C, H, W = input_data.shape 19 | out_h = (H + 2 * pad - filter_h) // stride + 1 20 | out_w = (W + 2 * pad - filter_w) // stride + 1 21 | 22 | img = np.pad(input_data, [(0, 0), (0, 0), (pad, pad), (pad, pad)], "constant") 23 | col = np.zeros((N, C, filter_h, filter_w, out_h, out_w)) 24 | 25 | for y in range(filter_h): 26 | y_max = y + stride * out_h 27 | for x in range(filter_w): 28 | x_max = x + stride * out_w 29 | col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride] 30 | 31 | col = col.transpose(0, 4, 5, 1, 2, 3).reshape(out_h * out_w * N, -1) 32 | return col 33 | 34 | 35 | if __name__=="__main__": 36 | N = 2 37 | C = 3 38 | H = 4 39 | W = 4 40 | input_data = np.random.randn(N, C, H, W) 41 | print("input_data\n", input_data) 42 | 43 | filter_h = 3 44 | filter_w = 3 45 | col = im2col(input_data, filter_h, filter_w) 46 | print("col\n", col) 47 | 48 | -------------------------------------------------------------------------------- /chapter19/Q22.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from my_functions import sigmoid #シグモイド関数 3 | 4 | class GRU: 5 | def __init__(self, Wx, Wh, b): 6 | ''' 7 | Wx: 入力x用の重みパラメータ(3つ分の重みをまとめたもの) 8 | Wh: 隠れ状態h用の重みパラメータ(3つ分の重みをまとめたもの) 9 | b: バイアス(3つ分のバイアスをまとめたもの) 10 | ''' 11 | self.params = [Wx, Wh, b] 12 | self.grads = [np.zeros_like(Wx), np.zeros_like(Wh), np.zeros_like(b)] 13 | self.cache = None 14 | 15 | def forward(self, x, h_prev): 16 | """ 17 | 順伝播計算 18 | """ 19 | Wx, Wh, b = self.params 20 | N, H = h_prev.shape 21 | 22 | Wxz, Wxr, Wxh = Wx[:, :H], Wx[:, H:2 * H], Wx[:, 2 * H:] 23 | Whz, Whr, Whh = Wh[:, :H], Wh[:, H:2 * H], Wh[:, 2 * H:] 24 | bhz, bhr, bhh = b[:H], b[H:2 * H], b[2 * H:] 25 | 26 | z = sigmoid(np.dot(x, Wxz) + np.dot(h_prev, Whz) + bhz) 27 | r = sigmoid(np.dot(x, Wxr) + np.dot(h_prev, Whr) + bhr) 28 | h_hat = np.tanh(np.dot(x, Wxh) + np.dot(r * h_prev, Whh) + bhh) 29 | h_next = z * h_prev + (1 - z) * h_hat 30 | 31 | self.cache = (x, h_prev, z, r, h_hat) 32 | 33 | return h_next 34 | 35 | def backward(self, dh_next): 36 | """ 37 | 逆伝播計算(省略) 38 | """ 39 | return dx, dh_prev 40 | 41 | 42 | if __name__=="__main__": 43 | N = 2 44 | D = 3 45 | H = 4 46 | x = np.random.randn(N, D) 47 | print("x\n", x) 48 | 49 | h_prev = np.random.randn(N, H) 50 | print("h_prev\n", h_prev) 51 | 52 | Wx = np.random.randn(D, 3*H) 53 | print("Wx\n", Wx) 54 | 55 | Wh = np.random.randn(H, 3*H) 56 | print("Wh\n", Wh) 57 | 58 | b = np.random.randn(3*H) 59 | print("b\n", b) 60 | 61 | gr = GRU(Wx, Wh, b) 62 | h_next, c_next = gr.forward(x, h_prev) 63 | print("h_next\n", h_next) 64 | print("c_next\n", c_next) 65 | 66 | -------------------------------------------------------------------------------- /chapter19/Q8.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def compute_distances(X, k, n_data, centroids): 5 | distances = np.zeros((n_data, k)) 6 | for idx_centroids in range(k): 7 | dist = np.sqrt(np.sum((X - centroids[idx_centroids]) ** 2, axis=1)) 8 | distances[:, idx_centroids] = dist 9 | return distances 10 | 11 | 12 | def init_centroid(X, k, n_data): 13 | # 1つ目のセントロイドをランダムに選択 14 | idx = np.random.choice(n_data, 1) 15 | centroids = X[idx] 16 | for i in range(k - 1): 17 | # 各データ点とセントロイドとの距離を計算 18 | distances = compute_distances(X, len(centroids), n_data, centroids) 19 | 20 | # 各データ点と最も近いセントロイドとの距離の二乗を計算 21 | closest_dist_sq = np.min(distances**2, axis=1) 22 | 23 | # 距離の二乗の和を計算 24 | weights = closest_dist_sq.sum() 25 | 26 | # [0, 1)の乱数と距離の二乗和を掛ける 27 | rand_vals = np.random.random_sample() * weights 28 | 29 | # 距離の二乗の累積和を計算し,rand_valと最も値が近いデータ点のindexを取得 30 | candidate_ids = np.searchsorted(np.cumsum(closest_dist_sq), rand_vals) 31 | 32 | # 選ばれた点を新たなセントロイドとして追加 33 | centroids = np.vstack([centroids, X[candidate_ids]]) 34 | return centroids 35 | 36 | 37 | def k_means(X, k, max_iter=300): 38 | """ 39 | X.shape = (データ数, 次元数) 40 | k = クラスタ数 41 | """ 42 | n_data, n_features = X.shape 43 | 44 | # 重心の初期値 45 | centroids = init_centroid(X, k, n_data) 46 | 47 | # 新しいクラスタを格納するための配列 48 | new_cluster = np.zeros(n_data) 49 | 50 | # 各データの所属クラスタを保存する配列 51 | cluster = np.zeros(n_data) 52 | 53 | for epoch in range(max_iter): 54 | # 各データ点と重心との距離を計算 55 | distances = compute_distances(X, k, n_data, centroids) 56 | 57 | # 新たな所属クラスタを計算 58 | new_cluster = np.argmin(distances, axis=1) 59 | 60 | # すべてのクラスタに対して重心を再計算 61 | for idx_centroids in range(k): 62 | centroids[idx_centroids] = X[new_cluster == idx_centroids].mean(axis=0) 63 | 64 | # クラスタによるグループ分けに変化がなかったら終了 65 | if (new_cluster == cluster).all(): 66 | break 67 | 68 | cluster = new_cluster 69 | 70 | return cluster 71 | 72 | 73 | if __name__=="__main__": 74 | X = np.arange(10*5).reshape(10, 5) 75 | print("X\n", X) 76 | k = 3 77 | print("k=",k) 78 | 79 | cluster = k_means(X, k, max_iter=300) 80 | print("cluster", cluster) 81 | 82 | 83 | -------------------------------------------------------------------------------- /chapter19/my_functions.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def sigmoid(x): 4 | return 1 / (1 + np.exp(-x)) --------------------------------------------------------------------------------