Data API 추가

This commit is contained in:
rickiepark
2018-05-19 17:03:53 +09:00
parent 364f9a271f
commit e168f9941e

View File

@@ -249,7 +249,24 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 리더" "# 리더 (Reader) - 예전 방법"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"reset_graph()\n",
"\n",
"default1 = tf.constant([5.])\n",
"default2 = tf.constant([6])\n",
"default3 = tf.constant([7])\n",
"dec = tf.decode_csv(tf.constant(\"1.,,44\"),\n",
" record_defaults=[default1, default2, default3])\n",
"with tf.Session() as sess:\n",
" print(sess.run(dec))"
] ]
}, },
{ {
@@ -274,7 +291,7 @@
"\n", "\n",
"test_csv = open(\"my_test.csv\", \"w\")\n", "test_csv = open(\"my_test.csv\", \"w\")\n",
"test_csv.write(\"x1, x2 , target\\n\")\n", "test_csv.write(\"x1, x2 , target\\n\")\n",
"test_csv.write(\"1., , 0\\n\")\n", "test_csv.write(\"1.,, 0\\n\")\n",
"test_csv.write(\"4., 5. , 1\\n\")\n", "test_csv.write(\"4., 5. , 1\\n\")\n",
"test_csv.write(\"7., 8. , 0\\n\")\n", "test_csv.write(\"7., 8. , 0\\n\")\n",
"test_csv.close()\n", "test_csv.close()\n",
@@ -493,6 +510,281 @@
" print(\"dequeue 타임 아웃\")" " print(\"dequeue 타임 아웃\")"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Data API"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"텐서플로 1.4에서 소개된 Data API를 사용하면 손쉽게 데이터를 효율적으로 읽을 수 있습니다."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"tf.reset_default_graph()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"0에서 9까지 정수를 세 번 반복한 간단한 데이터셋을 일곱 개씩 배치로 만들어 시작해 보죠:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"dataset = tf.data.Dataset.from_tensor_slices(np.arange(10))\n",
"dataset = dataset.repeat(3).batch(7)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"첫 번째 줄은 0에서 9까지 정수를 담은 데이터셋을 만듭니다. 두 번째 줄은 이 데이터셋의 원소를 세 번 반복하고 일곱 개씩 담은 새로운 데이터셋을 만듭니다. 위에서 볼 수 있듯이 원본 데이터셋에서 여러 변환 메서드를 연결하여 호출하여 적용했습니다."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"그다음, 데이터셋을 한 번 순회하는 원-샷-이터레이터(one-shot-iterator)를 만들고, 다음 원소를 지칭하는 텐서를 얻기 위해 `get_next()` 메서드를 호출합니다."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"iterator = dataset.make_one_shot_iterator()\n",
"next_element = iterator.get_next()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`next_element`를 반복적으로 평가해서 데이터셋을 순회해 보죠. 원소가 별로 없기 때문에 `OutOfRangeError`가 발생합니다:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"with tf.Session() as sess:\n",
" try:\n",
" while True:\n",
" print(next_element.eval())\n",
" except tf.errors.OutOfRangeError:\n",
" print(\"완료\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"좋네요! 잘 작동합니다."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"늘 그렇듯이 텐서는 그래프를 실행(`sess.run()`)할 때마다 한 번만 평가된다는 것을 기억하세요. `next_element`에 의존하는 텐서를 여러개 평가하더라도 한 번만 평가됩니다. 또한 `next_element`를 동시에 두 번 실행해도 마찬가지입니다:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"with tf.Session() as sess:\n",
" try:\n",
" while True:\n",
" print(sess.run([next_element, next_element]))\n",
" except tf.errors.OutOfRangeError:\n",
" print(\"완료\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`interleave()` 메서드는 강력하지만 처음에는 이해하기 좀 어렵습니다. 예제를 통해 이해하는 것이 가장 좋습니다:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"tf.reset_default_graph()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"dataset = tf.data.Dataset.from_tensor_slices(np.arange(10))\n",
"dataset = dataset.repeat(3).batch(7)\n",
"dataset = dataset.interleave(\n",
" lambda v: tf.data.Dataset.from_tensor_slices(v),\n",
" cycle_length=3,\n",
" block_length=2)\n",
"iterator = dataset.make_one_shot_iterator()\n",
"next_element = iterator.get_next()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"with tf.Session() as sess:\n",
" try:\n",
" while True:\n",
" print(next_element.eval(), end=\",\")\n",
" except tf.errors.OutOfRangeError:\n",
" print(\"완료\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`cycle_length=3`이므로 새로운 데이터셋은 이전 데이터셋에서 세 개의 원소를 추출합니다. 즉 `[0,1,2,3,4,5,6]`, `[7,8,9,0,1,2,3]`, `[4,5,6,7,8,9,0]` 입니다. 그다음 원소마다 하나의 데이터셋을 만들기 위해 람다(lambda) 함수를 호출합니다. `Dataset.from_tensor_slices()`를 사용했기 때문에 각 데이터셋은 차례대로 원소를 반환합니다. 다음 이 세 개의 데이터셋에서 각각 두 개의 아이템(`block_length=2`이므로)을 추출합니다. 세 개의 데이터셋의 아이템이 모두 소진될 때까지 반복됩니다. 즉 0,1 (첫 번째에서), 7,8 (두 번째에서), 4,5 (세 번째에서), 2,3 (첫 번째에서), 9,0 (두 번째에서) 등과 같은 식으로 8,9 (세 번째에서), 6 (첫 번째에서), 3 (두 번째에서), 0 (세 번째에서)까지 진행됩니다. 그다음에 원본 데이터셋에서 다음 번 세 개의 원소를 추출하려고 합니다. 하지만 두 개만 남아 있습니다. `[1,2,3,4,5,6,7]`와 `[8,9]` 입니다. 다시 이 원소로부터 데이터셋을 만들고 이 데이텃세의 아이템이 모두 소진될 때까지 두 개의 아이템을 추출합니다. 1,2 (첫 번째에서), 8,9 (두 번째에서), 3,4 (첫 번째에서), 5,6 (첫 번째에서), 7 (첫 번째에서)가 됩니다. 배열의 길이가 다르기 때문에 마지막에는 교대로 배치되지 않았습니다."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 리더 (Reader) - 새로운 방법"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`from_tensor_slices()`나 `from_tensor()`를 기반으로 한 원본 데이터셋을 사용하는 대신 리더 데이터셋을 사용할 수 있습니다. 복잡한 일들을 대부분 대신 처리해 줍니다(예를 들면, 스레드):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"tf.reset_default_graph()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"filenames = [\"my_test.csv\"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"dataset = tf.data.TextLineDataset(filenames)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"각 줄을 어떻게 디코드해야 하는지는 알려 주어야 합니다:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def decode_csv_line(line):\n",
" x1, x2, y = tf.decode_csv(\n",
" line, record_defaults=[[-1.], [-1.], [-1.]])\n",
" X = tf.stack([x1, x2])\n",
" return X, y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"그다음, 이 디코딩 함수를 `map()`을 사용하여 데이터셋에 있는 각 원소에 적용할 수 있습니다:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"dataset = dataset.skip(1).map(decode_csv_line)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"마지막으로 원-샷-이터레이터를 만들어 보죠:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"it = dataset.make_one_shot_iterator()\n",
"X, y = it.get_next()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"with tf.Session() as sess:\n",
" try:\n",
" while True:\n",
" X_val, y_val = sess.run([X, y])\n",
" print(X_val, y_val)\n",
" except tf.errors.OutOfRangeError as ex:\n",
" print(\"완료\")"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {