Monday Morning Haskell 1. Haskell Tensor Flow Guide

Similar documents
Lecture note 7: Playing with convolutions in TensorFlow

manifold Documentation

2 Initialize a git repository on your machine, add a README file, commit and push

Getting Started With Linux and Fortran Part 3

Introduction to Git and GitHub for Writers Workbook February 23, 2019 Peter Gruenbaum

AMath 483/583 Lecture 2

AMath 483/583 Lecture 2. Notes: Notes: Homework #1. Class Virtual Machine. Notes: Outline:

How to set Caffe up and running SegNet from scratch in OSX El Capitan using CPU mode

Tensorflow v0.10 installed from scratch on Ubuntu 16.04, CUDA 8.0RC+Patch, cudnn v5.1 with a 1080GTX

Number Systems Using and Converting Between Decimal, Binary, Octal and Hexadecimal Number Systems

Vaango Installation Guide

UNIVERSITY OF CALIFORNIA, SANTA CRUZ BOARD OF STUDIES IN COMPUTER ENGINEERING

CIS 194: Homework 5. Due Monday, 18 February. Expressions. (2 + 3) 4 would be represented by the value

CSCI 1100L: Topics in Computing Lab Lab 11: Programming with Scratch

The build2 Toolchain Installation and Upgrade

Part 6b: The effect of scale on raster calculations mean local relief and slope

CS152: Programming Languages. Lecture 11 STLC Extensions and Related Topics. Dan Grossman Spring 2011

2 Installing the Software

CS Introduction to Data Structures How to Parse Arithmetic Expressions

Here are a couple of warnings to my students who may be here to get a copy of what happened on a day that you missed.

Eigen Tutorial. CS2240 Interactive Computer Graphics

git-pr Release dev2+ng5b0396a

What is version control? (discuss) Who has used version control? Favorite VCS? Uses of version control (read)

Accessing Zen v13 from Python on Raspbian Using the Btrieve 2 Interface

Python for Astronomers. Week 1- Basic Python

CSC209. Software Tools and Systems Programming.

Assignment 1c: Compiler organization and backend programming

Git. CSCI 5828: Foundations of Software Engineering Lecture 02a 08/27/2015

Understanding Recursion

Using GitHub to Share with SparkFun a

CS197U: A Hands on Introduction to Unix

Objective- Students will be able to use the Order of Operations to evaluate algebraic expressions. Evaluating Algebraic Expressions

Grade 6 Math Circles November 6 & Relations, Functions, and Morphisms

CS558 Programming Languages

CS52 - Assignment 8. Due Friday 4/15 at 5:00pm.

Paul's Online Math Notes. Online Notes / Algebra (Notes) / Systems of Equations / Augmented Matricies

These are notes for the third lecture; if statements and loops.

CS457/557 Functional Languages

Divisibility Rules and Their Explanations

Introduction to Scientific Computing

GUT. GUT Installation Guide

CS103 Handout 29 Winter 2018 February 9, 2018 Inductive Proofwriting Checklist

CS/IT 114 Introduction to Java, Part 1 FALL 2016 CLASS 2: SEP. 8TH INSTRUCTOR: JIAYIN WANG

CSCI 201 Lab 1 Environment Setup

CSE 374 Programming Concepts & Tools. Hal Perkins Winter 2012 Lecture 16 Version control and svn

Performing Matrix Operations on the TI-83/84

Module 1: Introduction RStudio

Having Fun with Social Coding. Sean Handley. February 25, 2010

Intro to Linux & Command Line

Congruence Arithmetic

nacelle Documentation

About the Tutorial. Audience. Prerequisites. Copyright & Disclaimer. Haskell Programming

Pragmatic Version Control

If Statements, For Loops, Functions

Software Development I

Binary, Hexadecimal and Octal number system

A Basic Guide to Using Matlab in Econ 201FS

Programming in C++ Prof. Partha Pratim Das Department of Computer Science and Engineering Indian Institute of Technology, Kharagpur

Zephyr Kernel Installation & Setup Manual

Impressory Documentation

Intro. Scheme Basics. scm> 5 5. scm>

CS558 Programming Languages

Neural Network Exchange Format

T H E I N T E R A C T I V E S H E L L

Using git to download and update BOUT++

Numeric Precision 101

Chapter Two Bonus Lesson: JavaDoc

Blackfin Online Learning & Development

Basics of Computational Geometry

COPYRIGHTED MATERIAL. An Introduction to Computers That Will Actually Help You in Life. Chapter 1. Memory: Not Exactly 0s and 1s. Memory Organization

bistro Documentation Release dev Philippe Veber

Computer Science 322 Operating Systems Mount Holyoke College Spring Topic Notes: C and Unix Overview

Tutorial: GNU Radio Companion

Computer Science 62 Lab 8

Install and Configure wxwidgets on Ubuntu

Laboratory 1: Eclipse and Karel the Robot

TNM093 Practical Data Visualization and Virtual Reality Laboratory Platform

Table of Laplace Transforms

Bits, Words, and Integers

TENSORRT 4.0 RELEASE CANDIDATE (RC)

These notes are intended exclusively for the personal usage of the students of CS352 at Cal Poly Pomona. Any other usage is prohibited without

Lecture 3: Linear Classification

Overview. 1. Install git and create a Github account 2. What is git? 3. How does git work? 4. What is GitHub? 5. Quick example using git and GitHub

Unix - Basics Course on Unix and Genomic Data Prague, January 2017

TDDC88 Lab 4 Software Configuration Management

Onion Language Reference Manual. By: Andrew Aday, (aza2112) Amol Kapoor (ajk2227), Jonathan Zhang (jz2814)

Review. CS152: Programming Languages. Lecture 11 STLC Extensions and Related Topics. Let bindings (CBV) Adding Stuff. Booleans and Conditionals

COSC 2P91. Introduction Part Deux. Week 1b. Brock University. Brock University (Week 1b) Introduction Part Deux 1 / 14

CIS 194: Homework 3. Due Wednesday, February 11, Interpreters. Meet SImPL

GUT. GUT Installation Guide

cgatools Installation Guide

Chapter 3. Revision Control

Section 0.3 The Order of Operations

CSC209. Software Tools and Systems Programming.

CIS 194: Homework 6. Due Friday, October 17, Preface. Setup. Generics. No template file is provided for this homework.

TENSORRT 3.0. DU _v3.0 February Installation Guide

swiftenv Documentation

Raspberry Pi Kernel-o-Matic

Slide 1 Side Effects Duration: 00:00:53 Advance mode: Auto

1. Make sure you have home-brew installed. brew.sh

Transcription:

Monday Morning Haskell 1 Haskell Tensor Flow Guide

Monday Morning Haskell 2 Table of Contents Section 1: Installing Haskell Tensor Flow...3 Section 2: Overview of Files.7 Section 3: Important Types in Haskell Tensor Flow..9 Section 4: Basic Example...12

Monday Morning Haskell 3 Section 1: Installing Haskell Tensor Flow In the first part of this guide, we ll go over how to use Stack in conjunction with some other tools in order to get the basic Tensor flow libraries up and running. You can check out the README on the Github repository for additional assistance. I ve performed the instructions on both Mac and Linux. If you experience any issues with this (or any other) part of the guide, email me at james@mondaymorninghaskell.me so I can help you and make this guide better! First off, Tensor Flow is a Google product, and hence it depends on a number of other Google dependencies. These dependencies are protobuf, snappy, and tensorflow itself. If you re on a Mac, one easy way to get these would be to clone the Haskell Tensor Flow repository and use the tools/install_osx_dependencies script. If you re on Linux, this isn t an option, so you ll have to install these three things manually. The instructions I include are mostly from my test run on Linux, but they mostly follow what happens in the Mac OS instructions as well. Installing Protobuf The protobuf library implements Google s data interchange format. It allows different programs in totally different languages to communicate with each other in a sane way. In particular, we need this so that our Haskell code can communicate with the low level C code that Tensor Flow uses to perform all the math operations. First, you have to retrieve the protobuf source (I m using version 3.2.0, but be sure to check for later versions): >> curl -OL https://github.com/google/protobuf/releases/download/ v3.2.0/protoc-3.2.0-linux-x86_64.zip Next, unzip it: >> unzip protoc-3.2.0-linux-x86_64.zip -d protoc3 Now you need to move the binary executables and included headers to your path where they can be found: >> sudo mv protoc3/bin/* /usr/local/bin/ >> sudo mv protoc3/include/* /usr/local/include/ You ll know you ve succeeded if the protoc command (without any arguments) outputs Missing input file, rather than something like command not found.

Monday Morning Haskell 4 Installing Snappy Snappy is a compression library. You can install it with homebrew on Mac (brew install snappy). However, it s also pretty painless to download and compile from source. Follow the make instructions in the README. Then you ll just need to move the relevant files onto your path. Here s the full instruction set in Linux (if you re installing from source on Mac, it ll look very similar). >> sudo apt install cmake >> git clone https://github.com/google/snappy.git >> git checkout tags/1.1.6 >> mkdir build && cd build >> cmake../ >> make >> sudo cp../snappy.h /usr/local/include/ >> sudo cp snappy-stubs-public.h /usr/local/include/ >> sudo cp../snappy-sinksource.h /usr/local/include/ >> sudo cp libsnappy.so /usr/local/lib/ Install Tensor Flow Naturally, you also have to install Tensor Flow itself. By this, I mean the low-level machinery that actually performs all the math and builds up your graph. Whether you program in Python or in Haskell (or any other language), you re really just writing a Layer on top of this. You ll want to download the latest version for your system from Google APIs. Then unzip it, and you ll be able to copy the dynamic library onto your path so it can be seen. Here are the commands from the script for installing the Mac OS dependencies: >> curl https://storage.googleapis.com/tensorflow/libtensorflow/ libtensorflow-cpu-darwin-x86_64-1.0.0.tar.gz > libtensorflow.tar.gz >> sudo tar zxf libtensorflow.tar.gz -C /usr/local >> rm libtensorflow.tar.gz >> sudo mv /usr/local/lib/libtensorflow.so /usr/local/lib/ libtensorflow.dylib >> sudo install_name_tool -id libtensorflow.dylib /usr/local/lib/ libtensorflow.dylib Here s the process from scratch on Linux. Note the ldconfig command, which links the dynamic library. You do this instead of actually changing it to a.dylib file (that concept only exists on Mac OS). >> curl https://storage.googleapis.com/tensorflow/libtensorflow/ libtensorflow-cpu-linux-x86_64-1.0.0.tar.gz > libtensorflow.tar.gz >> sudo tar zxf libtensorflow.tar.gz -C /usr/local >> sudo ldconfig

Monday Morning Haskell 5 Bringing Tensor Flow into Haskell with Stack Now that you ve got all the dependencies installed, you need to start a Haskell project with Stack and bring the Haskell Tensor Flow library in as a dependency. The library is still in its early stages, so this is not quite so straightforward. There are a couple early versions on Hackage, but they don t include a lot of important recent work. So my recommendation is to use the bleeding edge version from Github. This guide and the blog posts that accompany it were written from commit 4ab9cb9cf274e88eababfaba85103e3890a96afc. To get it, we ll use the feature of Stack that allows us to use a particular Github link and commit as a package within our project. The repository uses a multi-package structure. This means you ll have to specify each individual subdirectory in the subdirs section of the definition so that so you can access the code. All in all, you ll want this section as a package in your stack.yaml file: - location: git: https://github.com/tensorflow/haskell.git commit: 4ab9cb9cf274e88eababfaba85103e3890a96afc subdirs: - tensorflow - tensorflow-ops - tensorflow-core-ops - tensorflow-logging - tensorflow-proto - tensorflow-opgen - tensorflow-test - tensorflow-mnist - tensorflow-mnist-input-data extra-dep: true In addition to that, you also need some extra dependencies. These are essentially Haskell bindings to some of the programs we installed earlier that don t necessarily live within the resolvers that Stackage uses. Some of these are only necessary if you want to do logging, but it s extremely frustrating to have to stop and figure that out in the middle of development, so I highly recommend you start with them all. extra-deps: - proto-lens-protobuf-types-0.2.1.0 - snappy-0.2.0.2 - snappy-framing-0.1.1 - tensorflow-logging-0.1.0.0 - tensorflow-records-0.1.0.0 - tensorflow-records-conduit-0.1.0.0 Finally, you have to make sure you update the extra-include-dir and extra-lib-dir fields to contain the directories where you put the header and library files for Snappy and Tensorflow. extra-include-dirs: - /usr/local/include

Monday Morning Haskell 6 extra-lib-dirs: - /usr/local/lib For the last step, all you need to do is include the relevant dependencies in your.cabal file. Again, I ve included a couple things here, such as mnist and logging, that aren t necessary for the core. But some of the blog material will require them. Here s what the build-depends section looks like: build-depends: base >= 4.7 && < 5, tensorflow, tensorflow-ops, tensorflow-core-ops, tensorflow-logging, tensorflow-mnist, proto-lens And that should be it! You should now be able to make a file and import the tensor flow files without any compiler errors! module Lib where import TensorFlow.Core import TensorFlow.Logging import TensorFlow.GenOps.Core Congratulations, you can now run Tensor Flow in Haskell!

Monday Morning Haskell 7 Section 2: Overview of Files In this section, we ll got over the most important files in the Tensor Flow library and what functions and types they export. TensorFlow.Core This module contains a lot of the most important pieces of Tensor Flow functionality. It s a good place to look to start. It has, for instance, many important types like the Tensor type and the Build monad. It also has functions for actually running tensors: run and runwithfeeds. TensorFlow.Ops TensorFlow.Ops contains all the basic mathematical operations you ll want to perform. For example, you ll find things like tensor addition, multiplication, and matrix multiplication. You ll also see useful conversion functions like scalar, vector, and cast. TensorFlow.Variable The Variable module naturally contains operations related to Tensor Flow variables. Examples include the Variable type, initializedvariable, and the readvalue function that allows operations to be performed on variables. TensorFlow.Session The Session module has the Session type as well as the runsession function, which you ll need to actually run most Tensor Flow programs. TensorFlow.Minimize This module contains optimizers that you ll use to train your algorithms. It has, for instance, the basic gradientdescent optimizer as well as the more sophisticated adam optimizer. You ll generally use the minimizewith function from this module, combined with one of the optimizers. TensorFlow.Logging This module contains functionality related to logging events for Tensor Board. You ll find functions like loggraph, logsummary, and witheventwriter.

Monday Morning Haskell 8 TensorFlow.GenOps.Core So this module is a little tricky. It does not exist concretely, in that the file does not live within the repository. Hence it doesn t actually have any documentation. The file is generated for you at compile time by the tensorflow-opgen package.it takes all the low-level C functions that do not have Tensor Flow specific implementations and turns them into Haskell functions you can use. Some of the C functions have optional arguments with default values. This makes them rather awkward to use from a Haskell perspective, and not especially type safe. Here s an example of using optional parameters to call the 2D convolution function: let conv = conv2d' convattrs where convstridesattr = opattr "strides".~ ([1,1,1,1] :: [Int64]) paddingattr = opattr "padding".~ ("SAME" :: ByteString) dataformatattr = opattr "data_format".~ ("NHWC" :: ByteString) convattrs = convstridesattr. paddingattr. dataformatattr These files should be enough to get you started! After a little while, you ll get used to which files you need to import for which tasks. The example at the end uses explicit imports, so you can learn from that as well.

Monday Morning Haskell 9 Section 3: Important Types in Haskell Tensor Flow In this section, we ll focus on two main categories of types within Haskell Tensor Flow. First, we ll look at the Tensor type, and then we ll examine the two most important monads, Build and Session. If this section seems confusing, I encourage you to move onto Section 4, try out some of the code examples, and THEN come back to this section after you ve seen these types in action. Tensor Types So many of the objects you will create in your Tensor Flow Graph are of type Tensor v a. What does this mean exactly? The Tensor type is parameterized by two other types. The first type parameter focuses on the state of the tensor. The second type focuses on the data that is stored within the Tensor. We ll start by focusing on the data parameter. Tensors mostly store numerical values. Thus the most common types you will see for this second type parameter are things like Float or Int64. There are a couple other types that can show up from time to time. For instance, we can make a summary tensor that uses a ByteString for its data. This byte string represents an event we can log. It is also possible to store boolean values in tensors. There is a decent degree of type safety with these. Most of the mathematical operations between two tensors (add, subtract, etc.) won t typecheck when called on tensors containing bytestrings or boolean values. The following results in a type error: let n1 = constant (Shape [1]) [True] let n2 = constant (Shape [1]) [4 :: Float] let additionnode = n1 `add` n2 Error: Couldn't match type TensorFlow.Types.TypeError Bool with TensorFlow.Types.ExcludedCase arising from a use of add Note that mathematical operations typically require the same underlying value type in the tensor. For instance, the following will also not typecheck: let n1 = constant (Shape [1]) [1 :: Int32] let n2 = constant (Shape [1]) [4 :: Float] let additionnode = n1 `add` n2

Monday Morning Haskell 10 You ll need to fix this by changing the first line to use a Float instead. It can be a little tricky to try to change datatypes mid-stream. You ll likely have to get the values out and then re-encode them as a new tensor. Tensor States Now, Tensors can also have different states of existence, and this is what the first type parameter v indicates. There are three different states: Build, Value, and Ref. When you construct constant tensors, they ll be in the Build state. This refers to a tensor that cannot change its value, but has not been rendered in the TensorFlow graph yet. Note all the following examples will use the ScopedTypeVariables extension. let (n1 :: Tensor Build Float) = constant (Shape [1]) [1 :: Float] Tensors in the Value state already exist within the graph, so they are to some extent fixed. When you are in the Build monad (see below), you can take any Build tensor and turn it into a Value tensor with the render function. You can also use the rendervalue function if you re not sure state your tensor is currently in. let (n1 :: Tensor Build Float) = constant (Shape [1]) [1 :: Float] (rendered :: Tensor Value Float) <- render n1 When you create placeholders, they are in the Value state, so you need to make them from within a Build monad. Try not to get to confused at the distinction between the Build monad and the Build tensor state! (n3 :: Tensor Value Float) <- placeholder [1] You can take any tensor, rendered or not, and get the core expression out of it with the expr function. This will give you a Build tensor. let (n1 :: Tensor Build Float) = constant (Shape [1]) [1 :: Float] (rendered :: Tensor Value Float) <- render n1 (n3 :: Tensor Value Float) <- placeholder (Shape [1]) let (n4 :: Tensor Build Float) = expr rendered let (n5 :: Tensor Build Float) = expr n3 The Ref state refers to tensors that have a particular state attaches to them. This typically refers to variables. You can easily convert them to Tensor Value items with the value function (no monad is needed). value :: Tensor Ref a -> Tensor Value a Unhelpfully, there are two initializedvariable functions in different modules, and their types are different. Using TensorFlow.Ops.initializedVariable will give you a Tensor Ref a. You can use this in operations as you would any tensor. Just note that the result will be a Tensor Build.

Monday Morning Haskell 11 (opsvariable :: Tensor Ref Float) <- TensorFlow.Ops.initializedVariable 3 let (additionwithref :: Tensor Build Float) = opsvariable `add` n1 Can also turn this into a value tensor. let (opsvalue :: Tensor Value Float) = value opsvariable On the other hand, we can also use TensorFlow.Variable.initializedVariable. This gives something of type Variable, which wraps the tensor. You then need to use the readvalue function in order to use it in computations. My examples will use this latter approach (mainly since it s the first approach I found in the docs), but I think the former approach is probably better. (var :: Variable Float) <- TensorFlow.Variable.initializedVariable 3 let (readvar :: Tensor Build Float) = readvalue var You ll get a compile error if you try to add var directly. let (additionwithvar :: Tensor Build Float) = readvar `add` n1 Build and Session Monads There are two main monads you ll be using. The Build monad is what you ll use for actually constructing your Tensor Flow graph. You primarily need the Build monad to store the state of certain graph elements like placeholders and variables. Critically, you need to remember that the Build monad encapsulates the creation of tensors of ALL states, not just those in the Build state. The Session monad stores the state of the Tensor Flow session. You ll need this to run your graph and actually get output. The session is also responsible for logging events. Note that Session belongs to the MonadBuild class, so we can call any Build function within the Session monad. The simple examples all do this. When you re building a more complex model though, it s generally a good idea to isolate the graph building logic from the session logic. Then you can just call the build function to lift your Build function into the Session monad. mysimplegraph :: Build (Tensor Build Float) mysimplegraph = do let myconstant = constant (Shape [1]) [1 :: Float] myvariable1 <- TensorFlow.Ops.initializedVariable 3 myvariable2 <- TensorFlow.Ops.initializedVariable 5 return $ myconstant `add` myvariable1 `add` myvariable2 mysession :: Session (Vector Float) mysession = do graph <- build mysimplegraph run graph

Monday Morning Haskell 12 Section 4: Basic Examples Here s a very basic example of a Tensor Flow application, with line-by-line comments explaining what s happening. Hopefully this is enough to get you off the ground and familiar with the basic concepts! module Main where import Control.Monad (replicatem_) import qualified Data.Vector as Vector import Data.Vector (Vector) import TensorFlow.Core (Tensor, Value, feed, encodetensordata, Scalar(..)) import TensorFlow.Ops (add, placeholder, sub, reducesum, mul) import TensorFlow.GenOps.Core (square) import TensorFlow.Variable (readvalue, initializedvariable, Variable) import TensorFlow.Session (runsession, run, runwithfeeds) import TensorFlow.Minimize (gradientdescent, minimizewith) Usage of the basicexample function. Should result in a tuple like: (5, -1) main :: IO () main = do results <- basicexample (Vector [1.0, 2.0, 3.0, 4.0]) (Vector [4.0, 9.0, 14.0, 19.0]) print results We ll take two vectors (of equal size representing the inputs and expected outputs of a linear equation. basicexample :: Vector Float -> Vector Float -> IO (Float, Float) basicexample xinput yinput = runsession $ do Everything below this ^^ takes place in the Session monad, which we run with runsession. Get the sizes of out input and expected output let xsize = fromintegral $ Vector.length xinput let ysize = fromintegral $ Vector.length yinput Make a weight variable (slope of our line) with initial value 3 (w :: Variable Float) <- initializedvariable 3 Make a bias variable (y-intercept of line) with initial value 1 (b :: Variable Float) <- initializedvariable 1 Create placeholders with the size of our input and output (x :: Tensor Value Float) <- placeholder [xsize] (y :: Tensor Value Float) <- placeholder [ysize]

Monday Morning Haskell 13 Make our model, which multiplies the weights by the input and then adds the bias. Notice we use readvalue to use operations on variables. This is our actual output value. let linear_model = ((readvalue w) `mul` x) `add` (readvalue b) Find the difference between actual output and expected output y, and then square it. let square_deltas = square (linear_model `sub` y) Get our loss function by taking the reduced sum of the above, then train our model by using the gradient descent optimizer. Notice we pass our weights and bias as the parameters that change. let loss = reducesum square_deltas trainstep <- minimizewith (gradientdescent 0.01) loss [w,b] Train our model, but passing our input and output values as feeds to fill in the placeholder values. let trainwithfeeds = \xf yf -> runwithfeeds [ feed x xf, feed y yf ] trainstep Run this training step 1000 times. Encode our input as TensorData replicatem_ 1000 $ trainwithfeeds (encodetensordata [xsize] xinput) (encodetensordata [ysize] yinput)) Run our variables to see their learned values and return them (Scalar w_learned, Scalar b_learned) <- run (readvalue w, readvalue b) return (w_learned, b_learned)