【文字列リスト】条件を満たす要素の一括抽出の仕方

コード読んでいると以下のようなコードが頻繁に出てくるし、リスト内包表記と一括抽出便利で使いたいので備忘録書いておきます。
**【お詫び】以下の記事で変数名にlistを使用していましたが、shiracamus様のコメント及び参考の記事のように組み込み関数のため変数名として使用してはいけない用語でした。お詫びして記事中name_listに修正させていただきます。また、コメントを反映させていただき、一部追加説明入れました。**
【参考】
[Pythonで変数名をつけるときには予約語だけでなく組み込み関数との衝突も気を付けましょう](https://qiita.com/cm3/items/6a856c44dd92632aa54f)
[組み込み関数@ Python»ドキュメント»Python標準ライブラリ»](https://docs.python.org/ja/3/library/functions.html)
[class list([iterable])@ Python»ドキュメント»Python標準ライブラリ»](https://docs.python.org/ja/3/library/stdtypes.html#list)

```py
layer_dict = dict([(layer.name, layer) for layer in model.layers[1:]])

# get layers that have an activation
layer_dict = [layer for layer in model.layers[1:]
              if hasattr(layer, 'activation')]

conv_output =  [l for l in model.layers if l.name == layer_name][0].output
```
まあ、なんとなく分かるのですが、以下のようにVGG16のlayer.nameのlistを自動的に取得したいと思いましたが、できなかったので調べました。

```py
name_list=['block1_conv1', 'block1_conv2', 'block1_pool', 'block2_conv1', 
'block2_conv2','block2_pool',  'block3_conv1', 'block3_conv2', 
'block3_conv3','block3_pool',  'block4_conv1', 'block4_conv2', 
'block4_conv3','block4_pool',  'block5_conv1', 'block5_conv2', 
'block5_conv3','block5_pool']
```
【参考】
・①[[python] リストから複数のインデックスを指定して値を取得・削除するまとめ](https://qiita.com/f6wbl6/items/ddd4720a3014a89d922d)
・②[Pythonリスト内包表記の使い方＠note.nkmk.me](https://note.nkmk.me/python-list-comprehension/)
・③[Pythonで文字列のリスト（配列）の条件を満たす要素を抽出、置換＠note.nkmk.me](https://note.nkmk.me/python-list-str-select-replace/)
以下は参考①から引用しています。これを見れば、こういうことはできるよなとは思いますが、ちょっと上記の例からすると面倒くさい。

```py
sentence = ["why","japanese","people","!!"]
dellist = lambda items,indices: [item for idx,item in enumerate(items) if idx not in indices]
del_idx = [0,2] # 削除するインデックス
sentence_deleted = dellist(sentence, del_idx)
print(sentence_deleted)
#['japanese', '!!']

sentence=["1","2","3_2","2_4","5",'!2!']
dellist = lambda items: [item for item in items if "1" not in item and "2" not in item]
sentence_deleted = dellist(sentence)
print(sentence_deleted)
#['5']

dellist = lambda items: [item for item in items if "1" in item or "2" in item or "5" in item]
sentence_deleted = dellist(sentence)
print(sentence_deleted)
#['1', '2', '3_2', '2_4', '5', '!2!']

dellist = lambda items: [item for item in items if "1" or "2" or "5" in item]
sentence_deleted = dellist(sentence)
print(sentence_deleted)
#['1', '2', '3_2', '2_4', '5', '!2!']

dellist = lambda items: [item for item in items if "1" and ("2" or "5") in item]
sentence_deleted = dellist(sentence)
print(sentence_deleted)
#['2', '3_2', '2_4', '!2!']
```
ということで、lambda使ったとしても、最後の二つの書き方は下に記述した理由と同じ理由で間違いにつながるので、止めましょう。
参考②③を見ると、いろいろ書いてありますが、つまり以下のようにも書ける。

```py
name_list = [layer for layer in sentence if "2" in layer]
print(name_list)
#['2', '3_2', '2_4', '!2!']

name_list = [layer for layer in sentence if "2" in layer and "3" in layer]
print(list)
#['3_2']

name_list = [layer for layer in sentence if "2" in layer or "5" in layer]
print(name_list)
#['2', '3_2', '2_4', '5', '!2!']

l = ['oneXXXaaa', 'twoXXXbbb', 'three999aaa', '000111222']
l_in = [s for s in l if 'XXX' in s]
print(l_in)
# ['oneXXXaaa', 'twoXXXbbb']

l_in_not = [s for s in l if 'XXX' not in s]
print(l_in_not)
# ['three999aaa', '000111222']

l_multi = [s for s in l if s.isalpha() and not s.startswith('t')]
print(l_multi)
# ['oneXXXaaa']

l_multi_or = [s for s in l if (s.isalpha() and not s.startswith('t')) or ('bbb' in s)]
print(l_multi_or)
# ['oneXXXaaa', 'twoXXXbbb']

name_list = [layer for layer in sentence if "2" and "3" in layer]
print(name_list)
#['3_2']
#コメントいただいたとおり、if ("2") and ("3" in layer)と演算され
#最初の("2")は常にTrueを返し、後ろの ("3" in layer)のみ反映される。
#"2" を正しく演算するには、以下のように記述する必要がある
name_list = [layer for layer in sentence if "2" in layer and "3" in layer]
print(name_list)
#['3_2']

name_list = [layer for layer in sentence if "2" or "3" in layer]
print(name_list)
#['1', '2', '3_2', '2_4', '5', '!2!']
#この演算も"2"はTrue、or "3" in layerはorがあるので上記の結果となっています
#本来以下の抽出をしたかったので以下のように記述するとやりたい抽出ができます
name_list = [layer for layer in sentence if "2" in layer or "3" in layer]
print(name_list)
#['2', '3_2', '2_4', '!2!']
```
こういうリスト内包表記も上記のlambdaも同じですが、最後の二つの書き方は間違いなので止めましょう。
ということで、無事に以下のコードで、layer.nameのlistが取得できました。
VGG16とVGG19では、以下のように直接求められます。

```py
name_list=[l.name for l in model.layers[1:]]
name_list=name_list[0:len(name_list)-4]
```
ResNet50やXceptionなど長ーいモデルの場合は、上記の第一行を実行したあと、下のコードのようにターゲット文字列を決め打ちにしてその文字列を含むlayer.nameを取得するようにしました。

```py
name_list = [layer for layer in name_list if 'add' in layer] #ResNet50
name_list = [layer for layer in name_list if 'add' in layer] #Xception
name_list = [layer for layer in name_list if 'concat' in layer] #DenseNet121
name_list = [layer for layer in name_list if 'ac' in layer] # InceptionResNetV2
...
```
###まとめ
・lambdaを使う方法をやってみた
・直接抽出する方法をやってみた
・VGG16などのlayer.nameの一括抽出ができた
・予約語や組み込み関数名を変数名に使わないこと

・これを使ってGrad-camの各Layerの動画を作成する
###おまけ
```py
from keras.applications.vgg16 import VGG16, preprocess_input, decode_predictions
from keras.applications.vgg19 import VGG19 #, preprocess_input, decode_predictions
from keras.applications.xception import Xception #, preprocess_input, decode_predictions
from keras.applications.resnet50 import ResNet50 #, preprocess_input, decode_predictions
from keras.applications.densenet import DenseNet121 #, preprocess_input, decode_predictions
from keras.applications.inception_resnet_v2 import InceptionResNetV2 #, preprocess_input, decode_predictions

model = VGG16(weights='imagenet')
model.summary()
model = VGG19(weights='imagenet')
model.summary()
model = Xception(weights='imagenet')  #add
model.summary()
model = ResNet50(weights='imagenet') #add
model.summary()
model = DenseNet121(weights='imagenet') #cancat
model.summary()
model = InceptionResNetV2(weights='imagenet') #ac
model.summary()

size=(299,299)
frame = cv2.imread("cat_dog.png")
preprocessed_input= cv2.resize(frame, size)
preprocessed_input= np.expand_dims(preprocessed_input, axis=0)
predictions = model.predict(preprocessed_input)
for s in range(5):
    top_1 = decode_predictions(predictions)[0][s]
    print('Predicted class:')
    print('%s (%s) with probability %.2f' % (top_1[1], top_1[0], top_1[2]))

name_list=[l.name for l in model.layers[1:]]
name_list = [layer for layer in name_list if 'ac' in layer and 'block' in layer] # InceptionResNetV2
print(len(name_list),name_list)

"""
name_list = [layer for layer in name_list if 'ac' in layer and 'block' in layer] 
39 ['block35_1_ac', 'block35_2_ac', 'block35_3_ac', 'block35_4_ac', 
'block35_5_ac', 'block35_6_ac', 'block35_7_ac', 'block35_8_ac', 'block35_9_ac', 
'block35_10_ac', 'block17_1_ac', 'block17_2_ac', 'block17_3_ac', 'block17_4_ac', 
'block17_5_ac', 'block17_6_ac', 'block17_7_ac', 'block17_8_ac', 'block17_9_ac', 
'block17_10_ac', 'block17_11_ac', 'block17_12_ac', 'block17_13_ac', 
'block17_14_ac', 'block17_15_ac', 'block17_16_ac', 'block17_17_ac', 
'block17_18_ac', 'block17_19_ac', 'block17_20_ac', 'block8_1_ac', 'block8_2_ac', 
'block8_3_ac', 'block8_4_ac', 'block8_5_ac', 'block8_6_ac', 'block8_7_ac', 
'block8_8_ac', 'block8_9_ac']

name_list = [layer for layer in list if 'ac' in layer] 
243 ['activation_1', 'activation_2', 'activation_3', 'activation_4', 
'activation_5', 'activation_9', 'activation_7', 'activation_10', 'activation_6', 
'activation_8', 'activation_11', 'activation_12', 'activation_16', 
'activation_14', 'activation_17', 'activation_13', 'activation_15', 
'activation_18', 'block35_1_ac', 'activation_22', 'activation_20', 
'activation_23', 'activation_19', 'activation_21', 'activation_24', 
'block35_2_ac', 'activation_28', 'activation_26', 'activation_29', 
'activation_25', 'activation_27', 'activation_30', 'block35_3_ac', 
'activation_34', 'activation_32', 'activation_35', 'activation_31', 
'activation_33', 'activation_36', 'block35_4_ac', 'activation_40', 
'activation_38', 'activation_41', 'activation_37', 'activation_39', 
'activation_42', 'block35_5_ac', 'activation_46', 'activation_44', 
'activation_47', 'activation_43', 'activation_45', 'activation_48', 
'block35_6_ac', 'activation_52', 'activation_50', 'activation_53', 
'activation_49', 'activation_51', 'activation_54', 'block35_7_ac', 
'activation_58', 'activation_56', 'activation_59', 'activation_55', 
'activation_57', 'activation_60', 'block35_8_ac', 'activation_64', 
'activation_62', 'activation_65', 'activation_61', 'activation_63', 
'activation_66', 'block35_9_ac', 'activation_70', 'activation_68', 
'activation_71', 'activation_67', 'activation_69', 'activation_72', 
'block35_10_ac', 'activation_74', 'activation_75', 'activation_73', 
'activation_76', 'activation_78', 'activation_79', 'activation_77', 
'activation_80', 'block17_1_ac', 'activation_82', 'activation_83', 
'activation_81', 'activation_84', 'block17_2_ac', 'activation_86', 
'activation_87', 'activation_85', 'activation_88', 'block17_3_ac', 
'activation_90', 'activation_91', 'activation_89', 'activation_92', 
'block17_4_ac', 'activation_94', 'activation_95', 'activation_93', 
'activation_96', 'block17_5_ac', 'activation_98', 'activation_99', 
'activation_97', 'activation_100', 'block17_6_ac', 'activation_102', 
'activation_103', 'activation_101', 'activation_104', 'block17_7_ac', 
'activation_106', 'activation_107', 'activation_105', 'activation_108', 
'block17_8_ac', 'activation_110', 'activation_111', 'activation_109', 
'activation_112', 'block17_9_ac', 'activation_114', 'activation_115', 
'activation_113', 'activation_116', 'block17_10_ac', 'activation_118', 
'activation_119', 'activation_117', 'activation_120', 'block17_11_ac', 
'activation_122', 'activation_123', 'activation_121', 'activation_124', 
'block17_12_ac', 'activation_126', 'activation_127', 'activation_125', 
'activation_128', 'block17_13_ac', 'activation_130', 'activation_131', 
'activation_129', 'activation_132', 'block17_14_ac', 'activation_134', 
'activation_135', 'activation_133', 'activation_136', 'block17_15_ac', 
'activation_138', 'activation_139', 'activation_137', 'activation_140', 
'block17_16_ac', 'activation_142', 'activation_143', 'activation_141', 
'activation_144', 'block17_17_ac', 'activation_146', 'activation_147', 
'activation_145', 'activation_148', 'block17_18_ac', 'activation_150', 
'activation_151', 'activation_149', 'activation_152', 'block17_19_ac', 
'activation_154', 'activation_155', 'activation_153', 'activation_156', 
'block17_20_ac', 'activation_161', 'activation_157', 'activation_159', 
'activation_162', 'activation_158', 'activation_160', 'activation_163', 
'activation_165', 'activation_166', 'activation_164', 'activation_167', 
'block8_1_ac', 'activation_169', 'activation_170', 'activation_168', 
'activation_171', 'block8_2_ac', 'activation_173', 'activation_174', 
'activation_172', 'activation_175', 'block8_3_ac', 'activation_177', 
'activation_178', 'activation_176', 'activation_179', 'block8_4_ac', 
'activation_181', 'activation_182', 'activation_180', 'activation_183', 
'block8_5_ac', 'activation_185', 'activation_186', 'activation_184', 
'activation_187', 'block8_6_ac', 'activation_189', 'activation_190', 
'activation_188', 'activation_191', 'block8_7_ac', 'activation_193', 
'activation_194', 'activation_192', 'activation_195', 'block8_8_ac', 
'activation_197', 'activation_198', 'activation_196', 'activation_199', 
'block8_9_ac', 'activation_201', 'activation_202', 'activation_200', 
'activation_203', 'conv_7b_ac']
"""

```