前提・実現したいこと
pythonで深層学習(CNN,LSTM)の勉強をしています。
jupyter notebookを使って、
サンプルコードの実装で以下のエラーが発生しました。
発生している問題・エラーメッセージ
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-5-8c39078450c0> in <module> 70 71 #キャプションと画像の紐づけ ---> 72 descriptions = load_descriptions(doc) 73 74 #余計な記号を除去する関数 <ipython-input-5-8c39078450c0> in load_descriptions(doc) 65 image_desc = ' '.join(image_desc) #キャプションの単語を文字列に戻す 66 if image_id not in mapping: #その画像名が一つ目ならリストを作成 ---> 67 mapping[image_id] = list() 68 mapping[image_id].append(image_desc) #画像名にキャプションを紐づけてディクショナリに格納 69 return mapping TypeError: 'str' object is not callable
該当のソースコード
Python
1# -*- coding: utf-8 -*- 2from os import listdir 3from pickle import dump 4from keras.applications.vgg16 import VGG16,preprocess_input 5from keras.preprocessing.image import load_img,img_to_array 6from keras.models import Model 7import string 8from pickle import load 9from keras.preprocessing.text import Tokenizer 10from keras.preprocessing.sequence import pad_sequences 11from keras.utils import to_categorical 12from numpy import array 13from keras.layers import Input,Dense,LSTM,Embedding,Dropout 14from keras.layers.merge import add 15from keras.callbacks import ModelCheckpoint 16 17image_directory = 'photo_data'#画像データのパスを指定すること 18caption_data = 'caption.txt'#キャプションデータのパスを指定すること 19train_data = 'train.txt'#トレーニングデータのパスを指定すること 20val_data = 'val.txt'#バリデーションデータのパスを指定すること 21 22# 指定したディレクトリ内の各写真から特徴を抽出する関数 23def extract_features(directory): 24 model = VGG16() 25 model.layers.pop() 26 model = Model(inputs=model.inputs, outputs=model.layers[-1].output) 27 features = dict() #特徴を格納するためのディクショナリ 28 for name in listdir(directory): 29 filename = directory + '/' + name #ファイルから画像を読み込む 30 image = load_img(filename, target_size=(224, 224)) #VGG16用に224×224に成形 31 image = img_to_array(image) #numpy配列に変換 32 image = image.reshape((1, image.shape[0], 33 image.shape[1], image.shape[2])) #モデルに読み込ませるために成形 34 image = preprocess_input(image) #VGGモデルに画像を読み込ませる 35 feature = model.predict(image, verbose=0) #特徴抽出 36 image_id = name.split('.')[0] #画像の名前を取得 37 features[image_id] = feature #画像の名前と特徴を紐付け 38 return features 39 40#特徴抽出 41features = extract_features(image_directory) 42 43#特徴をpklファイルとして保存 44dump(features, open('features.pkl', 'wb')) 45 46#ファイルを読み込む関数 47def load_doc(filename): 48 file = open(filename, 'r', encoding='utf-8') 49 text = file.read() 50 file.close() 51 return text 52 53#キャプションデータの読み込み 54doc = load_doc(caption_data) 55 56##---------エラーの該当場所---------------------- 57 58#キャプションと画像名を紐づけする関数 59def load_descriptions(doc): 60 mapping = dict() 61 for line in doc.split('\n'): 62 tokens = line.split() 63 if len(line) < 2: 64 continue 65 image_id, image_desc = tokens[0], tokens[1:] #最初の単語を画像名、残り全てをキャプションとして読み込む 66 image_id = image_id.split('.')[0] #ピリオドより手前を画像名とする 67 image_desc = ' '.join(image_desc) #キャプションの単語を文字列に戻す 68 if image_id not in mapping: #その画像名が一つ目ならリストを作成 69 mapping[image_id] = list() 70 mapping[image_id].append(image_desc) #画像名にキャプションを紐づけてディクショナリに格納 71 return mapping 72 73#キャプションと画像の紐づけ 74descriptions = load_descriptions(doc) 75 76##-------------------------------------------------------- 77 78#余計な記号を除去する関数 79def clean_descriptions(descriptions): 80 table = str.maketrans('', '', string.punctuation)#記号をリストアップ 81 for key, desc_list in descriptions.items(): 82 for i in range(len(desc_list)): 83 desc = desc_list[i] 84 desc = desc.split() #キャプションを単語に区切る 85 desc = [w.translate(table) for w in desc] #記号を消去 86 desc_list[i] = ' '.join(desc) #キャプションの単語を文字列に戻す 87 88#余計な記号を除去する 89clean_descriptions(descriptions) 90 91#語彙が縮小されたキャプションを保存する関数 92def save_descriptions(descriptions, filename): 93 lines = list() 94 for key, desc_list in descriptions.items(): 95 for desc in desc_list: 96 lines.append(key + ' ' + desc) 97 data = '\n'.join(lines) 98 file = open(filename, 'w', encoding='utf-8') 99 file.write(data) 100 file.close() 101 102#語彙が縮小されたキャプションをtxtファイルとして保存 103save_descriptions(descriptions, 'descriptions.txt') 104 105#画像数のチェック 106print('Loaded: %d ' % len(descriptions)) 107 108#データセットの画像名のリストを作成する関数 109def load_set(filename): 110 doc = load_doc(filename) 111 dataset = list() 112 for line in doc.split('\n'): 113 if len(line) < 1: 114 continue 115 identifier = line.split('.')[0] 116 dataset.append(identifier) 117 return set(dataset) 118 119#トレーニングデータの画像名のリスト作成 120train = load_set(train_data) 121#バリデーションデータの画像名のリスト作成 122val = load_set(val_data) 123 124#画像名とキャプションを紐付けたディクショナリを作成する関数 125def load_clean_descriptions(filename, dataset):#引数datasetはtrainとかvalとか 126 doc = load_doc(filename) 127 descriptions = dict() 128 for line in doc.split('\n'):#一行ずつ読み込む 129 tokens = line.split() #空白で区切る 130 image_id, image_desc = tokens[0], tokens[1:] #最初の単語を画像名、残り全てをキャプションとして読み込む 131 if image_id in dataset: #画像名がデータセット中に指定されていれば以下を実行 132 if image_id not in descriptions: #その画像名が一つ目ならリストを作成 133 descriptions[image_id] = list() 134 desc = 'startseq ' + ' '.join(image_desc) + ' endseq' #キャプションを開始語と終了語で囲む 135 descriptions[image_id].append(desc) #ディクショナリに格納 136 return descriptions 137 138#トレーニングデータのキャプションと画像名を紐付ける 139train_descriptions = load_clean_descriptions('descriptions.txt', train) 140#バリデーションデータのキャプションと画像名を紐付ける 141val_descriptions = load_clean_descriptions('descriptions.txt', val) 142 143#画像の特徴量を読み込む関数 144def load_photo_features(filename, dataset): 145 all_features = load(open(filename, 'rb')) 146 features = {k: all_features[k] for k in dataset}#画像名と特徴量を紐づけてディクショナリに格納 147 return features 148 149#トレーニングデータの特徴量と画像名を紐付ける 150train_features = load_photo_features('features.pkl', train) 151#バリデーションデータの特徴量と画像名を紐付ける 152val_features = load_photo_features('features.pkl', test) 153 154#キャプションのディクショナリをリストにする関数 155def to_lines(descriptions): 156 all_desc = list() 157 for key in descriptions.keys(): 158 [all_desc.append(d) for d in descriptions[key]] 159 return all_desc 160 161#キャプションをKerasのTokenizerで扱うために変換する 162def create_tokenizer(descriptions): 163 lines = to_lines(descriptions) 164 tokenizer = Tokenizer() 165 tokenizer.fit_on_texts(lines) 166 return tokenizer 167 168#tokenizerを準備する 169tokenizer = create_tokenizer(train_descriptions) 170vocab_size = len(tokenizer.word_index) + 1 171 172#最も多くの単語を含むキャプションの長さを計算する関数 173def max_length(descriptions): 174 lines = to_lines(descriptions) 175 return max(len(d.split()) for d in lines) 176 177#最大シーケンス長を計算する 178max_length = max_length(train_descriptions) 179 180#画像と出力単語を紐づける関数 181def create_sequences(tokenizer, max_length, descriptions, photos): 182 X1, X2, y = list(), list(), list()#X1が入力画像、X2が入力語、yがX1とX2に対応する出力語 183 #各画像名でループ 184 for key, desc_list in descriptions.items(): 185 #各画像のキャプションでループ 186 for desc in desc_list: 187 #シーケンスをエンコードする 188 seq = tokenizer.texts_to_sequences([desc])[0] 189 #1つのシーケンスを複数のX、Yペアに分割する 190 for i in range(1, len(seq)): 191 #入力と出力のペアに分割する 192 in_seq, out_seq = seq[:i], seq[i] 193 #行列のサイズを最大の単語数に合わせる 194 in_seq = pad_sequences([in_seq], maxlen=max_length)[0] 195 #出力シーケンス 196 out_seq = to_categorical([out_seq], num_classes=vocab_size)[0] 197 #全てをarrayに格納 198 X1.append(photos[key][0]) 199 X2.append(in_seq) 200 y.append(out_seq) 201 return array(X1), array(X2), array(y) 202 203#トレーニングデータの入力画像、入力語、出力語を紐付ける 204X1train, X2train, ytrain = create_sequences(tokenizer, max_length, train_descriptions, train_features) 205#バリデーションデータの入力画像、入力語、出力語を紐付ける 206X1val, X2val, yval = create_sequences(tokenizer, max_length, val_descriptions, val_features) 207 208#モデルを定義する関数 209def define_model(vocab_size, max_length): 210 #画像の特徴を入力するレイヤ 211 inputs1 = Input(shape=(4096,)) 212 fe1 = Dropout(0.5)(inputs1) 213 fe2 = Dense(256, activation='relu')(fe1) 214 #文章を入力するレイヤ 215 inputs2 = Input(shape=(max_length,)) 216 se1 = Embedding(vocab_size, 256, mask_zero=True)(inputs2) 217 se2 = Dropout(0.5)(se1) 218 se3 = LSTM(256)(se2) 219 #上の二つの出力を統合する部分 220 decoder1 = add([fe2, se3]) 221 decoder2 = Dense(256, activation='relu')(decoder1) 222 outputs = Dense(vocab_size, activation='softmax')(decoder2) 223 #モデルの定義.二つを入力にとって一つを出力する形になる 224 model = Model(inputs=[inputs1, inputs2], outputs=outputs) 225 model.compile(loss='categorical_crossentropy', optimizer='adam') 226 return model 227 228#モデルの定義 229model = define_model(vocab_size, max_length) 230#コールバックを定義する 231filepath = 'model-ep{epoch:03d}-loss{loss:.3f}-val_loss{val_loss:.3f}.h5' 232checkpoint = ModelCheckpoint(filepath, monitor='val_loss', verbose=1, save_best_only=True, mode='min') 233#学習 234model.fit([X1train, X2train], ytrain, epochs=10, verbose=2, callbacks=[checkpoint], validation_data=([X1val, X2val], yval))
試したこと
エラー文で調べてみたのですが、
関数として使っていた名前を文字列で上書きしたことが原因。や
Stringに変換するstrではなくstrと言うオブジェクト(変数)が呼び出されているためにエラーが発生している。
などと書かれていました。
jupyterを再起動すれば治る、などもあり、試してみましたがダメでした。
深層学習、Python初心者で、画像キャンプションを試してみたくてソースコードを丸パクリしただけなので、
正直ソースコードは理解していません。
補足情報(FW/ツールのバージョンなど)
バージョン 3.7.6
サンプルコードが書いてあるサイト
http://pchun.work/%E7%94%BB%E5%83%8F%E3%82%AD%E3%83%A3%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E8%87%AA%E5%8B%95%E7%94%9F%E6%88%90/
よろしくお願いします。
回答3件
あなたの回答
tips
プレビュー