메모장

07.12

잡담연구소 2021. 7. 12. 22:12

개쩌는 거 많이 배움 거의 99.7%가 빠른 98년생 성균관대 소프트웨어공학과 소프트웨어학과 현재 산업기능요원인 대 박상준님이 알려준 거

 

1. argparser가 formatting에 의해 잘리는 문제 

argparser는 길어도 여러 줄로 잘리면 보기 좋지 않다. 그래서 한 줄로 하고 싶은데 블랙 포맷팅에 의해서 자꾸 잘린다.

이럴 때는 내가 포맷이 되지 않기 바라는 줄 위에서 # fmt.off 으로 포맷팅을 꺼주면 된다.

다시 포맷팅이 시작되길 바라는 부분부터 #fmt.on으로 켜주면 된다. 

# fmt: off
parser = argparse.ArgumentParser("hi i am hyerin")
parser.add_argument("--tokenizer-path", type=str, default="tests/data", help="tokenizer model file")
# fmt: on

 

2. ci 문제

위의 꼼수로는 Lint를 피해갈 수 없다; flake8로 검사를 하면 오류가 나게 된다. 

setup.cfg에서 해당 오류를 추가해주면 해당 오류가 ignore 되면서 lint에서 걸리지 않는다. 

[flake8]
max-line-length = 120
ignore = E203, W503, E501

 

3. tf.ragged_tensor

이건 사실 저번 주에 배운 건데,,,dataset.py부터 정리하려고 하니까 보인다.

아래 code는 실행하면 오류가 난다. 왜냐 tensor로 묶으려면 모두 다 shape이 같아야 하는데 현재 다르기 때문이다.

tf.constant([[1, 2], [3], [4, 5, 6]])

이 때, ragged_tensor를 사용하면 해결할 수 있다.

tf.ragged.constant([[1, 2], [3], [4, 5, 6]])

그런데 인생은 역시 순탄치 않다. 텐서플로우 예제와는 다른 상황들이 너무 많이 생긴다. 

서로 길이가 다른 tensor들을 하나로 묶어 새로운 tensor를 만들고 싶다면!?!?!?

아래 처럼 하면 안된다. 위의 예는 텐서가 아니라 그냥 shape이 다른 리스트들이었는데, 아래는 shape가 다른 텐서들이다. 

a = tf.constant([1,2,3])
b = tf.constant([4,5])
tf.ragged.constant([a,b])

요럴 때는 tf.ragged.stack을 쓰면 된다. 

 

4. tensorflow의 dataset

init, getitem,len으로 dataset만들고 dataloader 하던 torch와는 달리 tensorflow에서는 슉 된다. 

https://www.tensorflow.org/api_docs/python/tf/data/Dataset#from_tensors

 

tf.data.Dataset  |  TensorFlow Core v2.5.0

Represents a potentially large set of elements.

www.tensorflow.org

튜플로 묶어줘야 앞,뒤에서 하나씩 뽑아준다. tf에서는 이름은 dataset이지만 generator로 돌아간다. 

dataset = tf.data.Dataset.from_tensor_slices([[1, 2], [3, 4]])
next(iter(dataset))
# <tf.Tensor: shape=(2,), dtype=int32, numpy=array([1, 2], dtype=int32)>
dataset = tf.data.Dataset.from_tensor_slices(([1, 2], [3, 4]))
next(iter(dataset))
# (<tf.Tensor: shape=(), dtype=int32, numpy=1>, <tf.Tensor: shape=(), dtype=int32, numpy=3>)

그러면 batch는 어떻게 주나 -> padded_batch 혹은 batch 쓰면 된다.

output이 (([1,2,3], [4,5]), ([1], [2])) 이런 식일 때, 내가 튜플 내 앞 부분 ([1,2,3], [4,5]) 만 padding을 주고 싶은데 어떻게 해야되는 지몰라서 엄청 헤맸었다. 

일단 print(dataset)을 찍는다. 그러면 output의 shape가 나온다. 그 shape에 따라 내가 채워주고 싶은 모양을 써주면 된다. 

나는 max_length에 맞게 padding을 해줘야 하는 상황이고, 앞의 튜플만 padding을 해주고 싶다. 

-> padded_shape = ({'input_ids' : (max_len, ), "attention_mask" : (max_len, )} , {"score": (), "binary_label": ()} )

# <TensorSliceDataset shapes: ({input_ids: (None,), attention_masks: (None,)}, {score: (), binary_label: ()}), types: ({input_ids: tf.int32, attention_masks: tf.int32}, {score: tf.float32, binary_label: tf.int32})>

ragged tensor로 이뤄진 dataset을 바로 PaddedBatchDataset으로 만들려고 하면 (.padded_batch) 안된다. 

그래서 map을 통해서 mapdataset으로 만들어 준 다음에 padded_batch를 해줘야 한다.

 

5. tensorflow에서의 model save

tensorflow에서 model을 저장하면 신기하게 2개의 파일이 저장된다.

내가 만약 model.ckpt라고 저장했으면 model.ckpt.data-00000-of-00001파일과 model.ckpt.index 가 저장된다.

다시 불러올 때는 torch 처럼 (load에도 방법이 다양하다고 한다.) model instance를 만들어준 다음에 

load_weight(모델 경로)를 적어주면 되는데, 이때 모델 경로는 두 파일의 공통부분인 model.ckpt까지 적어줘야 한다. 

 

6. output이 여러 개 거나, target이 여러 개일 때 model.fit하는 법 

이거 진짜 킹받는다,,,

예를 들어 output이 2개고, target도 2개고, 순서에 맞춰서 loss를 구하고 싶다. 

loss1 = criterion(output1, target1) 

loss2 = criteirion(output2, target2) 같은 상황

이 때 model.fit으로 한 번에 학습하려면,,,!!! output과 target의 이름을 맞춰줘야 한다.

이것 못해서 3시간 날려먹었다 하하핳 사수님이 3분만에 알랴ㅕ주심

 

7. model.compile시 loss 사용법 

이 둘의 차이점은?!?!? 그냥 대 소문자 차이가 아니고~!!!!!

위는 소문자 = 함수고, 아래는 대문자 = 클래스다. 

model.compile 시 loss 부분에 그냥 string으로 써줄 수도 있고, 인스턴스를 불러올 수도 있다. 

"인스턴스"니까 클래스를 불러와야 한다. 

tf.keras.metrics.binary_crossentropy

tf.keras.losses.BinaryCrossentropy

 

8. model.fit 살펴보기 

맨 처음 가장 이해가 안 갔던 부분은 dataset 뒤에 붙어있는 repeat과 epochs , steps_per_epoch

아니 한 에폭 당 하나의 dataset을 다 도는 데 step수가 정해져 있는데, 이게 왜 다 필요하지,,,? 싶었는데

dataset이 엄청나게 많으면 1에폭을 도는데 시간이 엄청나게 걸린다고 한다. 

그래서 dataset을 한 바퀴를 돌지 않아도 1epoch으로 치기 위해 steps_per_epoch이 필요하다 .

dataset이 1000개일 때, batch는 1로 고려하지 않으면, steps_per_epoch = 100 이면 

총 10 epoch을 돌아야 dataset을 한바퀴 전체 다 보는 거고, 내가 만약에 인자로 epoch을 5를 줬으면 dastaset을 500개를 보게 된다. 

1. x가 dataset 형식이면 y, batch_size는 필요하지 않다.  Numpy array(s) or TensorFlow tensor(s) 일 때만 필요하다. 

2. shuffle은 dataset형식이면 먹히지 않는다.

 

9. sys 

sys.exit() : sys모듈에서 프로그램 종료 함수내부 함수가 성공적으로 종료되면 1을 return하고 실패하면 0을 return함 라는 관습이 있다고 대 상준님이 알려주심

sys.exit(train(parser.parse_args()))

'메모장' 카테고리의 다른 글

오류 모음집  (0) 2021.07.11
가상환경 사용하기  (4) 2021.07.11
제주도  (0) 2021.07.11
json load vs loads  (7) 2021.07.07
2021년 절반 지난 기념 회고  (10) 2021.07.04