{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# tensors\n",
    "A **tensor** is a generalization of vectors and matrices to potentially higher dimisions. Internally, Tensorsflow represents tensors as n-dimensional arrays of basic datatyeps.\n",
    "\n",
    "When writing a tensorflow program, the main object you maniplate and pass around is the ```tf.Tensor```. A ```tf.Tensor``` object represnets a partially defined computation that will eventually produce a value.\n",
    "\n",
    "A ```tf.Tensor``` has the following properties:\n",
    "- a datatype(float32, int32, or srting)\n",
    "- a shape\n",
    "\n",
    "The main tensors are:\n",
    "- ```tf.Variable```\n",
    "- ```tf.constant```\n",
    "- ```tf.placeholder```\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Tensor has two primary purposes\n",
    "\n",
    "- a tensor can be passed as input to another operation. This build a dataflow connection \n",
    "between operations\n",
    "- After the graph has been launched in a session, the value of tensor can be computed by\n",
    "passing to tf.Session().run()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tensor(\"e:0\", shape=(2, 2), dtype=float32)\n",
      "node {\n",
      "  name: \"c\"\n",
      "  op: \"Const\"\n",
      "  attr {\n",
      "    key: \"dtype\"\n",
      "    value {\n",
      "      type: DT_FLOAT\n",
      "    }\n",
      "  }\n",
      "  attr {\n",
      "    key: \"value\"\n",
      "    value {\n",
      "      tensor {\n",
      "        dtype: DT_FLOAT\n",
      "        tensor_shape {\n",
      "          dim {\n",
      "            size: 2\n",
      "          }\n",
      "          dim {\n",
      "            size: 2\n",
      "          }\n",
      "        }\n",
      "        tensor_content: \"\\000\\000\\200?\\000\\000\\000@\\000\\000\\000@\\000\\000\\200@\"\n",
      "      }\n",
      "    }\n",
      "  }\n",
      "}\n",
      "node {\n",
      "  name: \"d\"\n",
      "  op: \"Const\"\n",
      "  attr {\n",
      "    key: \"dtype\"\n",
      "    value {\n",
      "      type: DT_FLOAT\n",
      "    }\n",
      "  }\n",
      "  attr {\n",
      "    key: \"value\"\n",
      "    value {\n",
      "      tensor {\n",
      "        dtype: DT_FLOAT\n",
      "        tensor_shape {\n",
      "          dim {\n",
      "            size: 2\n",
      "          }\n",
      "          dim {\n",
      "            size: 2\n",
      "          }\n",
      "        }\n",
      "        tensor_content: \"\\000\\000\\200?\\000\\000\\200?\\000\\000\\000\\000\\000\\000\\200?\"\n",
      "      }\n",
      "    }\n",
      "  }\n",
      "}\n",
      "node {\n",
      "  name: \"e\"\n",
      "  op: \"MatMul\"\n",
      "  input: \"c\"\n",
      "  input: \"d\"\n",
      "  attr {\n",
      "    key: \"T\"\n",
      "    value {\n",
      "      type: DT_FLOAT\n",
      "    }\n",
      "  }\n",
      "  attr {\n",
      "    key: \"transpose_a\"\n",
      "    value {\n",
      "      b: false\n",
      "    }\n",
      "  }\n",
      "  attr {\n",
      "    key: \"transpose_b\"\n",
      "    value {\n",
      "      b: false\n",
      "    }\n",
      "  }\n",
      "}\n",
      "versions {\n",
      "  producer: 22\n",
      "}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "tf.reset_default_graph()\n",
    "# Build a dataflow graph\n",
    "c = tf.constant([[1.0,2.0],[2.0,4.0]],name='c')\n",
    "d = tf.constant([[1.0,1.0],[0,1.0]],name='d')\n",
    "# a tensor can be passed as input to another operation. This build a dataflow connection \n",
    "#between operations\n",
    "e = tf.matmul(c,d,name='e')\n",
    "#A Tensor is a symbolic handle to one of the outputs of an Operations.\n",
    "print(e)\n",
    "print(tf.get_default_graph().as_graph_def())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1.  3.]\n",
      " [ 2.  6.]]\n"
     ]
    }
   ],
   "source": [
    "# After the graph has been launched in a session, the value of tensor can be computed by\n",
    "# passing to tf.Session().run()\n",
    "sess = tf.Session()\n",
    "#Note c,d,e are symbolic tensor objects, whereas result is a numpy array \n",
    "#that stores a concret value\n",
    "result =  sess.run(e)\n",
    "print result"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Understanding static and dynamic shapes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[None, 128]\n"
     ]
    }
   ],
   "source": [
    "a = tf.placeholder(tf.float32,[None,128])\n",
    "static_shape = a.shape.as_list()\n",
    "print static_shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tensor(\"Shape:0\", shape=(2,), dtype=int32)\n"
     ]
    }
   ],
   "source": [
    "dynamic_shape = tf.shape(a)\n",
    "print dynamic_shape\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(?, 10, 32)\n"
     ]
    }
   ],
   "source": [
    "b = tf.placeholder(tf.float32, [None, 10, 32])\n",
    "b_static_shape_list = b.shape\n",
    "print(b_static_shape_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "Failed to convert object of type <type 'list'> to Tensor. Contents: [Dimension(None), Dimension(320)]. Consider casting elements to a supported type.",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-25-43990214c345>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m b_reshape = tf.reshape(b,[b_static_shape_list[0],\n\u001b[0;32m----> 2\u001b[0;31m                           b_static_shape_list[1]*b_static_shape_list[2]])\n\u001b[0m",
      "\u001b[0;32m/home/yuzhile/work2017/env/tf/local/lib/python2.7/site-packages/tensorflow/python/ops/gen_array_ops.pyc\u001b[0m in \u001b[0;36mreshape\u001b[0;34m(tensor, shape, name)\u001b[0m\n\u001b[1;32m   2449\u001b[0m   \"\"\"\n\u001b[1;32m   2450\u001b[0m   result = _op_def_lib.apply_op(\"Reshape\", tensor=tensor, shape=shape,\n\u001b[0;32m-> 2451\u001b[0;31m                                 name=name)\n\u001b[0m\u001b[1;32m   2452\u001b[0m   \u001b[0;32mreturn\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   2453\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/home/yuzhile/work2017/env/tf/local/lib/python2.7/site-packages/tensorflow/python/framework/op_def_library.pyc\u001b[0m in \u001b[0;36mapply_op\u001b[0;34m(self, op_type_name, name, **keywords)\u001b[0m\n\u001b[1;32m    491\u001b[0m           \u001b[0;32mexcept\u001b[0m \u001b[0mTypeError\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0merr\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    492\u001b[0m             \u001b[0;32mif\u001b[0m \u001b[0mdtype\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 493\u001b[0;31m               \u001b[0;32mraise\u001b[0m \u001b[0merr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    494\u001b[0m             \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    495\u001b[0m               raise TypeError(\n",
      "\u001b[0;31mTypeError\u001b[0m: Failed to convert object of type <type 'list'> to Tensor. Contents: [Dimension(None), Dimension(320)]. Consider casting elements to a supported type."
     ]
    }
   ],
   "source": [
    "b_reshape = tf.reshape(b,[b_static_shape_list[0],\n",
    "                          b_static_shape_list[1]*b_static_shape_list[2]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[<tf.Tensor 'unstack_3:0' shape=() dtype=int32>, 10, 32]\n",
      "Tensor(\"Reshape_6:0\", shape=(?, 320), dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "\n",
    "def get_shape(tensor):\n",
    "    static_shape = tensor.shape.as_list()\n",
    "    dynamic_shape =  tf.unstack(tf.shape(tensor))\n",
    "    dims = [s[1] if s[0] is None else s[0] for s in zip(static_shape,dynamic_shape)]\n",
    "    return dims\n",
    "\n",
    "shape = get_shape(b)\n",
    "print(shape)\n",
    "b = tf.reshape(b,[shape[0],shape[1]*shape[2]])\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
