본문 바로가기
LG 헬로비전 DX DATA SCHOOL/Python

TensorFlow

by 황밤 2023. 9. 15.
728x90
반응형

**TensorFlow


1.개요


=>구글이 만든 딥 러닝에 초점을 맞춘 라이브러리
=>2015년 11월 오픈 소스로 전환했고 현재 가장 인기있는 딥 러닝 라이브러리
=>GPU를 지원하고 분산 컴퓨팅도 지원
=>일정의 JIT(Just-In-Time) 컴파일러를 사용해서 속도를 높이고 메모리 사용량을 줄여서 수행
사용하지 않는 노드를 가지치기를 해서 사용량을 최적화
=>Tensorflow를 이용해서 훈련 한 모델을 다른 환경에서 실행 할 수 있음
웹 브라우저 나 안드로이드에서 PC에서 훈련한 모델을 가져와서 사용이 가능
Tensorflow Lite 버전을 이용하면 안드로이드 기기 내에서도 훈련이 가능하지만 안드로이드 기기는 일반적으로 컴퓨팅 파워가 부족하기 때문에 대부분 훈련은 PC에서 수행하고 그 모델을 안드로이드 기기에 맞게 컨버팅 한 후 사용하는 방식이 많이 사용됩니다.
=>고성능 Optimizer 함수를 제공
=>API


Python 이외의 다른 언어로 만들어진 API를 제공
시각화를 위한 Tensorboard 제공
Tensorflow Hub를 이용해서 여러 모델을 제공받을 수 있고 업로드 할 수 있습니다.
슬랙 채널도 운영


=>연산
C++ 코드로 만들어져 있음
연산은 커널이라고 하는 여러 구현을 가지게 되며 커널은 CPU, GPU, TPU에 최적화되어있음
GPU 나 TPU(딥러닝에 특화)는 계산을 아주 작은 단위로 분할해서 동시에 수행하도록 설계된 Chip

 



2.Tensorflow 사용


=>Tensor는 numpy 의 ndarray 와 유사한데 보통의 경우는 다차원 배열이지만 스칼라 값도 가질 수 있음
=>Tensor 가 연산 사이에서 흐른다라는 의미로 Tensorflow 라고 명명

 


1)Tensor 와 연산

=>tf.constant(): 변경 불가능한 Tensor 생성: 만드는 방식은 함수 안에 데이터만 대입하면 됩니다.

#스칼라 텐서를 생성
t1 = tf.constant(42)
print(t1)
#배열을 가지고 생성
t2 = tf.constant([[1, 2, 3], [4, 5, 6]])
print(t2)



=>연산 방법은 numpy 의 ndarray 와 유사한데 내부적으로 CPU 나 GPU 또는 TPU 연산 최적화를 수행해 줍니다.

#연산
print(t2 + 10) #broadcast 연산 수행
print(tf.square(t2))
print(t2 @ tf.transpose(t2))



=>python은 연산자 오버로딩(Overloading - 이름은 동일하고 매개변수의 개수 나 자료형을 다르게 만드는 것 

 

python에서는 개수는 변화가 안되고 자료형만 변경 가능)을 지원 - 연산자도 함수
python에서는 +를 호출하면 __add__ 라는 Magic 함수를 호출
tensorflow에서는 tf.add 라는 함수를 호출하는 것이 됩니다.
사용되는 함수들은 numpy 와 이름이 유사하지만 다른 것들도 있습니다.
이름이 다른 경우는 동작방식이 다르기 때문입니다.
numpy에서는 행렬을 전치할 때 T 라는 속성을 사용하지만 tensorflow에서는 transpose 라는 함수를 이용
Tensorflow에서는 전치된 데이터의 복사본을 리턴하지만 numpy에는 전치된 View 일 뿐
Tensorflow 함수의 이름을 축약해 놓은 것이 있습니다.
tf.math.add() 와 tf.add()는 동일한 함수

 


Keras API의 저수준 함수들은 keras.backend에 포함되어 있습니다.

from tensorflow import keras
K = keras.backend
K.square(K.transpose(t2)) + 10



=>Tensor 와 numpy
Tensor 연산에 numpy 배열을 사용하는 것이 가능
Tensor를 numpy로 변환하는 것이 가능: numpy()

import numpy as np
ar = np.array([2, 3, 4])
print(np.sum(ar))

#numpy 배열을 가지고 Tensor 생성
x = tf.constant(ar)
print(x)
#Tensor를 numpy 배열로 변경
print(type(x.numpy()))


#numpy 와 Tensor 연산에 데이터 공유 가능
print(tf.square(ar))
print(np.square(x))



2)타입 변환
=>Tensorflow는 묵시적(자동) 형 변환이 없음
=>자료형이 연산이 불가능
=>cast 라는 함수를 이용해서 형 변환이 가능
Tensorflow.cast(데이터, 변경할 자료형)

try:
    print(tf.cast(tf.constant(10), tf.float32) + tf.constant(10.3))
except tf.errors.InvalidArgumentError as ex:
    print(ex)

3)변수 생성
=>값을 변경가능하도록 만들고자 하면 constant 대신에 Variable로 만들면 됩니다.
=>Tensorflow에 관련된 함수를 직접 만든다든가 할 때 필요
=>값을 수정할 때는 assign 함수를 이용
#변수 생성
v = tf.Variable([[1, 2, 3], [4, 5, 6]])
print(v)
v.assign(5 + v)
print(v)
v[0,0].assign(42)
print(v)

4)Data 구조
=>종류
Sparse Tensor(tf.SparseTensor): 0이 아주 많은 Tensor를 효율적으로 표현하기 위한 연산을 제공하는 자료형

tf.TensorArray: Tensor의 list 버전으로 고정된 길이를 가지지만 동적으로 변경이 가능하고 대신 속해있는 모든 Tensor의 크기 와 자료형이 일치해야 합니다.

ragged tensor: 배열의 배열 - 행렬은 아니고 배열 안의 각각의 배열은 크기가 달라도 됨

string tensor

set

queue

=>string tensor

tf.string 타입의 Tensor
바이트 문자열을 의미
유니코드 형태의 문자열을 대입하면 내부적으로 UTF-8로 인코딩해서 저장
tf.string 은 기본 자료형이라서 문자열의 길이를 Tensor에 가지고 있지 않은데 문자열의 길이를 같이 보관하고자 하는 경우는 유니코드 Tensor 로 변경해야 합니다.
기본 자료형은 데이터 1개를 갖는 Scala Type 입니다.

tf.constant("안녕하세요") #하나의 기본 자료형으로 인코딩 해서 저장

=>tf.TensorArray

  • 텐서의 배열
  • 기본적으로 고정된 길이를 가지지만 동적으로 크기 변경이 가능 - 예전에는 이런 구조를 Vector라고 부름
  • 생성할 때 하나의 요소 자료형 과 크기를 설정합니다.
  • write 함수를 이용해서 데이터를 수정 및 설정
#Tensor 배열 - 실수 3개를 저장하는 텐서 배열을 생성
array = tf.TensorArray(dtype=tf.float32, size=3)
#3개의 데이터 저장
array = array.write(0, tf.constant([1.0, 2.0]))
array = array.write(1, tf.constant([3.0, 4.0]))
array = array.write(2, tf.constant([5.0, 6.0]))
#첫번째 데이터 읽기
print(array.read(1))



=>ragged tensor(tf.ReggedTensor)
비정형 중첩 가변 길이 리스트
각 목록의 길이가 다른 2차원 배열

#ragged tensor: 각 배열의 길이가 달라도 됩니다.
ar = tf.ragged.constant([[10, 20], [30, 40, 50], [50, 60]])
print(ar)



=>sparse tensor(tf.SparseTensor)
대부분 0으로 채워진 Tensor

0이 아닌 데이터의 인덱스 와 값으로 생성

#희소 텐서 생성
#3행 4열의 행렬을 만들고 indices 자리에 values의 값을 순서대로 배정한
#희소 행렬
s = tf.SparseTensor(indices=[[0,1], [1, 0], [2, 3]],
                             values = [1.0, 2.0, 3.0],
                    dense_shape=[3, 4])
print(tf.sparse.to_dense(s))



=>set: 중복된 데이터를 허용하지 않는 집합
각 행 별로 연산을 수행합니다.
집합 연산이 가능합니다.

s1 = tf.constant([[1, 2, 3, 1, 1], [2, 4, 5, 8, 11]])
s2 = tf.constant([[1, 2, 3, 4, 4], [2, 7, 5, 8, 9]])
print(s1)
print(s2)
print(tf.sparse.to_dense(tf.sets.union(s1, s2)))
#set 연산은 배열로 리턴하기 때문에 연산의 결과 각 배열의 데이터 개수가 다르면 뒤에 0을 채워서 동일한 개수로 맞춰 줍니다.
#1행을 합집합하면 데이터 4가지가 되고 2행은 7가지가 되므로 1행의 결과 뒤에 0을 3개 추가


=>queue

  • 자료구조 상의 큐의 FIFO 구조(First In First Out 구조)
  • 포인터가 2개인 배열 구조
  • 한쪽 포인터에서는 데이터를 삽입하고 다른 포인터에서는 데이터를 삭제
  • FIFOQueue: 기본 큐
  • PriorityQueue: 우선순위가 부여된 큐
  • RandomShuffleQueue: 랜덤하게 섞어주는 큐
  • PaddingFIFOQueue: 패딩을 추가하여 크기가 다른 원소의 배치를 만드는 큐



5)Graph
=>Tensorflow는 계산 그래프 구조를 통해서 노드에서 노드로 이동을 합니다.
=>컴퓨터 공학에서 그래프는 Node 와 Edge로 구성된 자료구조를 의미하는데 Tensorflow에서는 노드에 Operator, Variable, Contant 등을 정의하고 노드 들 간의 연결인 Edge를 통해서 Tensor를 주고 받으면서 연산을 수행한다라고 합니다.
=>프로그램을 작성할 때는 그래프를 생성하고 실행하는 순서로 작성

6)함수
=>python 코드로 만든 함수를 Tensorflow 함수로 변경을 하고자 하는 경우는 상단에 tf.function이라는 데코레이터를 추가하면 됩니다.

7)오토 그래프 와 트레이싱
=>Tensorflow를 사용하는 프로그램을 작성하면 Tensorflow에서는 Python 함수의 소스 코드를 분석해서 for, while, if, break, continue, return 같은 제어문을 모두 찾는데 이 과정을 오토 그래프라고 합니다.
=>찾은 제어문을 Tensorflow 코드로 변경을 합니다.
=>이렇게 변환된 Tensorflow 코드를 실행합니다.
=>Tensorflow는 병렬 처리를 수행하기 때문에 병렬 처리가 가능한 부분이 있으면 자신의 방식으로 변환해서 처리하는 것이 효율적이기 때문입니다.
=>이런 변환이 가능한 함수를 만들 때 @tf.function 이라는 데코레이터를 사용했는데 keras는 이 데코레이터가 없더라도 함수가 자신의 모델에 사용이 되면 변환 작업을 자동으로 수행합니다.
=>규칙
numpy 나 파이썬 표준 라이브러리를 포함한 다른 라이브러리를 호출하면 트레이싱 과정에서 실행될 것데 이런 함수들 보다는 텐서플로우의 내장함수를 사용하는 것이 효율이 좋습니다.
함수 안에서 텐서플로우 변수에 새로운 데이터를 할당할 때는 = 대신에 assign을 사용하는 것을 권장

성능면에서는 반복문보다 벡터화 된 표현을 사용하는 것이 좋음

#텐서플로우 코드 최적화가 가능하도록 작성
@tf.function
def tf_cube(x):
  print(x)#값의 변화가 없는 구문이므로 함수 호출전에 전부 수행해버림
  return x ** 3 #텐서플로우 함수 호출 구문으로 변경되서 실행

result = tf_cube(tf.constant(2.0))
print(result)



8)난수 생성
=>균등한 분포(모든 숫자가 나올 확률 동일)에서 난수를 생성
tf.random.uniform([데이터 차원], 최소값, 최대값) 

=>정규 분포에서 난수를 생성
tf.random.normal([데이터 차원],  평균, 표준편차) 

 



3.뉴런 생성


1)뉴런(퍼셉트론)의 구조
입력 -> 뉴런 -> 출력
=>신경망에서는 뉴런이 여러 개가 되고 이를 여러 개의 Layer로 구성
가중치(w) 예측 = f(X * w)
입력(X)   ------> 활성화 함수 ----> 출력

=>입력이나 가중치, 출력은 int 나 float을 많이 사용
=>활성화 함수는 예측된 값을 가지고 출력 값을 정하는 함수
=>학습을 할 때 변하는 것은 가중치
가중치는 초기화를 통해서 랜덤한 값을 설정한 후 학습 과정에서 일정한 값으로 수렴
=>활성화 함수
출력을 결정짓는 함수로 비선형 함수를 선호: 시그모이드 나 ReLU를 사용

2)뉴런 생성

# 활성화 함수 - 시그모이드
import math

def sigmoid(x):
  return 1 / (1 + math.exp(-x))

#입력 값
X = 1
#타겟
y = 0
#가중치를 랜덤하게 설정
w = tf.random.normal([1], 0, 1)
#출력
output = sigmoid(X * w)
print("예측값:", output)


=>실제 값 과 예측 값의 차이가 error(residual 이라고도 하는데 이 경우는 잔차로 번역)
=>뉴런이 학습한다는 것은 error를 0에 가깝게 가중치를 수정하는 것
=>경사 하강법에서는 w 에 입력 과 학습률 과 에러를 곱한 값을 더해주는 형태로 작업
학습률은 w를 업데이트 하는 정도를 의미하는데 너무 큰 값으로 설정하면 학습은 빨라지지만 적정한 수치를 벗어날 우려가 있고 너무 작으면 학습이 너무 느림

=>경사 하강법 구현
#경사 하강법
for i in range(1000):
  output = sigmoid(X * w)
  error = y - output
  w = w + X * 0.1 * error #학습률을 0.1로 설정
  if i % 50 == 0:
    print(i, output, error)



=>경사 하강법 문제 발생

#가중치 만을 곱하게 되는 경우 Input이 0이면 가중치가 변경되지 않음
X = 0
y = 1
w = tf.random.normal([1], 0, 1)
for i in range(1000):
  output = sigmoid(X * w)
  error = y - output
  w = w + X * 0.1 * error #학습률을 0.1로 설정
  if i % 50 == 0:
    print(i, output, error)


=>Input이 모두 0인 경우를 고려해서 편향(Bias)을 추가

#경사 하강법 문제 발생 - 편향을 추가해서 해결
X = 0
y = 1
w = tf.random.normal([1], 0, 1)

b = tf.random.normal([1], 0, 1)
for i in range(1000):
  output = sigmoid(X * w + 1 * b)
  error = y - output
  w = w + X * 0.1 * error #학습률을 0.1로 설정
  b = b + 1 * 0.1 * error
  if i % 50 == 0:
    print(i, output, error)



3)AND 연산을 뉴런으로 구현
=>진리표
0 , 0 -> 0
0 , 1 -> 0
1 , 0 -> 0
1 , 1 -> 1

=>입력이 3 개 출력은 1 개

#AND를 뉴런으로 구현
import numpy as np

X = np.array([[0,0], [0,1], [1,0], [1,1]])
y = np.array([[0], [0], [0], [1]])
b = tf.random.normal([1], 0, 1)
#입력이 2개라서 가중치를 2개 생성
w = tf.random.normal([2], 0, 1)

for i in range(2000):
  #오차의 합계를 저장할 변수
  error_sum = 0
  #모든 입력을 대입해서 수행
  for j in range(4):
    output = sigmoid(np.sum(X[j] * w) + 1 * b)
    error = y[j][0] - output
    w = w + X[j] * 0.1 * error
    b = b + 1 * 0.1 * error
    error_sum += error
  if i % 100 == 0:
    print(i, error_sum)

=>실제 값과 훈련한 모델의 가중치 와 편향을 가지고 나온 값을 비교
#predict
for i in range(4):
  print("X:", X[i], "Y:", y[i], "Predict:", sigmoid(np.sum(X[i]*w)+b))

#0 0, 0 1, 1 0 일 때는 0에 근사치가  1 1 일 때는 1에 근사치가 도출되어야 합니다.



=>OR를 뉴런으로 구현

import numpy as np

X = np.array([[0,0], [0,1], [1,0], [1,1]])
y = np.array([[0], [1], [1], [1]])
b = tf.random.normal([1], 0, 1)
#입력이 2개라서 가중치를 2개 생성
w = tf.random.normal([2], 0, 1)

for i in range(2000):
  #오차의 합계를 저장할 변수
  error_sum = 0
  #모든 입력을 대입해서 수행
  for j in range(4):
    output = sigmoid(np.sum(X[j] * w) + 1 * b)
    error = y[j][0] - output
    w = w + X[j] * 0.1 * error
    b = b + 1 * 0.1 * error
    error_sum += error
  if i % 100 == 0:
    print(i, error_sum)

#predict
for i in range(4):
  print("X:", X[i], "Y:", y[i], "Predict:", sigmoid(np.sum(X[i]*w)+b))



3)XOR를 하나의 뉴런으로 작성

#XOR를 뉴런으로 구현
import numpy as np

X = np.array([[0,0], [0,1], [1,0], [1,1]])
y = np.array([[0], [1], [1], [0]])
b = tf.random.normal([1], 0, 1)
#입력이 2개라서 가중치를 2개 생성
w = tf.random.normal([2], 0, 1)

for i in range(2000):
  #오차의 합계를 저장할 변수
  error_sum = 0
  #모든 입력을 대입해서 수행
  for j in range(4):
    output = sigmoid(np.sum(X[j] * w) + 1 * b)
    error = y[j][0] - output
    w = w + X[j] * 0.1 * error
    b = b + 1 * 0.1 * error
    error_sum += error
  if i % 100 == 0:
    print(i, error_sum)

#predict
for i in range(4):
  print("X:", X[i], "Y:", y[i], "Predict:", sigmoid(np.sum(X[i]*w)+b))



4)여러 개의 뉴런으로 XOR 문제를 해결
=>하나의 뉴런으로는 XOR문제를 해결할 수 없지만 뉴런을 여러 개 쌓으면 이 문제를 해결할 수 있음

X = np.array([[0,0], [0,1], [1,0], [1,1]])
y = np.array([[0], [1], [1], [0]])

model = tf.keras.Sequential([
    tf.keras.layers.Dense(units=2, activation='sigmoid', input_shape=(2,)),
    tf.keras.layers.Dense(units=1, activation='sigmoid')
])

model.compile(optimizer=tf.keras.optimizers.SGD(lr=0.1), loss='mse')

model.summary()

history = model.fit(X, y, epochs=10000, batch_size=1)

model.predict(X)



=>위의 구조는 입력 2개 뉴런 2개로 구성된 첫번째 층 과 두번째는 첫번째 층의 출력인 2개의 입력을 받아서 하나을 출력
입력 피처가 뉴런 각각에 모두 대입되고 거기서 나온 가중치를 가지고 다음 뉴런에서 입력으로 사용해서 가중치를 수정
각각의 레이어를 통과할 때 마다 편향이 추가

=>가중치를 확인

for weight in model.weights:
  print(weight)



#가중치는 Layer 별로 출력이 되는데 입력의 개수 와 뉴런의 개수를 곱한만큼 만들어 집니다.

=>훈련을 한 후 리턴되는 데이터에는 훈련에 관련된 정보가 전부 저장됩니다.
손실의 값을 확인할 수 있습니다.

#loss 값을 시각화
import matplotlib.pyplot as plt
plt.plot(history.history['loss'])

 



4.Tensorflow Data API


1)개요
=>Deep Learning에서는 아주 큰 규모의 Dataset을 가지고 훈련해야 하는 경우가 많은데 Data를 로드하고 Preprocessing 하는 작업이 번거로운데 이러한 작업을 쉽게 할 수 있도록 해주는 API 가 Data API
=>Multi Threading, Queue, Prefetch 같은 처리를 수행
데이터를 읽을 때 나누어서 순서에 상관없이 읽어도 되는 것인지 아니면 순서가 있는 건지 나누어서 읽어야 하는 건지를 판단하는 것이 중요
=>csv, 관계형 데이터베이스, 구글의 big query 등에서 데이터를 읽어오는 기능을 제공
=>원 핫 인코딩 같은 전처리를 읽으면서 수행하는 것도 가능

2)메모리에서 Dataset을 생성

#메모리에서 데이터 생성
X = tf.range(10)
dataset = tf.data.Dataset.from_tensor_slices(X)
print(dataset)

dataset = tf.data.Dataset.range(10)
print(dataset)
for item in dataset:
  print(item)

dataset = tf.data.Dataset.range(10)
dataset = dataset.repeat(3).batch(8, drop_remainder=True) #3번 반복하고 8개씩 묶어서 8개가 안되는 것은 버림
for item in dataset:
  print(item)



3)data shuffling
=>경사 하강법은 훈련 세트에 있는 샘플이 독립적이고 동일한 분포일 때 최고의 성능을 발휘
=>shuffle 이라는 함수를 이용하면 데이터를 랜덤하게 추출할 수 있는데 Dataset 에서 batch_size 만큼 데이터를 랜덤하게 추출하고 아이템 요청이 오면 버퍼에서 랜덤하게 하나를 꺼내서 반환하고 Dataset에서 새로운 아이템을 버퍼에 제공하는 형태로 동작
=>버퍼의 크기를 크게 만드는 것이 효과를 높이는 방법인데 버퍼의 크기가 너무 크면 메모리에 부담을 주게됩니다.
=>데이터를 일정한 순서대로 제공할려면 랜덤 시드를 상수로 부여해야 합니다.

#셔플링
#0 ~ 29까지의 숫자를 가지고 텐서를 생성
dataset = tf.data.Dataset.range(30)
#버퍼의 크기는 5로 설정하고 seed는 42로 고정해서 일정하게 배치한 후 6개씩 묶어서 사용
dataset = dataset.shuffle(buffer_size=5, seed=42).batch(6)
for item in dataset:
  print(item)


=>메모리 용량보다 큰 대규모 Dataset은 버퍼가 Dataset 보다 작기 때문에 지금까지의 방법으로는 충분하지 않아서 이런 경우에는 원본 데이터 자체를 섞어야 합니다.
리눅스에서는 shuf 명령을 활용

=>한 번 훈련하는 과정을 epoch 라고 하는데 epoch 마다 데이터를 섞어 주는 것이 좋습니다.
epoch에서 데이터를 섞지 않는다면 데이터에 포함된 가짜 패턴(편향)이 학습되어 버림

=>하나의 파일에 존재하는 데이터는 동일한 방식으로 처리되므로 딥러닝이나 머신러닝에 사용해야 하는 데이터를 파일에 저장할 때는 여러 개의 파일로 데이터를 나누고 학습을 할 때 파일들의 일부분을 랜덤하게 읽어서 학습에 사용하는 것도 좋은 방법입니다.

#데이터를 읽어서 나누어 저장한 후 읽어오기
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import fetch_california_housing

housing = fetch_california_housing()

#train-훈련, valid-훈련 중 검증, test-모델을 훈련한 후 확인
X_train_full, X_test, y_train_full, y_test = train_test_split(housing.data, 
                                                    housing.target.reshape(-1, 1),
                                                    random_state=42)
X_train, X_valid, y_train, y_valid = train_test_split(X_train_full, y_train_full,
                                                      random_state=42)

scaler = StandardScaler()
scaler.fit(X_train)

X_mean = scaler.mean_
X_std = scaler.scale_
print(X_mean)
print(X_std)



#데이터를 여러 개의 파일로 나누어서 저장하는 함수
#매개변수는 데이터, 파일의 맨 앞의 공통된 이름, 헤더 포함 여부, 파일의 개수
def save_to_multiple_csv_files(data, name_prefix, header=None, n_parts=10):
  #파일을 저장할 디렉토리 생성
  housing_dir = os.path.join("Datasets", "housing")
  os.makedirs(housing_dir, exist_ok=True)
  #파일 경로 패턴 생성
  path_format = os.path.join(housing_dir, "my_{}_{:02d}.csv")

  filepaths = [] #파일 경로를 저장할 리스트
  m = len(data) #데이터의 개수

  #m 개수 만큼 숫자열을 만든 후 n_parts 개수 만큼 분할해서 
  #분할한 그룹 번호는 file_idx 에 행 번호는 row_indices에 저장
  for file_idx, row_indices in enumerate(np.array_split(np.arange(m), n_parts)):
    #실제 파일 경로 생성
    part_csv = path_format.format(name_prefix, file_idx)
    filepaths.append(part_csv)

    #데이터 기록
    with open(part_csv, "wt", encoding='utf-8') as f:
      if header is not None:
        f.write(header)
        f.write("\n")
        #행 인덱스를 가지고 데이터를 순회하면 각 데이터를 ,로 구분해서 작성
        for row_idx in row_indices:
          f.write(",".join([repr(col) for col in data[row_idx]]))
          f.write("\n")
  return filepaths

train_data = np.c_[X_train, y_train]
valid_data = np.c_[X_valid, y_valid]
test_data = np.c_[X_test, y_test]

headers_cols = housing.feature_names + ["MedianHouseValue"]
header = ",".join(headers_cols)

train_filepaths = save_to_multiple_csv_files(train_data, "train", header, n_parts=20)
valid_filepaths = save_to_multiple_csv_files(valid_data, "valid", header, n_parts=10)
test_filepaths = save_to_multiple_csv_files(test_data, "test", header, n_parts=10)

#파일 이름을 랜덤하게 가져오기
filepath_Dataset = tf.data.Dataset.list_files(train_filepaths)
for filepath in filepath_Dataset:
  print(filepath)


#5개의 파일에서 번갈아가면서 데이터를 읽어오기
n_readers = 5

#파일 경로에 있는 내용을 5개씩 번갈아가면서 줄단위로 읽어오기
dataset = filepath_Dataset.interleave(
    lambda filepath: tf.data.TextLineDataset(filepath).skip(1), cycle_length=n_readers)

for line in dataset.take(5):
  print(line.numpy())



=>intereave는 기본적으로 병렬화를 하지 않음
num_parallel_calls 매개변수에 코어의 개수를 지정하면 동시에 읽어옵니다.
개수를 설정을 못하는 경우에는 tf.data.experimental.AUTOTUNE을 지정하면 가능한 최대 코어 개수로 설정을 하게 됩니다.

4)Tensorflow Dataset 프로젝트
=> https://www.tensorflow.org/datasets?hl=ko 에 가면 널리 사용되는 Dataset을 손쉽게 다운로드 받을 수 있도록 해줍니다.
https://knowyourdata-tfds.withgoogle.com/ 
=>기본 패키지가 아니라서 tensorflow-Datasets 패키지를 설치해야 합니다.

import tensorflow_datasets as tfds

Datasets = tfds.load(name='mnist')
mnist_train, mnist_test = Datasets['train'], Datasets['test']

plt.figure(figsize=(6, 3))

mnist_train = mnist_train.repeat(5).batch(32).prefetch(1)
#32개를 가져오고 미리 한 묶음 더

for item in mnist_train:
  images = item['image']
  labels = item["label"]

  for index in range(5):
    plt.subplot(1, 5, index+1)
    image = images[index, ..., 0]
    label = labels[index].numpy()
    plt.imshow(image, cmap='binary')
    plt.title(label)
    plt.axis("off")
  break
반응형
LIST