baseline코드에서는 뭐가 문제인가?
deepsmiles로 변형해서 학습했다. 그 모델로 예측했더니 decoding이 안되는 deepsmiles가 꽤나 발견되었다.
성능은 다음과 같았다.
val_accuracy : 0.1897557218309859
val_similarity : 0.5036391507181318
소요시간은 다음과 같았다.
Time taken for 1 epoch 733.6990127563477 sec
Time taken for 1 epoch 495.8985216617584 sec
kaggle에서 학습시켜보자. deepsmiles로 변경하지 말고!
kaggle tpu가 안써지고.. --> 질문을 올렸으니 답변을 기다려보자.--> 답변은 안올라오고... 기본 모델도 tpu로 돌아가지가 않는다.
왜이러지?
colab에서 계속 에러가 뜬다.
이유는 다음과 같다고 하는데.. 파일이 많아서 그런가 보다. --> 디렉토리 위치를 바꿀 필요가 있겠다.
간혹 drive.mount()가 실패하면서 '시간 초과' 메시지가 표시되는 이유와 drive.mount()로 마운트된 폴더에서 I/O 작업이 실패하는 이유는 무엇인가요?
폴더에 파일 또는 하위 폴더가 너무 많은 경우 Google 드라이브 작업이 시간 초과될 수 있습니다. 수천 개의 항목이 최상위 수준의 '내 드라이브' 폴더에 직접 포함되어 있는 경우 드라이브를 마운트하면 시간 초과가 발생할 수 있습니다. 시간 초과되기 이전에 실패한 시도의 상태가 로컬에 부분적으로 캐시되므로 반복해서 시도하면 성공할 수도 있습니다. 이 문제가 발생할 경우 '내 드라이브'에 직접 포함된 파일 및 폴더를 하위 폴더로 이동해 보세요. drive.mount()가 성공한 후에 다른 폴더의 항목을 읽으면 비슷한 문제가 발생할 수 있습니다. 많은 항목이 포함된 폴더의 항목에 액세스하면 OSError: [Errno 5] Input/output error(python 3) 또는 IOError: [Errno 5] Input/output error(python 2) 같은 오류가 발생할 수 있습니다. 직접 포함된 항목을 하위 폴더로 이동하면 이 문제를 해결할 수 있습니다.
파일 또는 하위 폴더를 휴지통으로 이동하여 '삭제'하는 것으로는 충분하지 않을 수 있습니다. 이 경우 휴지통을 비워야 합니다.
gpu로 학습하니까 더 빠르다. ?
Time taken for 1 epoch 1273.4980828762054 sec
Time taken for 1 epoch 40.786654233932495 sec
1 에폭에서는 더 느렸는데 2에폭부터 40초씩밖에 안결렸다. -->1만개 데이터의 경우.
결과는 참담했다.
val_accuracy : 0.0
val_similarity : 0.054453542468316796
--> deepsmiles로 할때와 차이가 너무 많이 나는데 왜그런걸까?--> deepsmiles로 할때도 마찬가지였다..(처음에 할때 잘못한듯.)
원인파악.
1. smiles로 할때 학습이 제대로 안되는 것일 수 있다. 솔직히 성능이 너무 낮다. --> 아무리 그래도 너무 낮은데.... 다시 다른 데이터로 한번 해볼까 싶다...
2. deepsmiles로 할때. 검증셋에 있는데이터를 잘못 뽑아낸 것일 수 있다. --> 이미 validation set에 있는 데이터를 학습 한 상황일 수 있다.
그러니 testset으로 평가하는것이 정확할 것이다.
testset으로 평가해보자.
어차피 20000개를 다 해야.. 할 수 있으니.. 별 의미가 없나..
똑같은데....
두번째 10000개로 학습을 시도해 보자. (tpu로 학습)
Epoch 1 Batch 0 Loss 2.1918
Epoch 1 Batch 100 Loss 0.9181
Epoch 1 Loss 0.977363
Time taken for 1 epoch 441.1778767108917 sec
Epoch 2 Batch 0 Loss 0.8896
Epoch 2 Batch 100 Loss 0.7751
Epoch 2 Loss 0.827099
Time taken for 1 epoch 376.8460371494293 sec
Epoch 3 Batch 0 Loss 0.8133
Epoch 3 Batch 100 Loss 0.7554
Epoch 3 Loss 0.709328
Time taken for 1 epoch 375.0517899990082 sec
Epoch 4 Batch 0 Loss 0.7076
Epoch 4 Batch 100 Loss 0.7152
Epoch 4 Loss 0.641102
Time taken for 1 epoch 377.52686738967896 sec
Epoch 5 Loss 0.584895 Time taken for 1 epoch 377.9267580509186 sec
Epoch 6 Loss 0.547263 Time taken for 1 epoch 378.9959628582001 sec
Epoch 7 Loss 0.517993 Time taken for 1 epoch 373.67527437210083 sec
Epoch 8 Loss 0.491367 Time taken for 1 epoch 376.7663793563843 sec
Epoch 9 Loss 0.469783 Time taken for 1 epoch 375.89317083358765 sec
Epoch 10 Loss 0.451978 Time taken for 1 epoch 377.5178565979004 sec
val_accuracy : 0.0
val_similarity : 0.10248015707500588
epoch이 너무 낮아서 그런 것같다... 25까지 올려보자.
val_accuracy : 0.005
val_similarity : 0.140476966100008
test_similarity : 0.09024
predict하는데도 거의 3시간이 걸렸다...
일단 test_similarity를 높이기 위한 아니 일단 val_similarity를 높이기 위한 작업을 해보자.
1. token화를 좀 잘 해보자.
단어 단위로 token화를 하면 어떨까 싶다.
Use the Pre-trained SmilesPE Tokenizer
https://github.com/XinhaoLi74/SmilesPE
val_accuracy : 0.0
val_similarity : 0.25415615840452893
test_similarity : 0.23471
smiles로 잘 변경되는 지 확인해보자
이런식으로 된다.
'>'이 end 를 뜻하는 token이므로 '>'전까지를 output으로 채택.
예측 결과가 smiles규칙에 맞는지 검사하는 부분은. rdkit.chem을 이용한다.
chem.molfromsmiles를 이용하여 smiles가 fingerfint로 변환이 되면 규칙에 맞는것이고 아니면 틀린것
규칙에 맞지 않은 index를 저장해 놓고. 그것은 확률이 높은 다른값들로 다시 예측한다. 대부분의 결과가 SMIES규칙에 맞게 될때까지 반복한다.
drop_error = []
while True:
error_idx_dict = {}
for i, e in enumerate(error_idx_):
error_idx_dict[i] = e
img_name_val_, cap_val_ = np.array(img_name_val)[error_idx_], np.array(cap_val)[error_idx_]
dataset_val_ = tf.data.Dataset.from_tensor_slices((img_name_val_, cap_val_))
dataset_val_ = dataset_val_.map(lambda item1, item2: tf.numpy_function(map_func, [item1, item2], [tf.float32, tf.int32]), num_parallel_calls=tf.data.experimental.AUTOTUNE)
dataset_val_ = dataset_val_.batch(BATCH_SIZE)
dataset_val_ = dataset_val_.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)
val_result_ = []
for batch in dataset_val_:
val_result_.extend(predict_(batch[0]).T)
val_result_ = np.array(val_result_)
preds_ = []
for rid in range(val_result_.shape[0]):
pred = ''.join([tokenizer.index_word[i] for i in val_result_[rid] if i not in [0]])
pred = pred.split('>')[0]
preds_.append(pred)
for i, pred in enumerate(preds_):
m = Chem.MolFromSmiles(pred)
if m != None:
preds[error_idx_dict[i]] = pred
drop_idx = np.where(error_idx==error_idx_dict[i])[0]
drop_error.append(drop_idx[0])
error_idx_ = np.delete(error_idx, drop_error)
clear_output(wait=True)
print(len(list(drop_error)), '/', error_idx.shape[0])
if error_idx.shape[0]-len(list(drop_error)) < 10 :
break
ValueError: Tensor's shape (2684, 512) is not compatible with supplied shape (2706, 512)
train_1을 학습시킨 가중치에다가. train_3을 학습을 시키려고 했는데.. 에러가 뜬다. 왜일까?
tokenize한 word의 개수가 다르기 때문이다. 이를 맞추어 주어야한다..
"vocab_size" 가 다르다. --> 이걸 같게 만들어 주고 한번 테스트 해보자! --> ㄴㄴ 그냥 사이즈만 같게 한다고 해서 되는게 아니다. 왜냐하면 train_1의 tarin_1의 word_index와 train_3의 word_index가 다르기 때문이다. --> 그렇다면 train_1의 word_index를 이용해서 train_3의 이미지를 학습할 수 있을 것이다.
왜 1000개에서 validation smilarity가 0.25밖에 나오지 않았을까? 이게 궁금하다. 나는.
1. train set의 개수가 9800개 밖에 되지 않아서. --> 이걸 먼저 시도해보자
2. 코드가 최적화되어지지 않아서. --> tokenize를 좀더 적절하게 할 수 있을 것인가?
1.을 먼저 시도해 보기 위해서는 token을 다시 셋팅 해주어야한다. 어차피 90만개를 다 학습할것이므로 90만개를 다 불러와서 시켜보자. -->90만개에 대한 smileset은 이미 주어져있으므로. 아니면 180만개로 시도해볼까?
token
deepsmiles나 SELFIES를 로 변환해서 tokenize하는 것보다는 "Pre-trained SmilesPE Tokenizer" 를 쓰는 것이 더 나을듯하다.
CID-SMILES에서 상위 10만개를 이용해서 token을 만들어 낸 결과 1392개밖에 나오지 않았다.
train_1과 train_3을 이용했을때는 1만개인데 약 2700개가 나왔었는데 왜 그런 것일까? --> CID_SMILES에 비슷한것끼리 몰려있기 때문일 가능성이 높다. max_length = 360이 나왔는데.. 너무 긴 smiles까지 넣어서 그렇다. 그래서 smiles길이가 70이하인 애들로만 filtering 해 주었도너 max_length = 40이 되었다.
100만개를 이용해서 token을 만들어 낸 결과
1000만개를 이용해서 token을 만들어 낸 결과
-->메모리가 부족해서 못함
1억개를 다 이용해서 token을 만들어 낸 결과
-->메모리가 부족해서 못함
--> smiles 길이가 70이하인 것들만 추출하니 94138266 개.
-->token을 만드는 중.
dacon에서 주어진 trainset 약 90만 8천개를 이용해서 token을 만들어낸 결과
train_set 90만 8천개와, 1억1천만개 smiles의 교집합의 개수.. 너무 적다.
38746 -->무시해도 되는 수준이다.
tokenizer를 우선 만들어 보자.
90만개 +45만개를 이용하여 token을 만들어낸 결과
기존 train_set과 token이 별반 다를것이 없다...80개정도 들어났을 뿐
학습할때 10만개로 25epoch학습하고 또 10만개로 25epoch학습하고 이런식으로 해도 되나?
33509초가 소요되었는데 이는 상당히 오래걸린 것이다. 9.3시간.
예측하는데 걸린시간
14시 57분 시작
17시 39분 종료
이용한 모델은 90만 7천개로 1epoch학습한 모델. val_similarity : 0.37479 test smillarity : 0.24421 --> val_smiliarity는 10만개보다 많이 향상되었다.
loss가 왜 더 낮아지지 않을까 ..베이스라인에선 loss가 몇 이였나? 정상이다.
3epcoh결과 : val_similarity : 0.49 test smillarity : 0.24 ...val_smiliarity는 엄청 향상되었는데 왜.. test는 향상되지 않았을까?...
새 데이터를 써야하는것 같다.
--> overfiiting일 가능성이 높다. tokenizer를 만들때. 전부 이용하기 때문이다.