답변:
여전히 궁금한 사람들은 데이터를 섞을 수 있습니다. 하나의 파일에 TF 레코드를 사용하면 주문을 섞을 수 없습니다. 이것은 일반적으로 SGD에 필요합니다.
그러나 샤드를 사용하면 샤드 순서를 섞을 수 있으므로 개별 TFRecord에 액세스 할 수있는 것처럼 데이터를 섞는 것을 대략적으로 계산할 수 있습니다. 이것은 아무것도 아닌 것보다 분명히 낫고, 더 많은 샤드가 많을수록이 근사치가 더 좋습니다.
대안은 데이터를 복제하거나 TFRecords를 전혀 사용하지 않고 데이터를 미리 섞는 것입니다.
TFRecord 파일을 샤드로 분할하면 메모리에 맞지 않는 대용량 데이터 세트를 섞을 수 있습니다.
디스크에 수백만 개의 교육 예제가 저장되어 있고이를 훈련 프로세스를 통해 반복적으로 실행하려고한다고 가정하십시오. 또한 훈련 데이터를 반복 할 때마다 (즉, 각 에포크) 데이터를 완전히 임의의 순서로로드하려고한다고 가정하십시오.
한 가지 방법은 훈련 예제 당 하나의 파일을 만들고 모든 파일 이름 목록을 생성하는 것입니다. 그런 다음 각 에포크의 시작 부분에서 파일 이름 목록을 섞고 개별 파일을로드합니다. 이 방법의 문제점은 디스크의 임의 위치에서 수백만 개의 파일을로드한다는 것입니다. 특히 하드 디스크 드라이브에서 속도가 느려질 수 있습니다. 임의의 위치에서 수백만 개의 작은 파일을로드하는 경우 RAID 0 어레이라도 속도에 도움이되지 않습니다. 네트워크 연결을 통해 파일에 액세스하면 문제가 더욱 악화됩니다.
또 다른 방법은 하나의 큰 TFRecord 파일에서 학습 예제를 순서대로 읽고 셔플 버퍼를 사용하여 메모리에서 예제를 섞습니다. 그러나 셔플 버퍼는 일반적으로 CPU에서 사용 가능한 DDR 메모리보다 클 수 없습니다. 또한 셔플 버퍼가 데이터 세트보다 훨씬 작 으면 데이터를 제대로 섞을 수 없습니다. 데이터는 "로컬로"섞이지 만 "글로벌로"섞이지 않을 수 있습니다. 즉, 데이터 세트의 시작부터의 예는 데이터 세트의 끝에서 나온 예와 섞이지 않을 수 있습니다.
좋은 해결책은 데이터 세트를 여러 TFRecord 파일 (샤드라고 함)로 분할하여 위의 두 가지 접근 방식의 균형 잡힌 조합을 사용하는 것입니다. 각 에포크 동안 샤드 파일 이름을 셔플하여 전체 셔플 링을 얻고 셔플 버퍼를 사용하여 로컬 셔플 링을 얻을 수 있습니다. 균형이 잘 잡히면 샤드 크기가 디스크 속도 문제를 방지 할만큼 충분히 커지지 만, 샤드 버퍼는 셔플 버퍼로 적절히 섞을 수 있도록 샤드 크기를 작게 유지합니다.
정확한 단계는 다음과 같습니다.
TFRecords 파일을 여러 샤드로 분할하면 기본적으로 3 가지 장점이 있습니다.
.shuffle()
하나의 큰 tfrecord 파일이있는 경우 방법은 이상적인 솔루션이 아닙니다. 큰 버퍼 크기를 사용하지 않으면 섞인 출력이 원래 순서와 다소 관련이 있습니다. 큰 데이터 세트가있는 경우 tfrecord에 저장하거나 샤드로 분할하기 전에 데이터를 사전 셔플 링해야한다고 생각합니다.