Devreal

FP for Data Science: For-Loops Considere...

Event: Scale by the Bay

Scale By The Bay 2018: Aris Vlasakakis, FP for Data Science For Loops Considered Harmful

Recording: Scale By The Bay 2018: Aris Vlasakakis, FP for Data Science For Loops Considered Harmful

you here my name is iris I work at Credit Karma with a bunch of very talented folks and today I'd like to talk about functional program for data science and a little bit about why for loops are are bad the title a kind of motivation of this talk and the subtitle is motivation come from personal experience having come to this conference many other conferences having read books having read a lot of internet there's a lot of people talking about wonderful contracts in functional programming the evolution of functional programming a lot of stuff in machine learning modeling data analytics and so forth it's just been kind of uncommon to hear about the synthesis of the two and the two fit together beautifully I mean it's just the type of computation it's one of the philosophy and one is a domain right and the background behind for loop considered harmful is coming from my own personal experience of at this point a number of years ago I had basically given up on enjoying software engineering broadly there's a lot of cool stuff in computer science but the real day-to-day of working in teams writing code dealing with stuff was misery inducing it made me sad and I spent less time I mean on average it felt like I was putting way too much time dealing with non non computer science problems for that way and after a while quite on accident I had learned that it was basically due to broadly due to imperative and procedural programming and all this color so I'd like to speak about it so I'd like to start off by just getting some a feel on the audience here how many of you guys are at least aware of understand functional programming cool how many of you guys have keep your hands up actually for a moment can you also raise the other hand if you've done any type of data science work modeling data analytics cool and how many of you have ever committed a bug to production 3 ok so this may be of some use to you remember this is fun so this is what I want to talk about this stuff here I want to give us all on the same page at least about characteristics of what I'm talking about with with respect to statically typed functional programming here so first off it kind of all comes down to you know immutable data without immutable data you're not going very far if we look at also next of static and strong types yes I'm interested in that I know the closure is out there do a lot of cool stuff but keep that to the side for a moment and so static and strong meaning you know one plus one equals two it doesn't equal eleven sometimes you know no magic weird uncontrolled conversions further we're looking at you know referential transparency which is a fancy way of saying that whenever you call a function you can actually replace that function with the return value of that function and it doesn't do anything else so there's your program you can still understand what happened here you can think locally and not affect the world globally right and another concept here is like the separation the what from the how an easy way to think about that is imagine a sequel query guys select star from customers where age is greater than 40 well I've described a table but I haven't told you like down at the Assembly level like you know registers and what machine operations I'm going to do in order to compute that right so that's a really really cool property here and and that kind of leads into here a true function composition so you guys remember in school you had an f of X you had a G of X you could actually do an F of G of X and you actually get that property here with your functional programming as opposed to you know like square-hole round peg like if you jam it in there which computers let you do you can accomplish this but I like true function composition here so I would like to ask you some questions about your code my code too so does your code cause interstellar explosions this has actually happened if we look at the was it the the Mars rover back in 1999 it actually exploded because of confusion between like centimeters and inches basically metric and imperial units you know from statically typed functional programming like we have types we model these units as types i mean basically that would be a compiler error not a runtime error on Mars you move further hey work for me didn't work for you right this is kind of the ultimate problem what I'm basically asking is does do your systems I mean are your systems produced out of small easy to test and easy to understand components that work predictably it's a big question there a lot of those problems can be solved to some of these FB techniques such as again referential transparency some of the great patterns that we know about like monads functors applicatives and and not allowing things like global mutating variables kind of all over the place well does your code cause headaches is it basically is it hard for other people to understand your code there are ways of improving this as well through like stop the imperative control flow of using like for loops and while loops use maps and folds for example use total functions that always return a value like if you divide two numbers don't throw an exception return an option you'll see that in a second and and again use value mutability recursion your design and again remember a lot of this comes down to write big algorithms from small algorithms now if your code is something that you can't easily improve changing is what we do to code all the time you're going to be in trouble right and one of the reasons why we're scared of changing our code is we don't have any like guarantees or static properties of our code commonly so an important aspect and important property really of functional programming is you get equation alert ANSI way of saying like okay if I have this gigantic system you know can I split it in half can I move these two parts there can I replace this component with this component those are great properties to have when you're improving and changing your code I mean again that's part of an aspect of true composition how about you just never throw exceptions that would help and again control your side effects and another like useful component here is like adding type is using type classes again sometimes you just want to add behavior two types rather than change all the sub classing hierarchy and and end up looking like spark and the last thing I'd say is you know is code ceremony now ceremony is great for humans we like it we thrive on it but code ceremony and boilerplate know it ends up becoming like cognitive noise you'd end up seeing like 50 lines of java lines of stuff and it turns out only three lines do something and the rest of it is like the Spring Framework right a lot of like functional techniques such as higher-order functions really helped with this again having reliable patterns such as you know monads bind flat map help you out and again higher kind of types are huge in terms of removing repeated code I mean can't really write a generic monad without higher kind of types so where am I going with this yes statically typed functional programming the bottom line here is whether you're a business guy or research scientist is that we want better code we want it developed correctly faster not just develop faster and we want it cheaper in terms of agony and in terms of time cost right and there are a lot of like great properties from going this route and I'll talk about them parallelism correctness expressiveness compositionality now again looking at the mind of like an actor of an actual industry data scientist there's something that matters here from having work with the guys and girls on the team at Credit Karma here's what I've learned look they want better models they want better data more experiments they have a domain that they care about it turns out that the computers are incidentally there I mean very frequently you have people with with PhDs who've been in school and they're basically saying like I have this idea on paper how do I go from paper into the computer and make it happen right these are just incidental tools they are typically not you know again really geo on the computer science and this actually matters because I work with physicists and hard scientists PhDs who are it's not for lack of brains it's this that their interests are in different places and frequently they are just given some tools they're like here here you go have you some are have you some Python and and it works well enough and that's fine and and again to to at least address the Python problem look if you threw a statistician into a company and said hey write some Java write some C++ as was the case in the past it's it's not pleasant it's not great versus you know you fire up Jupiter notebook you import SK learn you import tensorflow you you know you deployed a model you thought about your domain you have a job that pays you six figures but this is a form of progress right so I can't argue with with with why the reality is as it is however let's say Python for example is open to a ton of problems that are just common to statically type the mostly procedural languages and despite the fact that you might be able to tell that I like functional programming I want to disabuse you of the idea that it is for free now this is kind of a magic pseudo fake graph talking about as time and complexity increases and your and your team by the way team productivity I'm giving you kind of like my experience here the bottom line here is look if if in a mythical world all you were doing was you had a 50 line program and that was your company write in Python I don't care write in bash do you want to do I mean that would be fine but in the real world as your project grows in complexity as the team grows in size and especially as people come and as they go and as again as time goes forward needs change I have noticed that you can actually become more productive like reliably more productive if you are clinging to these useful functional constructs rather than you know choking on complexity and just burning yourself also yes I get it there are many more libraries for Python than for Haskell I know so that's the other just you know reality check to have here is that if you're just looking for something to work boom out of the box etc you know why is reality as it is well this is part of the reality again these are unscientific but I'll just I'll just leave them as says uh something will believe me however guys functional programming truly is worth it there are a lot of benefits here in terms of Big Data computing parallelism I mean Hadoop spark all that stuff it came from map and reduce correctness you're more likely to get it right expressiveness also means like you end up writing less code less code equals probably less bugs and compositionality like I mentioned true f of G of X and just to just remember guys like sequel and Excel they're actually functional programming languages so these are not foreign concepts so talk about the benefit of parallelism look ultimately I'm gonna give you some like here's here's just like some fakie code that's kind of Sparky kind of dataflow Co etc but the bottom line is imagine like if your use case was this imagine you have a bunch of users their data and you have a mall and you have some models and you want to batch score a bunch of predictions right for like what part of what products you're going to give to these you know the recommended these users right common use case in the Silicon Valley instead of using a for loop I'm literally using a map the interesting property of this code is that it's scale invariant programming I mean meaning concretely that like if I have a megabyte of data or if I have like a petabyte of data on a cluster it's the same code basically and I can swap from again one framework to another and it it basically seems like the same thing like how many threads how many computers are operating on here as a data scientist I don't care the more you can say I don't care it just works the happier you will be let's look at correctness now here's a counter example of some code this is a version of code that I have seen like a junior data scientist actually write now the number of ways that this is wrong is it's just large you know you've got type confusion you have side effects mutation and like the really fun thing is if you just run this function multiple times you get different results half the time right and the point is is that one of the powers of Python and why people like it is like you can do anything and I'm saying well that's also part of the problem and and if the language kind of a encourages stuff well you'll you'll get what you incentivize although this can obviously be improved in a lot of ways even within Python something else that you can get out of here is for example I used to hate compilers long ago with Java but I really like compiler errors now because I want to have compiler errors early and often meaning like for example imagine you're multiplying two matrices here with a pseudo Scala yes you can multiply left times right and you will get a five by three matrix and even the the compiler itself can actually give it to you but you know how we make mistakes sometimes the nice thing is if you do it the wrong way and you multiply the matrices in the wrong direction it's a compiler error this eliminates an entire category of possible mistakes right and there are huge numbers of errors that can be just solved just by modeling your modeling your projects this way another part here is for correctness is you know is kind of like you know partial total functions aka you know unconstrained versus constrained code so in this it says pythonic Python there look besides the fact that I can read English I don't know anything about this function it says read file it might you know it might launch the missiles we don't know what it does versus if we look at this if it's written in pure functional Scala not just any Scala look all I know is it is read file is a function it takes a path file path it is actually some type of ADT and it returns the description of a program that when that program is run it will return some type of useful error type or some type of file now if you look at also expressiveness have you guys ever taken the average of list of numbers and okay also sometimes your list might be empty this is a total function it will work and and you can see it right I mean hopefully it's easy to follow what's going on here if you do this a procedural way well it does mostly the same thing it's accomplishing the same thing I understand that you know it uses exceptions instead but can anyone actually see the bug here did you see it okay there is no bug I just I just said that the kind of abuse you guys I mean it's literally just the case that we constantly have we constantly have off-by-one errors we have / 0 errors we have timer errors sometimes and it's just a point that we can be we can actually get away from this whole class of problems by having a more expressive function up there I would prefer the first function over the second function any day also if we look at algebraic properties here I mean this is a fancy way of saying something you guys already know and love for example the algebra of arithmetic so you guys remember that you learned this in school like the algebra let's let's say here for any real number if you go real number + 0 you get the real number back cool for any real number if you go times 1 you get that real number back like these are lovely properties that are better mathematically universally true this is good stuff MA no it's right here you can actually easily introduce concepts like this into your code in this contrived example of just talking about hey we've got data we have learners we can build models and then we have properties it's very much like the same way that you can trust realities about real numbers you can also have trust in your system and you can build that in and here if we talk about true compositionality one of the aspects here I like about about good FP is that you can separate again the the what we are doing from how we are doing it if you have yourself like a nice embedded DSL in this case I'm doing like free monad II type stuff but this is kind of the one of the ultimate in terms of having a nice DSL that describes your problem domain and it's totally compositional and it's totally substitutable a lot of these things go hand in hand having true substitution the cool thing about this for example is it's so substitutable and that you could write this one function that does this machine learning pipeline but you can even substitute what platform it's running on so scikit-learn tensorflow spark link that's pretty cool those are just different interpreters from the free monad world and you know cross language etc you get to do what you want and from the perspective of data scientists he just you know dude just thought about what dude want to do and it just happens right and engineering people that cough ah we just make it happen and whatever whatever environment needs to happen that's just an implementation detail right and again these are just bigger programs from smaller easily understood programs and I'd like to finish off on just sometimes sometimes the the correspondence here is little almost amazing it's very beautiful here so for example if you guys heard about like recurrent neural networks some people in the room probably use them frequently what you see here is like they're used for example let's say in translation okay let's say we want to turn it from French to German now what you're doing what the actual neural network is doing here in pictures for example if you're collapsing down the French sentence that's called a fold and then when you go from that representation into the target language that's called an unfold and hey what do you know it's basically called you know fold by after unfold this is called a refold and for example if people who are steeped in the functional programming world understand things like kata morphism and a morphism hila morphism because greek words are cool it's it's what we have here right and if you're just used to thinking this way it turns out you're used to thinking in some types of neural networks so that's extremely powerful there and I think it's probably better remove barriers from domain to language rather than introducing new ones like you know do this in a for loop so that's what I had to say I recommend that we again as a community we embrace this we try to enhance this get all our all of our friends and data scientists actually embrace these ideas and work with them and I think we'll just have better teams all have better models and be happy thank you very much preciate it no worries no no no worries out that could be a whole conversation I was actually speaking to the to the architecture of how SPARC is written in the sense like I've tried to like you know look at it from more type class perspective but it's like subclass up less up class up let's help us up let's that's more what I was discussing to that extent I mean there's actually a lot of like more you know it's a long question and and but you can't add things like for example adding more descriptive types to your code doing a little bit more work with rappers and so forth it's a great question but I feel like it would be to give it honest justice would take significant time anybody else hopefully I just made my mind my piece or made my case here pretty well alright thank you very much folks [Applause]