fast.ai: Intro to Machine Learning 1 (v1) (2018)
(autogenerated subtitles follow, may contain gibberish/bad format - please proofread to improve - remove this note once proofread)
Oh good, okay, so let me introduce everybody to everybody else. First of all, so we're here at the university of san francisco learning machine learning or you might be at home, watching this on video, so hey everybody wave here is the University of San Francisco graduate students. Thank you, everybody and wave back from the future and from home to all the students here. If, if you're watching this on youtube, please stop and instead go to course a I and watch it from there. Instead, that there's nothing wrong with YouTube, but I can't edit these videos after I've created them. So I need to be able to like, if you updated information about like what environments to use, how the technology changes, and so you need to go here right. So you can also watch the lessons from here. Here's lots of lessons and so forth right. So that's tip number one for the video tip number two for the video is because I can't edit them all. I can do is add these things called cards and cards or little things that appear in the top corner of the top right hand corner of the screen. So by the time this video comes out, I'm going to put a little card there right now for you to click on and try that out. Unfortunately, they're not easy to notice so keep an eye out for that, because that's going to be important updates to the video all right. So welcome we're going to be learning about machine learning today, then so after everybody in the class.
Here you all have Amazon Web Services setup, so you might want to go ahead and launch your AWS instance now or go ahead and create one short Jupiter notebook on your own computer. If you don't have Jupiter notebook setup, then what I recommend is you go to cresol, calm, wws or calm sign in there sign up , and you can then turn off enable GPU and click start. Jupiter and you'll have a Jupiter notebook instantly that costs you some money, it's three cents an hour. Okay, so if you don't mind spending three cents an hour to learn machine learning, here's a good way, so I'm going to go ahead and say start Jupiter, and so whatever technique you use there, you go one of the things that you'll find on the website is Links to lots of information about the costs and benefits and approaches to setting up lots of different environments for Jupiter notebook, both the deep learning and for regular machine learning, so check them out because there's lots of options. So if I then go open a Jupiter and Jupiter in a new tab Here I am in Crestle or on AWS or your own computer. We use the Anaconda Python distribution for basically everything you can install that yourself and again. There's lots of information on the website about how to set that up we're also assuming that either you're using Crestle or there's something else which I really like called paper space comm, which is another place. You can fire up if you put a notebook pretty much instantly.
Both of these have already have all of the fastai stuff pre-installed for you. So as soon as you open up cresol or paper space, assuming you chose the paper space fastai template you'll see that there's a fastai, folder. Okay, if you are using your own computer or AWS, you'll, need to go to our github repo, fastai, fastai and clone it okay, and then you'll need to do a condor and update to install the libraries and again, that's all information we put on the Website and we've got some previous workshop videos to help you through all of those deaths so for this class, I'm assuming that you have a Jupiter notebook running okay, so here we are in the in the Jupiter notebook and if I click on fastai, that's what You get if you get clone or if you're in Chris all you can see our repo here. All of our lessons are inside the courses folder and the machine learning part one is in the ml one folder. If you're ever looking at my screen and wondering where are you look up here and you'll see that tells you the path fastai forces ml 1 and today we're going to be looking at less than one random forests. So here is lesson 1 RF you you
(autogenerated subtitles follow, may contain gibberish/bad format - please proofread to improve - remove this note once proofread)
So there's a couple of different ways: you can do this, both here in person or on the video you can either attempt to follow along as you watch or you can just watch and then follow along later with the video it's up to you. I would maybe have a loose recommendation to say to watch now and follow along with the video later just because it's quite hard to motor tasks and if you're working on something you might miss a key piece of information which you're welcome to ask about. Okay. But if you follow along with the video afterwards, then you can pause, stop experiment and so forth. But anyway you can choose either way. I'm going to go of you, Topol header view, toggle tool bar and then full screen it so to get a bit more space. So the basic approach - we're going to be teaching here taking here, is to get straight into code, start building models not to look at theory. We've got to get to other theory, okay, but at the point where you deeply understand what it's for and at the point, that you're able to be an effective practitioner. So my hope is that you're going to spend your time focusing on experimenting. So if you take these notebooks and try different variations of what I show you try it with your own data sets the more coding you can do, the better. The more you'll learn.
Ok, don't in you know my suggestion, or at least, and all of my students have told me the ones who have gone away and spent time studying books of theory rather than coding found that they learnt less machine learning and that they often tell me they wish. That's one more time coding the stuff that we're showing in this course a lot of it's never been shown before. This is not a summary of other people's research. This is more a summary of 25 years of work that I've been doing in machine learning. So a lot of this is going to be shown for the first time and so that's kind of cool, because if you want to write a blog post about something that you learn here, you might be building something. But a lot of people find super useful. All right so there's a great opportunity to practice your technical writing and here's some examples of good technical writing. Okay, page by showing people stuff which you've it's not like. Hey. I just learnt this thing. I bet you all know it often it'll be. I just want this thing and I'm going to tell you about it, and other people haven't seen it. In fact, this is the first course ever. That's been built on top of the fastai library, so even just stuff in the library is going to be new to like everybody, okay. So when we use a droopin, a notebook or anything else in python, we have to import the the libraries that we're going to use something. That's quite convenient as if you use these to auto reload commands at the top of your notebook.
You can go in and edit the source code of the modules and your notebook will automatically update with those new modules you won't have to like restart anything. So that's super handy, then, to show your plots inside the notebook you're wanting that plot in line. So these three lines appear at the top of all of my notebooks you'll notice, when I import the libraries that for anybody here who is a experienced Python programmer, I am doing something that would be widely considered very inappropriate. I'm importing star, okay, generally speaking in software engineering, we're taught to like it specifically figure out what we need and import those things the more experienced you are as Python programmer, the more extremely offensive practices you're going to see me use, for example, I don't follow. What's called pap 8, which is the normal style method style of code used in Python, so I'm going to mention a couple of things: first is go along with it for a while. Don't judge me just yet right, there's reasons that I do these things and if it really bothers, you then feel free to to change it right. But the basic idea is data. Science is not software engineering right, there's a lot of overlap. You know we're using the same languages and in the end, these things or may become software engineering projects. But what we're doing right now is we're prototyping models and prototyping models has a very different set of best practices that are taught basically nowhere right, they're, not really even really written down, but the key is to be able to do things very interactively and very iteratively.
Right so, for example, from library import, star means you don't have to figure out ahead of time what you're going to need from that library. It's it's all there. Okay, also because
?display
documentation, ??display
source code(autogenerated subtitles follow, may contain gibberish/bad format - please proofread to improve - remove this note once proofread)
We're in this wonderful, interactive, Jupiter, environment, it lets us understand, what's in the libraries really well so, for example, later on, I'm using a function called display right. So an obvious question is like well, what is display, so you can just type the name of a function and press shift enter member shift enter is is to run a cell and it will tell you where it's from right. So anytime, you see a function. You are not familiar with. You can find out where it's wrong and then, if you want to find out what it does put a question mark at the start. Okay and here you have the documentation and then particularly helpful for the faster I library, so the faster. I library I try to make as many functions as possible, be like no more than about five lines of code. It's just going to be really easy to read right. If you put a second question mark at the star, it shows you the source code of the function right, so all the documentation plus the source code. So you can see like nothing has to be mysterious and we're going to be using the other library we'll use. A lot is scikit-learn, which is kind of implements a lot of machine learning stuff in Python. The scikit-learn source code is often pretty readable and so very often, if I want to really understand something I'll just go question mark question mark and the name of the scikit-learn function, I'm typing and I'll just go ahead and read the source code.
As I say, the first day, I library in particular is designed to have source code, that's very easy to read and we're going to be reading it a lot. Okay, all right. So today we're going to be working on a cattle competition called Blue Book for bulldozers. So the first thing we need is
(autogenerated subtitles follow, may contain gibberish/bad format - please proofread to improve - remove this note once proofread)
To get that data, so if you go Kaggle bulldozers, then you can find it so cackle competitions allow you to download a real-world data set. That's somebody a real problem that somebody's trying to solve and solve it according to a specification that that actual person with that actual problem decided would be actually helpful to them right. So these are pretty authentic experiences for applied machine learning. Now, of course, you're missing. All the bit that went before, which was why did this company to start up the side that predicting the option sale price of bulldozers was important. Where did they get the data from? How did they clean the data and so forth? Okay and that's all important stuff as well, but the focus of this course is really on what happens next, which is like how do you actually build the model? One of the great things about you working on Kaggle, competitions, whether they be running now or whether they be old ones, is that you can submit yours to the leaderboard, even old, closed competitions. You can submit to the leaderboard and find out. How would you have gone right and there's really no other way in the world of knowing whether you're competent at this kind of data in this kind of model than doing that right? Because otherwise, if your accuracy is really bad? Is it because this is just very hard like it's just not possible, then the data is so noisy.
You can't do better, or is it actually that it's an easy data set and you've made a mistake and like when you finish this course and apply this to your own projects. This is going to be something you're going to find very hard and there isn't a simple solution to it, which is you're now using something that hasn't been on cog or your own data set. Do you have a good enough answer or not? Okay, so we'll talk about that more during the course and in the end we just have to know that we have good effective techniques to reliably building baseline models. Otherwise, yeah there's really no way to know, there's no way other than creating a cackle competition or getting you know a hundred top data scientists to work at your problem to really know what's possible. Socal competitions are fantastic for for learning and, as I've said many times, I've learned more from kept from competing in cackled competitions and everything else. I've done in my life so to compete in the caracal competition. You need the data, this one's a an old competition. So it's not running now, but we can still access everything. So we first of all want to understand what the goal is, and I suggest that you read this later, but basically we're to try and predict the sale price of heavy equipment and one of the nice things about this competition is that, if you are like me, You probably don't know very much about heavy heavy industrial equipment options right.
I actually know more than I used to because my toddler loves building equipment, so we actually like watched, youtube videos about front end, loaders and forklifts, but you know two months ago I was, you know a real layman, so one of the nice things is that machine Learning should help us understand a data set not just make predictions about it, so by picking an area which we're not familiar with it's a good test of whether we can build an understanding right because otherwise, what can happen is that your intuition about the data can Make it very difficult for you to be open-minded enough to see what does the data really say? It's easy enough to download the computer sorry to download the data to your computer. You just have to click on the data set. So here is train, zip and click download right, and so you can go ahead and do that if you're running on your own computer right now, if you're running on AWS, it's a little bit harder right, because unless you're familiar with textmode browsers like a links or Links, it's quite tricky to get the data set to cable, so a couple of options: one is you could download it to your computer and then SCP it to AWS, so SCP works just like SSH, but it copies data rather logging in I'll show you a trick, Though that I really like and it relies on using Firefox for some reason - chrome - doesn't work correctly with cable for this. So if I go on Firefox to the website, eventually you and what we're going to do is we're going to use something called the JavaScript console. So every web browser comes with a set of tools for web developers to help them see what's going on, and you can hit 0 3 here developer, control-shift a okay, so you can hit ctrl shift.
I to bring up this. This web developer tools and one of the tabs is network okay, and so then, if I click on train zip and I click on download, okay and I'm not even going to download on let's gon na, say, cancel but you'll see down here. It's shown me all of the network connections that were just initiated right and so here's one which is downloading a zip file from storage. Google API is calm, blah blah blah. That's probably what I want now that looks good, so what you can do is you can right-click on that and say copy copy as curl, so curl is a UNIX command like wget that downloads stuff right. So if I go copy as curl that's going to create a command that has all of my cookies headers everything in it necessary to download this authenticated data set. So if I now go into my server right and if I paste that you can see a really really long, curl command, one thing I notice is that at least recent versions have started adding this 2.0 thing to the command that doesn't seem to work with all Versions of curl, so something you might want to do, is to oopsy-daisy a PE is to pop that into an editor, find that to get rid of it and then use that instead, okay, now one thing to be very careful about by default, curl downloads, the file And displays it in your terminal. So if I try to display this, it's going to display gigabytes of binary data in my terminal and crash it okay.
So to say that I want to output it using some different file name, I always type o for output file. Name and then the name of the file bulldozers dot and make sure you give it a suitable, a suitable extension. So in this case the file was train's, it okay, so bulldozers dot, zip there. It is okay, and so there it all is so I could make directory bulldozers and I couldn't move my zip file into there oops wrong way around . Yes, thank you! Ah, you you, okay and then you, if you don't have unzip install, you may need to sudo apt, install unzip or, if then you're, on a Mac that would be brew. Install unzip! If brew doesn't work, you haven't, got homebrew installed, so make sure you install it and then unzip, okay, and so there the basic steps. One nice thing is that if you're using Crestle most of the data sets should already be pre-installed for you. So what I can do here is, I can say, open a new tab. Here's a cool trick in Jupiter. You can actually say new terminal and you can actually get a web-based terminal and so you'll find one cresol. There's a slash. Data sets folder slash, data sets flash Kaggle, slash, data set, slash birthday. I often the things you need are going to be in one of those places. Okay, so assuming that we don't have it already downloaded in paper actually paper, space should have most of them as well.
Then we would need to go to far say I let's go into the courses, machine learning, folder and what I tend to do is I tend to put all of my data for a course into a folder called data. You'll find that if you try and if you're using what we using get right, you'll find that that doesn't get added to get because it's in the get ignore right. So so don't worry about creating the data folder! It's not going to screw anything up. So I generally make a folder called data, and then I tend to create folders for everything I need there. So in this case I'll make bulldozes CD and remember.  There we go okay, so you can now see. I generally have like anything that would change that. Might change from person to person I kind of put in a constant, so here I just defined something called path, but if you've used the same path, I just did just got to go ahead and run that and let's go ahead and keep moving along. So we've now got all of our libraries imported and we've said the path to the data. You can run.
!ls {PATH}
in Jupyter Notebook(autogenerated subtitles follow, may contain gibberish/bad format - please proofread to improve - remove this note once proofread)
Shell commands from within Tripta notebook by using an exclamation mark. So if I want to check what's inside that path, I can go. Ls data slash bulldozers, okay, and you can see that works or you can even use Python variables. If you use a Python variable inside a Jupiter show command, you have to put it in curlies, okay, so that makes me feel good that my path is pointing at the right place, if you say LS, curly capital's path and you get nothing at all, then you're Pointing at the wrong spot - yes, this up here, usually yeah, so the curly brackets refer to the fact that I put an exclamation mark at the front, which means the rest of this is not a Python command. It's a bashed, command and bash doesn't know about capital path, because capital Park is part of them. So this is a special Jupiter thing which says: expand this Python thing please before you pass it to the show question. Thank you. So the goal here is to use the training set, which contains data through the end of 2011 to predict the sale price of bulldozers, and so the main thing to start with then is of course, to look at the data. Now the data is in CSV format. Right so one easy way to look at the data would be to use shell command head to look at the first two lines: paired bulldozers and even tab-completion works here.
Jupiter does everything right, so here's the first few five lines?  So what we want to do is take this and read it into a nice tabular format. Okay, so just Terrance putting classes on mean. I should make this bigger, or is it okay? Is this big enough font size? Okay? So this kind of data where you've got columns representing a
(autogenerated subtitles follow, may contain gibberish/bad format - please proofread to improve - remove this note once proofread)
Wide range of different types of things, such as an identifier of value, a currency, a date, a size. I refer to this as structured data. Now I say I refer to this as structured data because, like there have been many arguments in the machine learning community on Twitter, about what is structured data weirdly enough. This is like the most important type of distinction is between data. That looks like this and data. Like images where every column is of the same type, like that's the most important distinction in machine learning, yet we don't have standard accepted terms. So I'm going to use the term structured and unstructured, but note that other people you talk to, particularly in NLP and NLP people, use structured to mean something totally different right. So when I refer to structured data, I mean columns of data that can have varying different types of data in them by far the most important tool in Python. If you're working with structure data is pandas, pandas is so important that it's one of the few libraries that everybody uses the same abbreviation for it, which is PD so you'll, find that one of the things I've got here is from fast. Ai imports import star.  So all of the code for fastai is inside the fast a I directory inside the fastai repo, and so you can have a look at imports and you'll see.
It's just literally a list of inputs and you're fine, there pandas as PD, and so everybody does this right. So you'll see lots of people using PD dot, something they're always talking about pandas. So pandas lets us read a CSV file, and so when we read the CSV file, we just tell it the path to the CSV file, a list of any columns that contain dates - and I always add this low-memory - equals false. That's going to actually make it read more of the file to decide what the types are. This here is something called a Python, 3.6 format string. It's one of the coolest parts of python 3.6. You've probably used lots of different ways in the past in Python of interpolating variables into your strings. Python 3.6 has a very simple way that you'll probably always want to use from now on, and it's you to create a normal string. You type an F for the start and then, if I define a variable, then I can say hello: curlies function, okay. This is kind of confusing. These are not the same curlies that we saw earlier on in that LS command right. That LS command is specific to Jupiter and interpolates code into shell code. These curlies are Python 3.6 format string curlies. They require an F at the start. So if I get rid of the F, it doesn't interpolate. Okay, so the F tells it to interpolate, and the cool thing is inside that curlies.
You can write any Python code you'd like just about so, for example, name dot, Papa hello, Jeremy, okay, so I use this all the time and it doesn't matter because it's a format string, it doesn't matter. If the thing was. I always forget my age. I think I'm 43, it doesn't matter if it's an integer right normally, if you like to do string concatenation with integers place and complains no such problem here, okay, so so this is going to read path, slash, train dot, CSV into a thing called a data frame. Pandas data frames and hours data frames are kind of pretty similar, so if you've used R before then you'll find that this is a you know reasonably comfortable. So this file is nine point. Three Meg and it's size is sorry: 112 Meg, 112 Nick and it has 400,000 rows in it. Okay, so it takes a moment to import it, but what it's done? We can type the name of the data frame, DF raw and then use various methods on it. So, for example, deer fur or tail will show us the last few rows of the data frame by default. It's going to show the columns along the top and the rows down the side, but in this case there's a lot of columns. So I've just said dot transpose to show it the other way around. I've created one extra function here display all normally, if you just type DF R or if it's too big, to show conveniently it truncates it and put little ipsus in the middle.
So the details, don't matter, but this is just changing your couple of settings to say even if it's got a thousand rows in a thousand columns, please still show the whole thing. Okay, so this is finished. I can actually show you that. So if I just type this is really cool in in Jupiter notebook, you can type a variable with almost any kind a video HTML, an image whatever and it'll generally figure out a way of displaying it for you, okay. So in this case it's a pandas data frame. It picks it out a way of just playing it for me, and so you can see here that by default it's actually doesn't show me the whole thing. So so here's the data set we've got a few different rows. This is the last bit the tail of it alright last few rows. This is the thing we want to predict price, okay and then all of the other. We call this the dependent variable, the dependent variable is the price, and then we got a whole bunch of things we could predict it with and when I start with a data set, I tend yes Terrance. How can I give you this hello, Jeremy, hi, Tara? I've read in books that you should never look at the data.
(autogenerated subtitles follow, may contain gibberish/bad format - please proofread to improve - remove this note once proofread)
Because of the risk of overfit, why do you start by looking at the data yeah, so I think she's gon na mention I actually kind of don't like I. I want to find out at least enough to know that I've like managed to imported okay, but I tend not to really study it at all at this point, because I don't want to make too many assumptions about it, I would actually say most books say the Opposite most books do a whole lot of expediate exploratory data analysis. First yeah academic books say that that's one of the biggest risks of everything but the practical books say: let's do some EDA first yeah, so that the truth is kind of somewhere in between, and I generally I generally try to do machine learning, driven EDA and that's What we're going to learn today? Okay, so the do thing I do care about, though, is what's the purpose of the project and for capital projects. The purpose is very easy. We can just look and find out, there's always an evaluation section. How is it evaluated - and this is evaluated on root - mean squared log error, so this means they're going to look at the difference between the log of our prediction of price and the log of the actual price and then they're going to square it and addemup. Okay, so because they're going to be focusing on the difference of the logs, that means that we should focus on the logs as well, and this is pretty common like for a price generally, you care not so much about.
Did I miss by ten dollars, but did I miss by ten percent right? So if it was a million dollar thing and you're a hundred thousand dollars off or if you're, it's a ten thousand dollar thing and you're a thousand dollars off often we would consider those equivalent scale issues and so for this oxygen problem, the organizers are telling us They care about ratios more than differences, and so the log is the thing we care about. So the first thing I do is to take the log okay. Now NP is numpy, I'm assuming that you have some familiarity with numpy. If you don't, we've got a video called deep learning workshop, which actually isn't just for deep learning. It's Rahal! It's basically for this as well, and one of the parts there, which we've got a time coded link to there's a quick introduction to numb pay, but basically numpy lets us treat arrays matrices, vectors, high dimensional chances as if they're Python variables, and we can do stuff. Like log to them and it'll apply it to everything, numpy and pandas work together very nicely. So, in this case, DF fraud, sale price is pulling a column out of a pandas data frame which gives us a pandas series right shows us the sale prices and their indexes right and a series can be passed.
(autogenerated subtitles follow, may contain gibberish/bad format - please proofread to improve - remove this note once proofread)
To a number I function, okay, which is pretty handy, and so you can see here. This is how I can replace a column with a new column, pretty easy. So, okay, now that we've replaced its sale price with its log, we can go ahead and try to create a random forest. What's a random forest we'll find out in detail, but in brief, a random forest is a kind of universal machine learning technique. It's a way of predicting something that can be of any kind. It could be a category like. Is it a dog or a cat, or it could be a continuous function? You aspera like price. It can predict it with columns of pretty much any kind. Pixel data zip codes, revenues whatever in general, it doesn't overfit it can and will learn to check whether it is, but it doesn't generally overfit too badly and it's very very easy to make to stop it from overfitting. You don't need, and we'll talk more about this - you don't need a separate validation set in general. It can tell you how well it generalizes, even if you only have one data set, it has few. If any statistical assumptions it doesn't assume that your data is normally distributed, it doesn't assume that the relationship so linear it doesn't assume that you've just specified the interactions. It requires very few pieces of feature engineering for many different types of situation.
You don't have to take the log of the data you don't have to multiply interactions together, so in other words, it's a great place to start right. If your first random forest does very little useful, then that's a sign that there might be problems with your data. Like it's designed to work pretty much first off, can you please throw it out or towards this gentleman? Thank you. What about the national year and, of course, yeah great question, so there's this concept of curse of dimensionality. In fact, there's two concepts: I'll touch on curse of dimensionality and the low free lunch theorem. These are two concepts. You often hear a lot about, they're, both largely meaningless and basically stupid, and yet I would say, maybe the majority of people in the field. Not only don't know that, but think the opposite, so it's well worth explaining the curse of dimensionality. Is this idea that the more columns you have it basically creates a space, that's more and more empty, and this is kind of fascinating mathematical idea, which is the more dimensions you have. The more all of the points sit on the edge of that space. Alright. So if you've just got a single dimension, where things are like random, then they're spread out all over right. Where else, if it's a square, then the probability that they're in the middle means that they've kind of been on the edge of either dimension. So it's a little bit less likely that they're not on the edge edge dimension.
You add, it becomes more addictive, ly, less likely that the point isn't on the edge of at least one dimension right and so basically in high dimensions. Everything sits on the edge, and what that means in theory is that the distance between points is much less meaningful. And so, if we assume that somehow that matters that it would suggest that when you've got lots of columns - and you just use them without being very careful to remove the ones, you don't care about that, somehow things won't work. That turns out just not to be the case. It's not the case for a number of reasons. One is that the points still do have different distances away from each other, just because they're on the edge they still do, vary and far where they are from each other, and so this point is more similar at this point that it is to that point. So even things will learn about K, nearest neighbors, actually, work really well really really well in high dimensions, despite what the theoreticians claimed and what really happened here was that in the 90s theory totally took over machine learning, and so particularly there was this concept of these Things called support, vector machines that were theoretically very well justified, extremely easy to analyze mathematically and you could like kind of prove things about them and we kind of lost a decade of real practical development.
In my opinion, and all these theories became very popular, like the curse of dimensionality nowadays and a lot of theoreticians hate this and the the world of machine learning has become very empirical, which is like which techniques actually work, and it turns out that, in practice, building Models on lots and lots of columns works really really well so yeah. The other thing to quickly mention is the no free lunch theorem, there's a mathematical theorem by that name that you will often hear about their claims that there is no type of model that works. Well, for any kind of data set, which is true and is obviously true, if you think about it in the mathematical sense, any random data set by definition is random right. So there isn't going to be some way of looking at every possible random data set. That's in some way more useful than any other approach in the real world. We look at data which is not random mathematically. We would say it sits on some lower dimensional manifold. It was created by some kind of caused all structure. There are some relationships in there. So the truth is that we're not using random datasets, and so the truth is in the real world. There are actually techniques that work much better than other techniques for nearly all of the datasets you look at, and nowadays there are empirical researchers who spend a lot of time studying this, which is which techniques work a lot of the time and ensembles of decision trees.
With which random for a one is perhaps the technique which most often comes at the top, and that is despite the fact that until the library that we're showing you today first day, I came along, there wasn't really any standard way to pre-process them properly and to Properly set their parameters, so I think it's even more strong than that so yeah. I think this is where the difference between theory and practice is is, is huge. So when I try to create a ratso random forest regressor, what is that random forest regressor? Okay? It's part of something called scikit-learn. scikit-learn is scikit-learn. It is by far the most popular and important package for machine learning in python. It does nearly everything it's not the best at
(autogenerated subtitles follow, may contain gibberish/bad format - please proofread to improve - remove this note once proofread)
Nearly everything, but it's perfectly good at nearly everything so like you - might find in the next part of this course with your net you're, going to look at a different kind of decision. Tree ensemble called gradient roost in trees, where actually there's something called x3 boost, which is better than gradient, boosting trees in psyche alone. But it's pretty good at everything. So, where I'm really going to focus on cycle in random forests, you can do two kinds of things with a random forest. If I hit tab, I haven't imported it. So let's go back to where we import . So you can hit tab in Jupiter. Notebook to get tab-completion for anything, that's in your environment, you'll see that there's also a random forest classifier. So in general, there's an important distinction between things which can predict continuous variables. That's called regression and therefore a method for doing that would be a regresar and things that predict categorical variables, and that is called classification and the things that do that are called plasa fires now. So in our case, we're trying to predict a continuous variable pres. So therefore, we are doing regression and therefore we need a regress or a lot of people incorrectly use the word regression to refer to linear regression. Now it is just not at all true or appropriate. Regression means an assumed learning model. That's trying to predict some kind of continuous outcome.
It has a continuous dependent variable, so pretty much everything in scikit-learn has the same form. You first of all create an instance of an object for the machine learning model you want. You then call fit passing in the independent variables, the things you're gon na use to predict and the dependent variable the thing that you want to predict. So, in our case, the dependent variable is, is the data frames, sale, price column, and so we, the thing we want to use to predict is everything except that in pandas, the drop method returns. A new data frame with a list of columns removed right. Well, a list of rows or columns removed, so access equals 1 means removed columns. So this here is the data frame containing everything except for sale, price. Okay, so you just pass a list. Let's find out so to find out. I could hit shift tab and that will bring up the you know a quick inspection of the parameters in this case. It doesn't quite tell me what I want. So if I hit shift tab twice, it gives me a bit more information. Yes - and that tells me it's a single label or list like list like means, like anything you can index in Python, there's lots of things by the way.  Okay, so that was shift tab. Another way of doing that, of course, which we learned would be question mark question mark DF, bra drop.
Okay, sorry question mark question mark would be the source code for it, for a single question mark is the documentation. So I think that trick of like tab, complete shift-tab parameters, question mark and double question mark for the docs and the source code like if you know nothing else about using Python libraries, know that, because now you know how to find out everything else. Okay, so we try to run it and it doesn't work okay. So why didn't it work? So anytime? You get a stack trace like this. So an error. The trick is to go to the bottom, because the bottom tells you what went wrong a buffer. It tells you all of the functions the court other function could cause other functions to get. There could not convert string to float conventional, so there was a column name. Sorry a there was a value rather inside my data set conventional. The word conventional and it didn't know how to create a model using that string. Now, that's true. We have to pass numbers to most machine learning models and certainly to random forests, so step one is to convert everything into numbers, so our data set contains both continuous variables so numbers where the meaning is numeric like price, and it contains categorical
add_datepart()
(autogenerated subtitles follow, may contain gibberish/bad format - please proofread to improve - remove this note once proofread)
Variables which could either be numbers where the meaning is not continuous, like zip code, or it could be a string like large, small and medium. It's a categorical and continuous variables. We want to basically get to a point where we have a data set where we can use all of these variables, so they have to all be numeric and they have to be usable in some way. So one issue is that we've got something called say all date, which you might remember right at the top. We told it that that's a date, so it's been passed as a date, and so you can see here it's Dana type, D, type, very important thing. Data type is date/time 64-bit, so that's not a number right, and this is actually where we need to do our first piece of feature engineering right inside a date. There's a lot of interesting all right. So since you've got the catch box, can you tell me what are some of the interesting bits of information inside a date? What we can see like a time series? That's true! I'm hadn't expressed for real. What are some columns that we could pull out of this yeah month?  You go, you got some more columns for us the day of month. Yeah keep going to the right yeah week, 30 of week, yeah week of here, yeah, okay, I'll, give you a few more like that you might want to think about would be like.
Is it a holiday? Is it a weekend? Was it raining that day? Was there a sports event that day like it depends a bit on what you're doing right so like if you're predicting soda sales in soma, you would probably want to know? Was there a San Francisco Giants ball game on that day, right so like what's in a date, is one of the most important pieces of feature engineering you can do and no machine learning algorithm can tell you whether the Giants were playing that day and that it Was important right, so this is where you need to do feature engineering, so I to as much things as many things automatically as I can for you right so here I've got something called add date pad. What is that? It's something inside fastai, dot, structured, okay, and what is it? Well, let's read the source code here it is so you'll find. Most of my functions are less than half a page of code. Alright, so here is something it's going to so, rather than often rather than having Docs I'm going to try to add Doc's over time, but that is their design. You can understand them. I reading the code so we're passing in a data frame and the name of some field, okay, which in this case was sale date, and so in this case we can't go D, F, dot field name because that would actually find a field called field name. It literally so DF square bracket field name, is how we grab a column where that column name is stored in this variable.
Okay, so we've now got the field itself, the series yeah, and so what we're going to do is we're going to go through. All of these different strings right - and this is a piece of Python which actually looks inside an object and finds a attribute with that name. So this is going to go through and you can again you can google for Pais and get attribute it's a cool. Little advanced technique, but this is going to go through it's going to find for this field. It's going to find its Year attribute now. Planter's has got this interesting idea, which is, if I actually look inside, let's go field equals. This is the kind of experiment I want you to do right, play around say all date: okay, so I've now got that in a field object, and so I can go field right and I can go field dot, tab, okay and, let's see is year in there. Oh, it's not okay! Why not! Well that's, because year is only going to apply to pandas series that date time objects. So what pandas does is it lets out different methods inside attributes that are specific to what they are so date/time objects will have a DT attribute defined and at that is where you'll find all the date/time specific stuff. So what I went through was, I went through all of these and picked out all of the ones that could ever be interesting for having any reason right - and this is like the opposite of the curse of dimensionality - it's like if there is any column or any Variant of that column that could be ever be interesting at all.
Add that to your data set and every variation of it, you can think of there's no harm in adding more columns nearly all the time right. So in this case, we're going to go ahead and all of these different attributes and so for every one I'm going to create a new field. That's going to be called the name of your field with the word date removed, sort of a sale and then the name of the attribute, so we're going to get a sale year, sale months so a week say all day, etc, etc. Okay and then at the very end, I'm going to remove the original field right because remember, we can't use, say all date directly, because it's not a number, so your sickness only worked because it was a date type. Did you make the data it was already saved as one in the original yeah, it's already a date type and the reason it was a date tonight is because when we imported it we said PA's dates, equals and told pandas, it's a date type. So as long as it looks date-ish and we tell it to parse it as a date, if you don't have an intranet, i I think there might be, but for some reason it wasn't ideal like. Maybe it took lots of time or it didn't always work or for some reason I had to list it here. I would suggest checking out the docs for pandas, don't read CSV and maybe on the forum. You can tell us what you find, because I can't remember offhand you I got telephoning so how about the time zone.
Let's do that one on the same forum thread that savanah creates, because I think it's a reasonably advanced question, but, generally speaking the time zone in a properly formatted date will be included in the string and it should format it. It should pull it out correctly and turn it into a universal time zone. So, generally speaking, it should handle it for you, so I noticed you for indexing a column to shrink when we use the is there any consideration? The square brackets one is safer, particularly if you're assigning to a column. If it didn't already exist, you need to use the square brackets format. Otherwise, you'll get weird errors, so the square brackets format is sofa. The dart version saves me like a couple of keystrokes, so I probably use it more than I should in this particular case, because I wanted to grab something that was had field name was had something inside it wasn't the name itself. I have to use square brackets, so square brackets is going to be your your safe bet, if in doubt so after I run that you'll notice that DF r or dark columns gives me a list of all of the columns just as strings and at the end There they all are right, so it's removed sale date and it's added all those. So that's not quite enough. The other problem is that we've got a whole bunch of strings in there right. So you can just think that they're doing to pass a bet so is like low high medium. Thank you.
So
(autogenerated subtitles follow, may contain gibberish/bad format - please proofread to improve - remove this note once proofread)
A pandas actually has a concept with a category data type, but by default it doesn't turn anything into a category for you. So I've created something called Train cats, which creates categorical variables for everything. That's the string, okay, and so what that's going to do is behind the scenes it's going to create a column, that's actually a number right as an integer and it's going to store a mapping from the integers to the streets. Okay, the reason it's trained cats, as it uses for the training set more advanced usage, is that when we get to looking at the test and validation sets, this is really important idea. In fact, Terrence came to me the other day and he said my models not working. Why not? And he figured it out for himself - it turned out the reason. Why was because the mappings he was using from string to number in the training set were different to the mappings? He was using from string to number in the test set. So therefore, in the training set, hi might have been three, but in the trait test set. It might have been two, so the two were totally different, and so the model was basically non predictive. Okay, so I have another function, called apply categories where you can pass in your existing training set and it all use the same mappings to let you all make sure your test set of validation set uses the same mappings okay.
So when I go trained cats, it's actually not going to make the data frame look different at all, but behind the scenes it's going to turn them all into numbers. When we finish at 12 11:50 - let's see here, we go I'll, try to finish on time. So you'll see now remember I mentioned there was this dot DT attribute that gives you access to everything, assuming it's a date time about the date time. There's a dot count attribute that gives you access to things as something's, a category all right and so usage banned. Was a string and so now that I've run train cats, it's turned it into a category, so I can go to your or usage banned cat right and there's a whole bunch of other things. We've got there, okay, so one of the things we've got, there is dot categories and you can see here is the list. Now one of the things you might notice, it's that this list is in a bit of a weird order: high low medium. The truth is it doesn't matter too much, but what's going to happen when we use the random forest, is it's actually good that this is going to be 0? This is going to be 1. This is gon na, be true and we're going to be creating decision. Trees and so we're going to have a decision tree that can split things at a single point, so it either be high versus low and medium or medium versus high and low. That would be kind of weird right. It actually turns out not to work too badly, but it'll work a little bit better if you have these in sensible orders.
Okay. So if you want to reorder a category, then you can just go caps net categories and pass in the order you want until it is ordered, and almost every pandas method has an in-place parameter, which, rather than returning a new data frame, is going to change that Data frame, okay, so I'm not going to do that. Like I didn't check that carefully for categories it should be ordered, but this seems like a pretty obvious one. You reiterate that issue. I don't understand what the chart so um the usage banned column. It's actually going to be. This is actually what I random forest is gon na see these numbers one zero, two one: okay and they map to the position in this array and as we're going to learn shortly, a random forest consists of a bunch of trees. It's going to make a single split and the single split is going to be either greater than or less than 1 or greater than a less than two right, so we could split it into high versus low and medium, which that semantically makes sense it's like. Is it big or we could split it into medium versus high and low? It doesn't make much sense right, so in practice, the decision tree could then make a second split to say like medium versus high and low and then within the high and low into high and low, but by putting it in a sensible order if it wants to Spit out low, it can do it in one decision rather than two and we'll be learning more about this shortly.
It's it honestly, it's not a big deal, but I just wanted to mention it's there and it's also good to know that people when they talk about like different types of categorical variable, specifically, you need to know, there's a kind of categorical variable called ordinal and an Ordinal categorical variable is one that has some kind of order like high medium and low. Okay and random. Forests are terribly sensitive for that fact, but it's worth noting it's there and trying it out still ordering wouldn't sell for maximum that. That's what I'm saying it helps a little bit right. It means you can get there with one decision rather than two. I noticed there is a negative one in that list of categories. Is that, like an NA yeah exactly so for free, we get a negative one which prefers to missing and what are the things we're going to do? Is we're going to actually add one? Can somebody pass the vector Paul? Is we're going to add one to our codes? Maybe in two guys let people know it's coming yeah, so let people know we're going to add one to all of our codes to make missing a zero later on yeah we're going to get to that yeah yeah. So get dummies which we'll get to in a moment, is going to create three separate columns, ones and zeros for high once there's a million ones in series for low. Where else this one creates a single column with an integer zero one or two we're going to get to that one shortly. Yep did you have a question to Paul or just pointing out? Okay, okay.
So at this point, as long as we always make sure we use dot cat codes, the thing with the numbers in we're basically done all of our streams have been turned into numbers. Dates been turned into a bunch of numeric columns, and everything else is already a number okay. The only other main thing we have to do is notice that we have lots of missing values. So here is DFA. Is null that's going to return true or false, depending on whether something is empty dot? Some is going to add up how many empty for each series and then I'm going to sort them and divide by the size of the data set. So here we have some things which have like quite high percentages of Nantz, sir, so missing values we call them in play or what I call it. Maybe I didn't run it there. We go okay, so we're going to get to that in a moment, but I will point something out which is reading the CSV talk a minute or so the processing took another ten seconds or so from time to time. When I've done a little bit of work. I don't want to wait for again. I will tend to save where I'm at so here, I'm going to save it and I got to save it in a format called feather format. This is very, very new all right, but what this is going to do is it's going to save it to disk in exactly the same basic format, but it's actually in RAM. This is by far the fastest way to save something in the fastest way to read it back right.
So most of the folks you deal with unless they're on the cutting edge won't be familiar with this format, so this would be something you can teach them about. It's becoming the standard right, it's actually becoming something that's going to be used, not just in pandas, but in Java, in spark in lots of like things for like communicating across computers, because it's incredibly fast and it's actually co-designed by the guy that made Panthers by where's Mckinney, so we can just go deer 4.2 feather and pass in some name. I tend to have a folder called temp for all of my like as I'm going along stuff, and so when you go OS, don't make do as you can pass in any path path. Here you like, it won't complain if it's already there exists, okay equals true. If there are some sub directories, it'll create them for you. So this is a super. Handy little function, okay, so it's not installed so because I'm using Crestle for the first time. It's complaining about that. So if you get a message that something's not installed, if you're using anaconda, you can condor, install Crestle actually doesn't use anaconda, it uses a pit you, and so we wait for that to go along okay, and so now, if I run it and so sometimes
(autogenerated subtitles follow, may contain gibberish/bad format - please proofread to improve - remove this note once proofread)
You may find you actually have to restart Jupiter, so I won't do that now, it's really out of time. So, if you restart Jupiter you'll be able to keep moving a lot so from now on, you don't have to rerun all the stuff they love. You could just say: PD, don't read further and we've got our data frame back. So the last step we're going to do is to actually replace the strings with their numeric codes and we're going to pull out the dependent variable sale price into a separate variable and we're going to also handle missing continuous values. And so how are we going to do that so you'll see here, we've got a function called proc DF. What is that croc DF? So it's in so fastai, dot, structured again, and here it is so quite a lot of the functions have a few additional parameters that you can provide and we'll talk about them later, but basically we're providing the data frame to process and the name of the Dependent variable that the the Y field - name - okay, and so what it's going to do is it's going to make a copy of the data frame? It's going to grab the Y value, it's going to drop the dependent variable from the original, and then it's going to fix missing. So how do we fix missing? So what we do to fix missing is pretty simple. If it's numeric, then we fix it by basically saying, let's first of all check that it does have some missing right, so if it does have some missing values, so in other words the is not some is nonzero, then we're going to create a new column called With name as the original plus underscore na, and it's going to be a bullion column with a 1 anytime that was missing and a 0 anytime.
It wasn't we're going to talk about this again next week, but this is, you know, give you the quick version. Having done that, where they're going to replace the NA s, the missing with the median okay so anywhere that used to be missing will be replaced with the median or add a new column to tell us which ones were missing. We only do that for numeric. We don't need it for categories because pandas had is handles categorical variables automatically by setting them to minus one. So what we're going to do is if it's not numeric and it's a categorical type, we'll talk about the maximum number of categories later but lets us units is always true. So if it's not a numeric type, we're going to replace the column with its codes, the integers, okay, plus one right so the by default pandas uses minus one for missing. So now zero will be missing and one two three four will be all the other categories. So we're going to talk about dummies later on in the course, but basically optionally. You can say that if you already know about dummy values, there are columns with a small number of possible values you can put in two dummies. Instead, you can America lysing them, but we're not going to do that for now. Okay, so for now all we're doing is we're using the categorical codes plus one replacing missing values with the median, adding an additional column telling us which ones were replaced and removing the dependent variable. So that's what proc DF does runs very quickly.
Okay, so you'll see now sale price is no longer here. Okay, we've now got a whole new color, a whole new variable called Y, the contain sale press you'll see we put a couple of extra blah underscore na s at the end. Okay, and if I look at that, everything is a number okay. These boolean z' are treated as numbers. They're just considered contributed a zero, or one that is displayed as false and true they can see here is at the end of a month, is at the start of a month, is at the end of a quarter. It's kind of funny right because we've got things like a model ID which presumably is something like that could be a serial number. It could be like the model identifier, that's created by the factory or something we've got like a data source ID like some of these are numbers but they're, not continuous. It turns out actually random forests work fine with those we'll talk about. Why and how and a lot about that in detail, but for now all you need to know is no problem. Okay, so as long as this is all numbers which it now is, we can now go ahead and create a random forest, so m dot random forest regressor random forests are trivially paralyse abour. So what that means is that they, if you've, got more than one CPU, which everybody will basically on their computers at home and if you've got a t2 dot medium or bigger at AWS. You've got multiple CPUs trivially paralyse Abul means that it will split up the data across your different CPUs and basically linearly scale right.
So the more CPUs you have pretty much. It will divide the time it takes by that number, not exactly but roughly so n jobs equals minus one tells the random forest regressor to create a separate job. It's a separate process, basically for each CPU. You have so that's pretty much what you want all the time fit the model using this new data frame we created using that Y value, we pulled out and then get the score. Ok, the score is going to be the r-squared we'll define that next week. Hopefully, some of you already know about the r-squared. One is very good. Zero is very bad, so, as you can see, we've mmediately got a very high score. Okay, so that looks great. But what we'll talk about next week, a lot more, is that it's not quite great, because maybe we had data that had points that look like this and we fitted a line that looks like this when actually we want to want normal, it looks like that. Ok, the only way to know whether we've actually done a good job is by having some other data set, that we didn't use to train the model. Now we're going to learn about some ways with random fire, we can kind of get away without even having that. Other data set, but for now what we're going to do is we're going to
(autogenerated subtitles follow, may contain gibberish/bad format - please proofread to improve - remove this note once proofread)
Split into twelve thousand rows, which we're going to put in a separate data set called the validation set versus the training sets going to take, contain everything else right, and our data set is going to be sorted by date, and so that means that the most recent Twelve thousand rows are going to be our validation set again. We'll talk more about this next week. It's a really important idea, but for now we can just recognize that if we do that and run it, I've created a little thing called print score and it's going to print out the root mean square error between the predictions and actuals for the training set for The validation set that r-squared for the training set and the validation set and you'll see that actually the r-squared for the training was 0.98, but for the validation was 0.89 okay, then the RMS see and remember this is on the logs was point: oh nine, for the Training set 0.25 for the validation set. Now, if you actually go to cattle and go to the leaderboard okay, let's do it right now. He's got private and public. I click on public leaderboard and we can go down and find out. Where is point two five, so there are four hundred seventy-five teams and, generally speaking, if you're in the top half of a capital, competition you're doing pretty well so a point two-five here we are point two five: what was it exactly point? Two five by two 507 yeah about a hundred and tenth so we're about in the top 25 %. So so the idea like this is pretty cool right with with like, with no thinking at all, using the defaults of everything we're in the top 25 % of a caracal competition, so like random, forests are insanely powerful, and this totally standardized process is insanely good.
For like any datasets, so we're gon na wrap up well, what I'm going to ask you to do for Tuesday, it's like take as many tackle competitions as you can, whether they be running now or old ones or datasets. That you're interested in for your hobbies will work and - and please try it right, try this process and if it doesn't work, you know tell us on the forum: here's the data, so I'm using here's where I got it from his like the stack trace of where I got an error or here's like you know, if you use my print score function or something like it like you know, show us what the training versus tests it looks like we'll, try and figure it out right, but what I'm hoping we'll find is that all Of you will be pleasantly surprised that, with with the you know hour or two with information you got today, you can already get better models than most of the very serious practicing data scientists that competing table competitions. Okay, great good luck and I'll see you on the forums. Oh one more thing, Friday. The other class said a lot of them had class during my office hours. So if I made them one till three instead of two two or four on Fridays, is that okay seminar, oh okay, I have to find a whole another time all right. I will talk to somebody who actually knows what they're doing, unlike me, about finding other cells.
Absolutely


| 1. Let's recap what we did in the last video. | |
| 2. We had this differential equation here, then we found that it had two linearly independent solutions, e to the t and e to the three t, and we said that the general solution to this differential equation is a linear combination of these two solutions, just a constant times one solution plus another constant times the other solution. | |
| 3. What I want to talk about in this video is, why is this the case? | |
| 4. Why is the general solution a linear combination? | |
| 5. How does that even result from this property of linearity of the differential equation? | |
| 6. Let's get started. | |
| 7. We know that y is equal to e to the t, we know that's a solution to this differential equation, it satisfies it. | |
| 8. What would happen if we were to multiply this solution by constant, like c or c could be any number like two, point five, negative twelve, anything, it's just a constant. | |
| 9. Is it constant times a solution still a solution? | |
| 10. Let's find out. | |
| 11. We take the first derivative, that's just c times e to the t, and likewise, the second derivative, that's also c times e to the t. | |
| 12. If were to plug these into here, we get that the second derivative minus four times the first derivative, plus three times y, that's equal to zero. | |
| 13. Every term has a c times e to the t term, so we can factor that out, we get c times e to the t times, one minus four plus three, that should be equal to zero. | |
| 14. We knew that one minus four plus three is zero, so we get that zero is equal to zero, and this holds. | |
| 15. C times e to the t is also a solution, which means if we multiply solution by any constant, it is still a solution to this differential equation. | |
| 16. That means that, pi times e to the t satisfies it, that means a million times e to the t satisfies this, that means point zero zero one times e to the t satisfies it. | |
| 17. They are all solutions. | |
| 18. Now, let's take a look at one other thing. | |
| 19. We know that, e to the t is a solution, and we knew that e to the three t is a solution, but what would happen if we were to add them together? | |
| 20. Is the sum of two solutions also a solution? | |
| 21. Let's find out. | |
| 22. Let's take the first derivative again, that's just e to the t plus three e to the three t. | |
| 23. Let's take the second derivative, that's just e to the t plus nine e to the three t. | |
| 24. If we plug that into the differential equation, we get the second derivative e to the t plus nine, oops, e to the three t minus four times the first derivative, e to the t plus three e to the three t plus three times our zero derivative, that should be equal to zero, we'll see. | |
| 25. Let's group together all the two like the e to the t terms in all the e to the three t terms together. | |
| 26. So we get e to the t, I am going to factor it out, and say, times one minus four plus three plus e to the three t, grouping all these terms together times nine minus four times three is minus twelve plus three is then equal to zero. | |
| 27. We know that, one minus four plus three is zero, and nine minus twelve plus three is zero, so, we have e to the t times zero plus e to the three t times zero is equal to zero. | |
| 28. That is also true. | |
| 29. A sum of two solutions is also a solution. | |
| 30. Now, let's combine these two facts that we learned. | |
| 31. Let's take our solutions, multiply them by constants and add them together, but there is a name for that. | |
| 32. What's it called? | |
| 33. It's called, taking the linear combination of our two solutions. | |
| 34. We know that since multiplying by a constant works in, by adding our two solution works, we know that, this linear combination is also a solution. | |
| 35. In fact, we like to call it the general solution, because it can describe all possible solutions to this differential equation, describes every possible solution. | |
| 36. If you have a linear differential equation, the general solution is a linear combination of the linearly independent solutions. | |
| 37. You are going to hear the word, linear quite a lot in this video. | |
| 38. That's all a very important property that, all is a case for a linear differential equation. | |
| 39. What makes a linear differential equation so special? | |
| 40. In order to really answer that, we have to take a step back. | |
| 41. Let's move away from differential equations, and just think about Math in abstract terms. | |
| 42. Let's say, we have a function g of x. | |
| 43. We say that something operates on this function, you can call it an operator f. | |
| 44. If it inputs one function, then we get out another function, let's say, h of x. | |
| 45. There are lots of examples of operators. | |
| 46. Just something that changes one function to another function, like multiplying by a constant is an operator, taking a derivative is an operator, squaring something is an operator. | |
| 47. All these things in taking one function as an input, and giving another function as an output. | |
| 48. Just like thinking in abstract terms. | |
| 49. There is an important class of operators called, linear operators. | |
| 50. Linear operators, all share one very important property. | |
| 51.  This is equal to a times f operated on g of x plus b times f operated on h of x. | |
| 53. This may seem fairly confusing when we think of it in very abstract terms, but we'll find that they are quite a lot of examples of linear operators. | |
| 54. Let's make things more clear. | |
| 55. Instead of using this input, let's take a look at two x plus three x squared, and we'll find that multiplying by a constant is a linear operator, because if we are to multiply this by four, we know that's the same as just two times four times x plus three times four times x squared. | |
| 56. We'll find that basically saying that this operator or this entire input is the same as it operating on one input, with the same scalar plus operating the other input with the same scalar. | |
| 57. Now, we'll find that there are other examples of linear operators. | |
| 58. Like, taking a derivative is a linear operator because if we take e derivative, we take the derivative term by term. | |
| 59. That's two times the derivative of x plus three times the derivative of x squared. | |
| 60. We'll find that, taking a definite integral is a linear operator. | |
| 61. Because likewise, we integrate term by term. | |
| 62. And we know that, this is equal to two times the definite integral of x dx plus three times the definite integral of x squared dx. | |
| 63. Taking derivatives and integrating definitely, that's also a linear operator. | |
| 64. Now, what's an example of something that's not a linear operator? | |
| 65. One important class of non-linear operators is raising to an exponent. | |
| 66. If we had this two x plus three x squared, well, if we have this all squared, we know that, this is not equal to two times x squared plus three times x squared squared. | |
| 67. We know that, we have to factor out, and we'll have other terms. | |
| 68. So, raising to an exponent is not a linear operator. | |
| 69. We can form other linear operators by combining these, like taking a derivative and multiplying by a constant is a linear operator, taking higher derivatives is a linear operator. | |
| 70. If we add two linear operators, the result is almost like a linear operator. | |
| 71. In fact, we can say something like taking a derivative of a function, or secondary derivative of a function minus four times taking the derivative of a function plus three times that function, that's also a linear operator. | |
| 72. But this was just our differential equation. | |
| 73. It's is basically the same thing, except we had it under one constraint, that this was equal to zero. | |
| 74. It turns out, our linear differential equation is also a linear operator. | |
| 75. Since, it is a linear operator, some people like to use a little shorthand. | |
| 76. If this is all equal to zero, they may just say that the linear operator of this differential equation, acting on y is equal to zero. | |
| 77. Here, our L acting on y, that's just analogous to this whole f acting on g of x. | |
| 78. In this particular case, you can think of L as just equal to the second derivative minus four times the first derivative plus three. | |
| 79. L acting on y is just this acting on y. | |
| 80. So it's a little shorthand notation. | |
| 81. If we think about it, this makes sense that this linear differential equation, or at least this bit here is a linear operator. | |
| 82. Let's look back at the definition we used for a linear differential equation. | |
| 83. We said that a differential equation was linear, if it had a general form, a n of x times d nth derivative of a function with respect to x plus a to the n minus one, of x times the n minus one derivative, all the way down to let's just say, a one of x times the first derivative plus a naught acting on y. | |
| 84. We said that, this was a form of a linear differential equation, and the reason is, it's composed of linear operations. | |
| 85. If you recall, if we square or raised any of these derivative terms, to an exponent or if we multiply any of these derivative terms by each other, then it would be non-linear differential equation. | |
| 86. We know now, that's because, raising to an exponent, that's not a linear operation. | |
| 87. A linear differential equation is composed of linear operations. | |
| 88. How does this property of linearity show up for linear differential equations? | |
| 89. We'll find what we know. | |
| 90. Let's just say that we have two solutions that satisfy this differential equation, y one and y two, such that, L operating on y one is just zero and L operating on y two is equal to zero. | |
| 91. That means that, we can work in reverse, and say that L operating on c one times y one plus c two times y two, that's equal to using our main property of linear operators, that is equal to c one times L acting on y one plus c two times L acting on y two. | |
| 92. We know that, L acting on y one, that's zero and L acting on y two is equal to zero. | |
| 93. So, we get that, this whole thing is equal to zero, which means that this whole thing is also a solution. | |
| 94. It also satisfies this condition, that the linear operator is equal to zero. | |
| 95. Because our differential equation is linear, we know that if we have two solution that satisfy it, with that we can form a linear combination of those two solutions, and the result will still satisfy it. | |
| 96. That's exactly what we found up here, we found that, if we add two solutions that satisfy this differential equation, that the linear combination of them also satisfy it. | |
| 97. We just worked in reverse up here. | |
| 98. Here we went from the property and went forward, up here we had this and went backwards. | |
| 99. That's quite a lot. | |
| 100. Let's recap what we found in this video. | |
| 101. We were able to define a linear operator. | |
| 102. And we said that, our linear differential equations, that's a differential equation that's composed of linear operators, and because of this property that all linear operators follow, we know that, if we were to have two solutions, then a linear combination of these two solutions is also a solution. | |
| 103. We were able to theoretically show the origin of why a linear combination of two solutions is also a solution. | |
| 104. It all stems from this wonderful property of linearity. | |
| 105. Hopefully, that wasn't too confusing. | |
| 106. We'll continue on with more second order differential equations in the next video. |


Developers hate repeating themselves over and over again. It is especially true when we’re talking about writing CSS3 behaviours and we are forced to use the elusive vendor prefixes to tell every single browser what we want them to do. Don’t get me wrong, I don’t think vendor prefixes are necessarily evil, but they are very unconvenient for frequent use.
Delevopers like to come up with brilliant solutions to problems. Less is a good solution for people who want to write less CSS and don’t want to keep repeating themselves. You write some pretty Less code, which then will be compiled on the client side using JavaScript and will be turned into CSS. It works, that’s for sure, but there are some problems, whitch bother me about this solution:
- You use client-side JavaScript to generate your CSS
- You load an external JavaScript file to process your Less files (one extra http request)
- There is always going to be a short “psychological” delay between the content loading, the JavaScript loading and running, and the CSS displaying
I am not saying that these problems are very concerning, but still there must be a neeter way of doing Less, right?
Right!
As I was trying to get my head around Less today, I’ve found a very good article about Less compilers. Of course, what a brilliant idea! Use Less as you usually do, but instead of using the cient-side JavaScript solution, you use the compiler, that helps you to generate the output CSS whilst you are developing your content. The article mentions some cool Less compilers for Windows, Mac and Linux.
Now I am going to quickly go through of setting up the Less.app on Mac and will show you how to use it.
Using the Less.app (on Mac OS X Lion)
I tried the Less.app for Mac only, as I refuse to use Windows anymore :) The app is really lightweight (under 3Mb) and absolutely free. You can download it here.
After downloading the app, the user needs to unzip and run it.
The Less.app has a very nice, simple and easy to use UI with two tabs in the header for “Less Files” and “Compiler”.
Less Files
In the “Less Files” view you can drag-and-drop a web project on the side bar, and the app automatically searches for Less files in the structure.
Once the search is done, you can see your Less files in the “File & Output” panel. According to the Less.app tutorial when you drop your project on the side-bar, the app should automatically offer the output location for the compiled CSS files, but for some reason it didn’t happen to me, so I manually had to set the output folder. To set your CSS output destination folder simpy right-click on the Less file in the list and choose “Set CSS Output Path”. There is an option for minifying your output CSS file, which comes very handy.
You can add multiple projects to the side-bar and then you can manage them separately, which is clever.
Before you compile your files you need to go to the “Compiler” view.
Compiler View
In the “Compiler View” you can see a list of your already done and pending processes. In the footer there is a checkbox for automatic compilation on save - this is a very smart feature: If you tick it, the app will automatically compile your CSS file every time you change and save your Less file. On the right hand side of the footer there is a button for clearing the list, and another one for compiling all your Less files.
Conclusion
After the very easy and straightforward setup process the Less.app is ready to go. All you need to do is to check if it’s running when you’re working on your project. When you save your less files, the app compiles silently in the background and generates your CSS files.
Whith Less compilers developers can get rid of using JavaScript for generating the CSS on the client-side, whilst they still can use Less code and save precious time for creative coding (and debugging) :)
I’d love to hear your voice! Do you use any Less compilers? What is your experience with them and why do you think using Less compilers is a good/bad idea?


This file contains prototype definitions for Modem Information APIs.
IPC interfaces binding
All the functions of this API are provided by the modemService.
Here's a code sample binding to modem services:
bindings: { clientExe.clientComponent.le_info -> modemService.le_info }
Query Firmware Version
le_info_GetFirmwareVersion() is used to query the current firmware version. le_info_GetBootloaderVersion() is used to query the current bootloader version. In both cases, the version is returned as a human readable string.
The linux kernel version can be queried using standard linux methods, such as the uname command, or the uname() API.
Query Device information
le_info_GetDeviceModel() is used to retrieve the target hardware platform identity.
le_info_GetImei() is used to retrieve the International Mobile Equipment Identity (IMEI).
le_info_GetMeid() is used to retrieve the CDMA device Mobile Equipment Identifier (MEID).
le_info_GetEsn() is used to retrieve Electronic Serial Number (ESN) of the device.
le_info_GetMdn() is used to retrieve the Mobile Directory Number (MDN) of the device.
le_info_GetMin() is used to retrieve the CDMA Mobile Identification Number (MIN).
le_info_GetPrlVersion() is used to retrieve the CDMA version of Preferred Roaming List (PRL).
le_info_GetPrlOnlyPreference() is used to retrieve the CDMA Preferred Roaming List (PRL) only preferences status.
le_info_GetNai() is used to retrieve the CDMA Network Access Identifier (NAI) string.
le_info_GetManufacturerName() is used to retrieve the Manufacturer name.
le_info_GetPriId() is used to retrieve the Product Requirement Information Identifier (PRI ID) Part Number and the Revision number. The Part number is a 7-digit string. Revision Number string contains 2-digit major version + '.' char + 2-digit minor version (xx.xx).
le_info_GetPlatformSerialNumber() is used to retrieve the Platform Serial Number (PSN) string.
Copyright (C) Sierra Wireless Inc. Use of this work is subject to license.


Sublet Paradise
Select your campus here:
Villanova University
Drexel University
Search
Add Your Property


Module: ActiveRecord::ConnectionAdapters::Quoting
| Relationships & Source Files | |
| Extension / Inclusion / Inheritance Descendants | |
|
Included In:
| |
| Defined in: | activerecord/lib/active_record/connection_adapters/abstract/quoting.rb |
Constant Summary
-
COLUMN_NAME =
private
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 174
::Regexp
for column names (with or without a table name prefix). Matches the following:"#{table_name}.#{column_name}" "#{column_name}"
/ \A ( (?: # table_name.column_name | function(one or no argument) ((?:\w\.)?\w) | \w+\((?:|\g<2>)\) ) (?:(?:\sAS)?\s\w+)? ) (?:\s*,\s*\g<1>)* \z /ix
-
COLUMN_NAME_WITH_ORDER =
private
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 198
::Regexp
for column names with order (with or without a table name prefix, with or without various order modifiers). Matches the following:"#{table_name}.#{column_name}" "#{table_name}.#{column_name} #{direction}" "#{table_name}.#{column_name} #{direction} NULLS FIRST" "#{table_name}.#{column_name} NULLS LAST" "#{column_name}" "#{column_name} #{direction}" "#{column_name} #{direction} NULLS FIRST" "#{column_name} NULLS LAST"
/ \A ( (?: # table_name.column_name | function(one or no argument) ((?:\w\.)?\w) | \w+\((?:|\g<2>)\) ) (?:\sASC|\sDESC)? (?:\sNULLS\s(?:FIRST|LAST))? ) (?:\s*,\s*\g<1>)* \z /ix
Instance Method Summary
-
#quote(value)
Quotes the column value to help prevent SQL injection attacks.
-
#quote_bound_value(value)
Quote a value to be used as a bound parameter of unknown type.
-
#quote_column_name(column_name)
Quotes the column name.
-
#quote_string(s)
Quotes a string, escaping any ‘ (single quote) and \ (backslash) characters.
-
#quote_table_name(table_name)
Quotes the table name.
-
#quote_table_name_for_assignment(table, attr)
Override to return the quoted table name for assignment.
-
#quoted_date(value)
Quote date/time values for use in SQL input.
- #quoted_false
- #quoted_true
-
#type_cast(value)
Cast a
value
to a type that the database understands. - #unquoted_false
- #unquoted_true
- #lookup_cast_type(sql_type) private
- #type_casted_binds(binds) private
- #column_name_matcher Internal use only
- #column_name_with_order_matcher Internal use only
-
#lookup_cast_type_from_column(column)
Internal use only
If you are having to call this function, you are likely doing something wrong.
- #quote_default_expression(value, column) Internal use only
- #quoted_binary(value) Internal use only
- #quoted_time(value) Internal use only
- #sanitize_as_sql_comment(value) Internal use only
Instance Method Details
#column_name_matcher
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 161
def column_name_matcher # :nodoc: COLUMN_NAME end
#column_name_with_order_matcher
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 165
def column_name_with_order_matcher # :nodoc: COLUMN_NAME_WITH_ORDER end
#lookup_cast_type(sql_type) (private)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 225
def lookup_cast_type(sql_type) type_map.lookup(sql_type) end
#lookup_cast_type_from_column(column)
If you are having to call this function, you are likely doing something wrong. The column does not have sufficient type information if the user provided a custom type on the class level either explicitly (via Attributes::ClassMethods#attribute) or implicitly (via AttributeMethods::Serialization::ClassMethods#serialize, time_zone_aware_attributes
). In almost all cases, the sql type should only be used to change quoting behavior, when the primitive to represent the type doesn’t sufficiently reflect the differences (varchar vs binary) for example. The type used to get this primitive should have been provided before reaching the connection adapter.
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 63
def lookup_cast_type_from_column(column) # :nodoc: lookup_cast_type(column.sql_type) end
#quote(value)
Quotes the column value to help prevent SQL injection attacks.
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 11
def quote(value) case value when String, Symbol, ActiveSupport::Multibyte::Chars "'#{quote_string(value.to_s)}'" when true then quoted_true when false then quoted_false when nil then "NULL" # BigDecimals need to be put in a non-normalized form and quoted. when BigDecimal then value.to_s("F") when Numeric, ActiveSupport::Duration then value.to_s when Type::Binary::Data then quoted_binary(value) when Type::Time::Value then "'#{quoted_time(value)}'" when Date, Time then "'#{quoted_date(value)}'" when Class then "'#{value}'" else raise TypeError, "can't quote #{value.class.name}" end end
#quote_bound_value(value)
Quote a value to be used as a bound parameter of unknown type. For example, MySQL
might perform dangerous castings when comparing a string to a number, so this method will cast numbers to string.
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 50
def quote_bound_value(value) quote(value) end
#quote_column_name(column_name)
Quotes the column name. Defaults to no quoting.
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 74
def quote_column_name(column_name) column_name.to_s end
#quote_default_expression(value, column)
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 95
def quote_default_expression(value, column) # :nodoc: if value.is_a?(Proc) value.call else value = lookup_cast_type(column.sql_type).serialize(value) quote(value) end end
#quote_string(s)
Quotes a string, escaping any ‘ (single quote) and \ (backslash) characters.
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 69
def quote_string(s) s.gsub("\\", '\&\&').gsub("'", "''") # ' (for ruby-mode) end
#quote_table_name(table_name)
Quotes the table name. Defaults to column name quoting.
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 79
def quote_table_name(table_name) quote_column_name(table_name) end
#quote_table_name_for_assignment(table, attr)
Override to return the quoted table name for assignment. Defaults to table quoting.
This works for mysql2 where table.column can be used to resolve ambiguity.
We override this in the sqlite3 and postgresql adapters to use only the column name (as per syntax requirements).
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 91
def quote_table_name_for_assignment(table, attr) quote_table_name("#{table}.#{attr}") end
#quoted_binary(value)
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 144
def quoted_binary(value) # :nodoc: "'#{quote_string(value.to_s)}'" end
#quoted_date(value)
Quote date/time values for use in SQL input. Includes microseconds if the value is a ::Time
responding to usec.
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 122
def quoted_date(value) if value.acts_like?(:time) if ActiveRecord.default_timezone == :utc value = value.getutc if !value.utc? else value = value.getlocal end end result = value.to_fs(:db) if value.respond_to?(:usec) && value.usec > 0 result << "." << sprintf("%06d", value.usec) else result end end
#quoted_false
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 112
def quoted_false "FALSE" end
#quoted_time(value)
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 139
def quoted_time(value) # :nodoc: value = value.change(year: 2000, month: 1, day: 1) quoted_date(value).sub(/\A\d\d\d\d-\d\d-\d\d /, "") end
#quoted_true
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 104
def quoted_true "TRUE" end
#sanitize_as_sql_comment(value)
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 148
def sanitize_as_sql_comment(value) # :nodoc: # Sanitize a string to appear within a SQL comment # For compatibility, this also surrounding "/*+", "/*", and "*/" # charcacters, possibly with single surrounding space. # Then follows that by replacing any internal "*/" or "/ *" with # "* /" or "/ *" comment = value.to_s.dup comment.gsub!(%r{\A\s*/\*\+?\s?|\s?\*/\s*\Z}, "") comment.gsub!("*/", "* /") comment.gsub!("/*", "/ *") comment end
#type_cast(value)
# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 32
def type_cast(value) case value when Symbol, ActiveSupport::Multibyte::Chars, Type::Binary::Data value.to_s when true then unquoted_true when false then unquoted_false # BigDecimals need to be put in a non-normalized form and quoted. when BigDecimal then value.to_s("F") when nil, Numeric, String then value when Type::Time::Value then quoted_time(value) when Date, Time then quoted_date(value) else raise TypeError, "can't cast #{value.class.name}" end end
#type_casted_binds(binds) (private)
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 215
def type_casted_binds(binds) binds.map do |value| if ActiveModel::Attribute === value type_cast(value.value_for_database) else type_cast(value) end end end
#unquoted_false
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 116
def unquoted_false false end
#unquoted_true
[ GitHub ]# File 'activerecord/lib/active_record/connection_adapters/abstract/quoting.rb', line 108
def unquoted_true true end


Author: {{quote.author|uppercase}}
Date published: {{quote.datePublished|date}}
This quote has been published for : {{quote.datePublished|dates}} years
Submitted by : {{quote.submitter}}


Use the table below to specify what specific classes and inheritors should be excluded from being checked by this inspection. This is meant for those classes which, although they inherit Serializable from a superclass, are not intended for serialization. Such classes would lead this inspection to report unnecessarily.
Powered by InspectionGadgets


[1]
The short time I had it NONE!; everything about it.
[2]
It isn't Vista; None, I bought a new I-MAC. I'm' happy.


Tools for the guided selection of satellite data and environmental predictors, the combination of remote sensing and animal movement data and the mapping of resource suitabilitz. Based on the paper by Remelgado et al. (2015) <doi:10.1002/rse2.70>.
| Version: | 0.2.7 |
| Imports: | raster, sp, caret, ggplot2, grDevices, pryr, plyr, Rcpp, lubridate, RCurl |
| LinkingTo: | Rcpp |
| Suggests: | knitr, rmarkdown, kableExtra, imager, devtools, lattice, rgdal, igraph, randomForest, e1071 |
| Published: | 2018-12-11 |
| Author: | Ruben Remelgado [aut, cre] |
| Maintainer: | Ruben Remelgado <remelgado.ruben at gmail.com> |
| BugReports: | https://github.com/RRemelgado/rsMove/issues/ |
| License: | GPL (≥ 3) |
| URL: | https://github.com/RRemelgado/rsMove/tree/master/ |
| NeedsCompilation: | yes |
| Materials: | README |
| CRAN checks: | rsMove results |
| Reference manual: | rsMove.pdf |
| Vignettes: |
Predicting Resource Suitability with rsMove |
| Package source: | rsMove_0.2.7.tar.gz |
| Windows binaries: | r-devel: rsMove_0.2.7.zip, r-release: rsMove_0.2.7.zip, r-oldrel: rsMove_0.2.7.zip |
| OS X binaries: | r-release: rsMove_0.2.7.tgz, r-oldrel: rsMove_0.2.7.tgz |
| Old sources: | rsMove archive |
Please use the canonical form https://CRAN.R-project.org/package=rsMove to link to this page.


Able Player Width Tests
This page includes various combinations of audio and video elements. The following rules apply for defining the size of an Able Player instance:
- If width and height attributes are present, these are used to set the default size of the player.
- The above attributes are not valid HTML for <audio>, but are still supported. However, to ensure valid code, data-width should be used instead.
- If no size attributes are present, the player defaults to the intrinsic width of the video.
- The player will not exceed the width of its container, and will scale appropriately in a responsive design.
For additional demos see the Index of Able Player Examples.
Audio Example 1 (default width)
- Width attribute: No
- CSS width of container: Unspecified
- Expected outcome: Player fills width of the screen
Audio Example 2 (width attribute)
- Width attribute: 800
- CSS width of container: Unspecified
- Expected outcome: Player is 800px wide
Audio Example 3 (width controlled by container)
- Width attribute: 800
- CSS width of container: 500px
- Expected outcome: Player fills width of container (500px)
Video Example 1 (Default Size)
- Video intrinsic size: 1920 x 1080
- Aspect ratio: 16:9
- Width/height attributes: Unspecified
- Width of container: Unspecified
- Expected outcome: Player fills width of the screen
Video Example 2 (Width attribute)
- Video dimensions: 1920 x 1080
- Aspect ratio: 16:9
- Width/height attributes: 800 x 450
- Width of container: Unspecified
- Expected outcome: Video displayed at 800 x 450
Video Example 3 (width controlled by container)
- Video dimensions: 1920 x 1080
- Aspect ratio: 16:9
- Width/height attributes: Unspecified
- Width of container: 500px (max-width 100%)
- Expected outcome: Video fills the width of its container, 500px or less.
Video Example 4 (4:3 Aspect Ratio)
- Video dimensions: 640 x 480
- Aspect ratio: 4:3
- Width/height attributes: Unspecified
- Width of container: 500px (max-width 100%)
- Expected outcome: Video fills the width of its container, 500px or less.
YouTube Example 1 (Unconstrained)
- Video dimensions: 640 x 360
- Aspect ratio: 16:9
- Width/height attributes: Unspecified
- Width of container: Unspecified
- Expected outcome: Player fills width of the screen
YouTube Example 2 (width attribute)
- Video dimensions: 640 x 360
- Aspect ratio: 16:9
- Width/height attributes: 800 x 450
- Width of container: Unspecified
- Expected outcome: Video will be displayed at 800 x 450.
YouTube Example 3 (width controlled by container)
- Video dimensions: 640 x 360
- Aspect ratio: 16:9
- Width/height attributes: Unspecified
- Width of container: 500px (max-width 100%)
- Expected outcome: Video fills the width of its container, 500px or less.
Vimeo Example 1 (Unconstrained)
- Video dimensions: Unknown
- Aspect ratio: Unknown
- Inline style dimensions: N/A
- Width/height attributes: N/A
- Expected outcome: Player fills width of the screen.
Vimeo Example 2 (width attribute)
- Video dimensions: Unknown
- Aspect ratio: Unknown
- Width/height attributes: 800 x 450
- Expected outcome: Video displayed at 800px wide
Vimeo Example 3 (width controlled by container)
- Video dimensions: Unknown
- Aspect ratio: Unknown
- Width/height attributes: Unspecified
- Width of container: 500px (max-width 100%)
- Expected outcome: Video fills the width of its container, 500px or less.


Profile
Sign Out
Tutor's Rating:
Name:
Name of the Tutor
Gender:
male/female/other
Locations:
Locations he could teach(offline teaching)
Tution Type:
institute, online, home-tution, tutor's place
Reviews:
Reviews about Tutor
Submit
About:
About the Tutor
Address:
Adress of Tutor(State, District, Pincode, City, Area)
Experience:
His/Her Experience
Educational Qualification:
Educational Qualification Details
Subjects & Classes:
Subjects: Classes/Courses: Board:
Time Slots Availability of Tutor
Time
Mon
Tue
Wed
Thr
Fri
Sat
Sun
Morning
Noon
Evening
Night
Enter
Request Phone Number


Dead simple client for interacting with the Metabase dataset API
metabasic.exceptions.
AuthError
Bases: Exception
Exception
ConfigError