Reactive User Interfaces final by Konrad Krawczyk
an app that predicts flight delays for domestic flights in the US
tech stack: Python, sklearn (neural network), Flask (API), React (front end)
design tools: Figma
- improving the model
- deploying as an API
- designing UI wireframes
- developing the React front end
Step 1. improving the model
BTW: I have the documentation of our final from last semester. [HERE]
For this part, my goal was to create a function that would get my six variables and output a result – either 0 or 1, ideally with a higher accuracy than last time I used the app.
Flight delays are very complex events, almost comparably to stock exchange or weather. There are certainly patterns with delays – for example, during Christmas there are always delays, certain high-traffic or underinvested airports are having delayed flights often. I tried improving the algorithm before proceeding to “pickle” and deploy the model. This, however, did not happen because of the time constraints. I could try to tweak parameters like layer sizes, or to add totally new features like weather – but training a neural network with this amount of data takes around 40 minutes each time, and I wanted to focus on other, more front-end-oriented features of the app instead.
What took me an extraordinary amount of time was making sense of the data I had. I wrongly recalled that it is possible to input around 6-8 variables and receive anything that makes sense. But no! The data was modified to fit into the sklearn package for data modelling. This meant that I could not input strings, and instead each of the over 220 airports listed in the database had to be converted into a 0-1 variable (the so-called dummy variable). And these were unlabelled, meaning that all I could see in our data was a set of nondescript zeroes and ones. I had to regenerate this dataset with labelled data, and make sure that the accuracies in the testing phase are the same. I spend some quality time doing that, and in the meantime I looked through docs related to deploying Python apps in React. There have also been some issues with data formats – for example one of the packages I used had its own special DataFrame format, and then I had to figure out whether my model accepts it. It didn’t, and I had to convert to matrices.
step 2. deploying as an API
I found this guide on the Internet – and followed all of it: https://www.analyticsvidhya.com/blog/2017/09/machine-learning-models-as-apis-using-flask/
Halfway through, I realised I don’t know how to save a model. The answer turned out to be the pickle library. It trains and tests the model, and then returns a “pickle” file that can be used to speed up the use of the app. Generating it was fairly easy. But the input still had to be sklearn-friendly, consisting of around 250 variables. What I did was: I got the names of all airports used, put them in an array, and then looped over that array to creat the 0-1 variables based on the name from the input. (basically, If input is XYZ, is_airport_XYZ = 1.).
First, I tried to convert the code into an API by myself. But then I reminded myself that I know nothing about back end, so I reached out for a nice Flask API boilerplate. It’s here: https://github.com/smitthakkar96/flask-restful-boilerplate. It had a nice structure, where all the code responsible for specific requests was in one controller file called helloController.
My other struggle was that I worked mostly inside the Anaconda framework – which handles all the packages by itself. It only turned out after the deployment hat I had to manually install all of them.
But then, I ran into some issues when I was deploying to Heroku. Namely, the CORS error happened. I couldn’t make a request from my own IP, as it was “unsafe”. I had to edit the api.py file to add headers that would allow all domains to access. I am not sure if this is exactly safe, but there is little at stake in this case, and I really wanted to move on to the front end.
step 3. UX
For the wireframes I used a great tool I found called Figma. It’s a vector graphics editor similar to Sketch, where one can easily create layouts for specific devices, and also share them in the cloud and collaborate on them. It’s also free for individual users. Anyway. I tried to make the interface a simple set of direct questions to the user. Instead of just making one form, I decided to put each one field on a separate view. The form is simple, so in order to fill the empty space and to make the interface more interesting and informative I made a simple vector graphic that showed an airplane departing, flying and arriving. I also left some empty space to account for the mobile touch keyboards.
At the last stage, I prepared an infographic that would show if the user was curious about our model. I thought that since we know our model is far from perfect, there needs to at least be an indication of that if we are to be honest with our users. I thought: what if one day people start using this model, and they rely on it, and it gets some airlines in trouble even though they shouldn’t be? I think a big part of the problem with the models right now is that their authors are embarrassed to acknowledge that they might be really wrong.
step 4. React
First, I made a basic HTML form that would simply grab the data and return a result. This was really easy.
Then I tried to put each input into a separate view. I really wanted to avoid making the entire form one component, as it would mean putting four different screens on one entity. Following Rune’s advice, I split it into different components and played with the background-position parameter to move the sag background into the right position.
One of the big parts of the design was autosuggestion in the airport and airline fields. For the airports, it turned out that I have to manually make a list of every single airport I am using and the city or town it’s located in. This list is saved as this.state.airports. Took a bit of time, but that was necessary.
Another thing I wanted to implement was automatic suggestion in the input field itself. I accomplished that only by creating a separate text element that showed up underneath the input, which showed the already typed-in letters in black, and the rest of the suggestion in grey. This way, the input field itself is invisible.
On componentDidMount, I also added an autofocus to the input field. This was made much easier since I separated the input fields into components.
Finally, I realised that I don’t even need a form at all. Instead of sending the onSubmit form results, I passed the state (manipulated with onChange) to the API call. The rest was pretty straightforward – the API call was working, and on a specific state a result screen would show up.
I have a short list of things to improve:
- When working with CSS transitions, the screens would often stack on top of one another, causing the layout to overflow. I solved it with a nasty hack that translates the previous slide to the top of the screen, therefore preventing it from wrapping to the next “line”. I have no idea how this would work if, for example, I added the option to move backwards.
- Moving backwards, as well as restarting the whole process, is also something I need to implement. People will make mistakes, and they might want to use the app more than once without restarting it. For that I would need to add a restart function that would change all states to their default values.
- Design details, especially after the app responds with a result. I wanted to make a little animation that would play along with the response, but it ended up being just one yellow screen. I agree with Kilian’s suggestion to make the “How do we know” button an actual button, or at least a link. And, the result screen is set as position: absolute, because I wanted it to be a fade-in, instead of slide from the right. Position absolute has no place here.
Otherwise, building an app that stands on its own was a really exhausting, but rewarding task. I might even try and make this thing in React Native, and release a version for Android.