Back to Index

fast.ai APL study session 8


Transcript

Good afternoon. Hello. Hi. How are you doing. Good. Very good. I always look forward to APL time. I was him. Hi, Serrata. Hello. I want to say hi to Joelle but I don't know how to pronounce his name. Good enough. It's Joelle. What country is that name from? It's Portuguese and Brazilian.

Okay. Great. Yeah, I came here because of a rate test though. I mean, if I had known that you were having these meetings open, I would have come in. Joining. Hi, Radek, how are you? I don't hear you. Great. Let's start. Anybody got anything they wanted to mention or talk about?

Hopefully Radek doesn't because his microphone's not working. He can use sign language or chat or something, I suppose. I was really worried that I maybe missed a lesson or something, but apparently there wasn't any, so I was like, oh. My bad. I was talking to JJ Larey, we were doing...

MBDev2 and Quoto were coming out in like a week's time, so I decided to do a two-way ask me anything with him, and that was... I scheduled it for like two hours before our time, and then we ended up going on for such a long time that I didn't really...

Yeah, I was late enough that I then thought, okay, I may as well cancel it, otherwise people might have come and gone, and then they'd miss out. You still don't hear me. Yes, we do hear you. Hello. Oh, you can hear me. Oh, wow. Okay. What button did you press, Radek?

I don't know. It just started to work. The technology continues to surprise me, but I just wanted to second what Tanishk said. I was also worried I missed a session because I couldn't come here on Friday, and I kept looking on the forums, but what a fabulous surprise. I don't need to diagnose a study session, but there will be also an interview with you to look forward to.

That is what a way to start a Tuesday. I sent Hamel a preview of the interview, and he said he really enjoyed it, so hopefully people like it. Cool. All right, I will share my screen. Okay. So a couple of things on the forum. So Adam, who has been apparently writing APL since pretty much as long as he could read or talk or something, pointed out that the way I'm doing operators is not quite right, which I was kind of aware of, but I was hand waving over, which I agree I should not be.

So let me show you what I mean. So operators, the issue is that operators themselves can be monadic or dyadic. So monadic operator means that you just have a function on the left of it, whereas a dyadic operator would have a function on the left and the right. Well, not necessarily.

It could be a function or an array on the left and the right, and would return a function. The functions that these operators return, regardless of their monadic or dyadic operators, can themselves be monadic or dyadic functions. I guess I should also say it could be, I don't know if people would say ambivalent or ambivalent.

Ambivalent sounds like they don't care to me, but anyway, ambivalent meaning to valences that could be dyadic or monadic. So if we look at the help, for example, they do point this out in the documentation. So operator slash. Okay, so this is operator slash. So this is the function being returned, which is monadic.

And then I know Serata asked about this and why it's reduced. Is this a dyadic version or something? No, it's not. This is something else. Slash is a monadic operator with a dyadic operand. Oh, okay. So the thing that it takes is dyadic and it returns. Okay, so this one only returns a monadic function.

Serata, what is n, y is reduced? How is this different to? Oh, no, this is dyadic. This is the dyadic function version. Okay. We don't hear you, Serata. Even though I can see, I hear you now. No, just the documentation is very intimidating. And I can't distinguish what is the difference between reduced and reduced and y.

So, okay. Well, in that case, this is a perfect example, because I don't know either. But I can see from here that it's a monadic versus a dyadic function. So what we could do is we could go all the way down to a fifth level heading here and say monadic function.

And then we could have dyadic function. Okay, the monadic function is called reduce. Okay, which means we can't put the name up here anymore. Well, maybe I should put both, reduce/reduce and ys. But how they write it? And ys reduce, okay. And ys reduce. Copy that. Dyadic function and ys reduce.

And so then copy. All right. Okay, so I4, we know what that is. That's fine. All right, what's this doing? So this is three, I think we have some more examples. Let me know if anybody figures out what this is doing. It seems one, two, three, two, three, four, window size of three.

Oh, so this is a yeah, so it's kind of chunking it. And then adding it. Okay, that makes sense. So you've got. Oh, no, it's not chunking it. I see. So we've got the numbers one to four. So it's adding the first. Oh, it's doing it's kind of like a moving average, right?

So if I did. A window sum, I guess. A window sum. A window sum, yes, exactly. So if I did three divided into. Turn on my APL keyboard. Three divided into. What's the swap thing again? Yes. So that would be like, yeah, that's like a moving average now, right?

The average of one, two, three, the average of two, three, four. Probably a better way to write that, but it's. And then lamp is. Cover. Moving average. Okay. Endowed some. Oh. Well, I don't need to put it here. But above. Endowed some. What does this do if you pass in an array as the alpha argument, like three, four or something?

Your microphone is so loud, it's kind of like distorting. I don't know if there's a way to like move it away from your mouth or change it. Or something. I'm sorry. That was two. That was three. That is better. That's actually almost too quiet, but I, that's, that's not going to drive me quite so crazy yet.

Say it again. Oh, I was wondering what, you know, this does, if you asked an array as the, the alpha argument, like three, four. Oh, that's a good question. I want to raise up. Let's find out. Moving average. Like that. Yeah, they don't like it. I would say X must be a simple scalar of one item integer.

What's the distinction between a simple scalar and an item integer? I mean, one thing I did want to do today or soon is something that Adam suggested, which is to look at the rank operator, which would allow us to deal with this nicely. For now, let's put that aside.

Okay. Yeah. So this one just is doing a sum of single things, which is not very useful. Okay. Identity element. This is kind of interesting, actually more of a mathematical or computer science idea, but I think we should keep it because that's part of what we're learning about is the idea of the identity element for an operation.

So. So basically, this is like if you want to start with a number and then add things to it, then starting with zero is the number you would want to start at to get the right answer. Zero plus a bunch of things gives you the addition of a bunch of things.

But for multiply, that's not true. For multiply, you have to start with a number one. And so, yeah, so APL seems to know what the identity element, at least for these operations is. That's interesting. Flipping the window when the scalar is negative. When the switch, sorry, where's the scalar negative?

Oh, the last one. Yeah. Yeah. Okay. Hang on. You're getting ahead of where I'm up to a little bit. Okay. So this is just showing the example with comma where comma means concatenate. That's easy enough. And all right, so then. Yeah, so it's just flipping it around. Okay, seems reasonable.

I'm not sure we need both of those. We have we done comma before. Does anybody remember. I don't remember doing it. I don't think we did. Oh, okay. Well, that's important. It's not the right button. Nothing to search for. No, we haven't. Okay, fine. Okay. So let's do comma.

I get a bit confused because I. You know, also do similar classes with my daughter and her friends. So I get confused about what I've done with whom, even though I'm trying to make them somewhat aligned. Okay, so here's comma. Presumably they call comma. Yes, they do. All right, my data is called rebel.

Which I saw came up on the forum. It's called that. The nice thing is that as we do more stuff, we can increasingly use examples directly from the docs, which is nice. Okay, so. Best. All right, so here is going to be. Two by two by two, two by two by two.

I guess we could print that out row in there as well. Oh, thank you. Two by two by two. Eight. Oh, no, it's just two by two. Okay, oh, I see that extra access is to show us that there's a second place. Cool. Okay, so cover just would be what we'd call flatten, I guess in pytorch.

I think it, it will not flatten nested list nested arrays out though. Right, which I don't think pytorch, which I don't think pytorch doesn't have them. But if we go into the documentation, they are actually different from the epsilon. Very subtle difference. I don't think we've done epsilon yet have we.

We should do it now. Okay, well we can do it now if that's something worth looking at. If we rebel that it doesn't really do anything, because it's yeah, because it's not a. It's not it's not a higher rank tensor. It's a array of arrays. I guess that's worth including.

And yeah, epsilon does flatten that out. I see. Let's do a simple one. Okay. Dietic comma. Oh, have we talked about axes yet. Ring a bell to anybody. Yes. Oh, we've got them here, but we haven't talked about them. Let's create a section for axes then. And so let's move these.

Because this is important. Okay, let's read access. Up to here. Okay, so comma three, four. Oh, I think the problem is my little sample one's a bit broken. See, that's why that's broken. Okay. This is kind of an X. This is probably kind of an operator that never mind.

So, axes are things you put in square brackets. After a function. And it lets you apply that function. Over a particular axis. Maxis. Yeah, I think we started talking about these briefly, perhaps. Okay, it does not follow the normal syntax of an operator so I'm not going to just call it a normal operator.

That's why we're getting at its own spot. And it can be applied to any dyadic primitive scalar function. This looks like a good example. Okay, so. So this is a function that's going to apply equals to columns, I guess. Let's see 145145. And so the way it describes it.

Does it say what it is. I found that kind of the way that helped me kind of understand what it's doing is with plus slash. Yeah, you use the bracket access to have a matrix on some of those. I'm hoping to do this before we do operators, though, which is why I was wanting to do a static version.

I'm just trying to find anywhere in the help to actually say what it does. I'm having trouble seeing that here. I don't think it actually says what R is, does it? That's weird. Maybe this is the description. The access operator can take a scalar. No, that doesn't really tell us either.

I think the APL wiki has a better information about it. Thanks under function access if I remember. It's got better search to bracket access. Well, we're directed to practice function access. Okay. I can exactly say what it is. It seems like like different functions have different ways that access affects them.

Is that what it is? Oh, is that the problem? I see. So it's hard to say exactly what it is because it varies. Okay. Okay, so I guess, yeah, this is what we're actually doing is we've got an access with a scalar dyadic function. So plus as well equals is a scalar dyadic function.

It applies it's an infix thing, which is going to have a scalar can have a scalar on the left and the right. Normally, it would apply element wise over the scalars. In this case, we've got an access. So it stretches the lower rank array. So the one on the left is lower rank.

This is rank one. To fit the higher rank. The elements of the row rank array are replicated. So we want to apply this column wise. So these are treated as columns. That makes sense. And so you get one four five equals one three five and then one four five equals two four six.

That's cool. Yeah, I think you're right. I think that's the issue. That does make life a little confusing. All right, so let's use this example. Okay, so Matt is two rows of three columns of that. Okay, so plus will be applied to columns. This is the lower rank. So this will become a bunch of columns of one and two.

So you get one and two added to this one and two added to this one and two added to this, which is exactly correct. Okay, I think that makes sense. And so now what we're about to discover is that, for example, Ravel has its own special behavior. With an access area, Ravel with axes.

Okay, is the access and it could be a fraction or integer or vector or empty. Well, okay, if it's a fraction. I do like access of length one is inserted. Okay. Oh yeah, you see the difference. We've got this. That's a bit subtle because you can't see it in the documentation right because they don't actually print the boxing.

So I'm glad we've got boxing on. So this is inserted a new access between the zeroth axis and the one axis. And I think we could use anything between zero and one it would do the same thing. So in NumPy, that would be the equivalent of indexing something with with non or NP dot new access.

All right. I think the documentation tried to show it by doing row of that to show that it's okay. Yeah, yeah, okay. Got it. You're right. You're right. Maybe we should do that as also just in case people don't notice the arrow. All right. If it's an integer. Then it only travels along those axes.

Okay, no worries. So we're going to create something called M. So what they had. Yes, it is. So what's happening here? Okay, so then we're traveling over axes one and two, which is these two that we index from one, I guess. What are we index from zero axes? Hopefully we index from one because that's what we normally do.

So that would suggest we're indexing over, traveling over these. We're left with six four. Oh, okay. Okay. Wait, no, I'm slightly confused. This is the opposite of what I expected. So this is left the trailing axis on its own and the first two axes have been combined. Oh, so that's what this is saying is combine these two axes.

Yes, it is. You can see here it's combining those two axes. Does that make sense? Anybody have any questions about that so far? I haven't done unravel, so I have no idea. Is that a thing? I remember reading about it like I came across it with numpy before and it was like something numpy has some kind of like a ravel method and I was like confused like I'm not sure if that's the opposite of just in English.

I've actually seen that word just by itself like that. Oh, I've not seen it in normal. It's always just unravel something. Oh, there's reveal the composer. Oh, here we go. Apparently it exists to disentangle or unravel. Well, that's confusing to become unwoven. Sounds the same as unravel. Like inflammable means flammable.

So it's one of those things. Well, thank you for checking the dictionary for me. Somebody said hello in the chat. Hello Miguel. Are you able to speak or are you just on text chat today. Miguel said, I'm able to speak. I've just been lurking. Yeah, tell us what you said in the chat.

Yeah, um, ravel I does, I do think means the opposite of unravel. Yes, I mean tell us what you said earlier in the chat. You had something that big. Yeah, I joined a while ago, I, I'm also a fan of rate programming languages and memorization techniques so I caught up with earlier sessions, and I made an anchor deck for the BQ English.

And is that in here somewhere. Oh yeah, Miguel raises anchor deck. Yeah, excellent. So how long. Okay, so let me just go back a bit so probably not everybody here knows what bqn is so to tell us about bqn. Bqn is a another offshoot of apl. It's free and open source.

And if you go to the community page there. That's the online rebel to so you can just try it out in your browser. And there's no my Anki deck link there, so that you can also learn the glyphs on the community page. Where's the sorry so there's a online ripple here somewhere.

Yeah. Oh, you mean on here. Yeah. That's. Oh, you can actually this is. I see. That's nifty. So, bqn, all I know about it really is from listening to the arraycast episode with the creator of it Marshall Lockburn, who used to work at bqn, and from listening to the arraycast chat with the CTO of dialogue.

He described Marshall is basically wanting to go too fast. So Marshall left dialogue, and rather than trying to turn apl into the thing he really wanted it to be he decided to start from scratch and create a new array language to be all the stuff that he wished dialogue, apl was I guess I wished apl was based on, you know, all the things we've learned about array programming since it uses its own character set, which some things look familiar to me.

Like down style and up style. And these ones look the same but there's also some symbols that aren't an apl. Yeah, there's also something interesting where they use stranding for the limiting lists. So that reduces ambiguity and though yeah that's this one here right. Yeah, yeah, so stranding means this.

Okay, so apparently this was a huge area of contention some decades ago, being able to basically do this to create an array of arrays is is called stranding. And in bqn can you can you create a list like this or even this list would require that stranding character. You need the stranding character.

Yeah, okay so you can't just write one space to play space three instead you have to use this, this thing. So, one, three. What just happened. That didn't work where expected. Oh that error must do something different what I thought it did. Do I have to press enter instead.

What button do I press to. I do shift. I do shift got it there we go. Okay. Yeah. So I think it took some of the ideas from J. Some ideas from apl. Some ideas that aren't an apl yet. So definitely something I'm keen to check out at some point.

So your thoughts so far Miguel about bqn, like, as a language for learning array programming or sand or doing data analysis and or having fun. There's less literature than apl, which has decades. So, translating a lot of the materials into bqn is interesting. I enjoy it. I found it ways here to get started with because I couldn't work out how to download the API thing and get it working on my computer so I just started with bqn and jails just, I think, put a little joke in the chat which I think I understand he said it's the less healthy version of apl assume where apl we read as Apple and bqn we read as bacon.

Yeah, yeah, exactly. Okay, I got it. And according to the documentation for bqn you're not meant to call it bacon unless you're making a joke. So, you are allowed to call it bacon in this situation. All right. Nice. We are not as yet unraveled, I don't think so. Guess we should do this one now.

I had it, comma. All right. So this one looks pretty straightforward. Well, not quite straightforward, actually. So we need our cube back again. All right, so this is just concatenate, which, as folks on the chat have pointed out. Hang on, there's some contention here. Concatenate. Miguel wrote catenate is the opposite of concatenate, but I think actually no.

Catenate is the same as concatenate, and so I think we are here we are concatenating 4, 5, 6 to 1, 2, 3. And here we are taking our 2x2x2 cube and concatenating 99 to the kind of innermost axis, I guess. Which presumably the documentation will explain to us. Oh, and then there's a different version, which is comma bar, I guess you would call that, which we should probably therefore also mention.

I guess that's catenate first, is it? Yes, it is. So is there anything else to know about comma bar? Oh, that means something else entirely, does it? Is this transpose? Gosh, what a rabbit hole. Oh, that's weird. It's not quite transpose. Curious. All right, so catenation with an integer or implied access specification, they're joined along the required access.

What does that mean, the required access? Why does this appear at the bottom? Because you can denote the axis you want to concatenate along with the index. Oh, it's because this has come about. That's why. Yeah, the required access, I guess, is implied to be. Yes, it's specified. The last axis is implied.

Okay, so the comma bar and comma are the same thing, but comma bar implies the first axis and comma implies the last axis. And we write comma bar. On the APL card, it explains it a little, like, maybe exactly almost what you said, Jeremy. Okay, cool. Great. So I can use the comma bar to be helpful if I have a, I'm working with tabular data, if I have a data frame shape or a matrix, I can use comma bar with a vector of strings to print out a header row, so I could see what all the columns are.

That makes sense. I'm standing too lazy to stand. Okay, cool. I think at this point, we don't necessarily need to explain how to use every kind of access in every case, because it might get a bit boring. Not surprisingly, if you've got a fractional access, it kind of works the same way they joined along a new axis.

Well, unless it's useful for seeing an example. No, that probably is useful, right? This is kind of like another way of doing what Isaac was just describing. Because here you had to already have two rows. But here you only have a rector, and you want to make it into a matrix by adding the row.

So this is the equivalent of stack in PyTorch versus cat in PyTorch. So yeah, that's probably worth mentioning. Okay. So, shift, comma, which presumably is called comma bar, and the monadic form of that is a table. Okay, which I'm pretty confused about what it's for. Maybe we should look up AP or wiki.

Just in case it knows what it's for. Table. Yeah. Apply ravel to each major cell. So I think that's like the biggest, you know, subarrays. For arrays of rank one or higher, it's identical to applying ravel to major cells. So ravel will flatten, so it'll flatten each major cell.

I don't understand what this is doing. It's quad A. Is that like something they define or is that part of the language? Copy is A2Z. Oh, okay. Well, let's put that in our string section, shall we? Cool. Good to know. All right. So this is the five row on something that's 26 long is just going to give you the first five characters.

And so that's A, B, C, D, E. Now what's going on? This is a function. Oh, okay. It applies. This is just composition. So it applies this function and then it applies this function. So first of all, it applies the function ravel. And then it applies this function, which prints out the original argument and the shape of that argument.

That's kind of nifty. So it's showing us that the result of this table or ravel items is A, B, C, D, E and that the shape of it is 5, 1. And then here it's showing us that comma underbar hasn't done anything as far as I can tell. Let's check.

Okay, so that's done nothing at all. They could have told us that. But here's. Yeah, so here it's applying ravel to major cells. So the major cells here are lists of four. The major cells here are vectors of four. The major cells here are matrices of three, four. So it's raveling those major cells, the two major cells that we have.

Okay, so. Let's use that example then. Okay. I'm going to write ravel items here because I think that's easier for me to understand what that means. For an item, I guess they mean a major cell. So this contains two major cells, each of size three by four. And so therefore this is turning them into two length 12 major cells.

It's a raveling the items. It's a scalar arguments converted to a one by one matrix. And I guess this example is useful as well, which is basically like transpose, but it's kind of adding the axis. So we should put that first. Actually, maybe first we should put the scalar version.

That's that. Does anybody know what this is for? It's equivalent to this operation, which we haven't done yet, which so we should do that soon. And we haven't done that yet. It's annoying. So we should come back probably to this idea, I guess. So then we could do dyadic.

Catnip first. Presumably this will be the same. Yes, it is. But this will be different. And presumably once we add an access specification, it will make no difference because the only difference between them is the assumed access specification. Correct. And okay, cool. All right, we have here that. So, maybe we should do axes with operators.

Okay. Okay, so dyadic. Dyadic mixed functions. What does that mean? Dyadic mixed functions. Oh, these are not with an operator. So the plus slash, is it Isaac was suggesting plus slash with axis. How would that work? Because that's not a dyadic function. Yeah, I guess that's a dyadic. Ah, it can be a function derived from slash.

Okay. Right. Like with a matrix, you can do plus slash bracket one and then plus slash bracket two, and you'll see a row wise some versus a column wise some. I see. It's not defined here but I guess minimum or maximum works with it too. Jeremy you have a paper.

I'm going to check. Yes, where's my typo. Go up the SC, not as go up. Yep. Yep. That's not a typo. That's what I want axes. That's the plural of access. Maybe I should say access rather than axes, I guess. I suppose so. All right. Well, yeah, okay. So I guess we want to, we want to make tricks then set the idea.

And then we would say, plus slash over one is that how we do it. Yep. Okay. And if you did a bracket to that's kind of the same thing as the default, which would be, you know, the same 615. Just my daughter wants me actually maybe that's a good time to go.

All right, cool. Thanks gang. See you next time. Have a good one. Bye. Yeah.