New Home

Until now my “home in the cloud” has been DigitalOcean, and I’ve been pretty happy with them. Five bucks a month for a VPS, what’s not to like? But then I upgraded it to ubuntu 20.04, and the 1G of memory on my little cheapo machine could not keep up.

I looked around at other providers and it seemed that most of them were charging about $5/G of memory. But then I found this place VPSDime, that was charging $7 for a VPS with 6G of memory! I was immediately suspicious, of course. Is this a fake website that is going to rip me off? Is this part of some international spy ring?

I signed up anyway, though, because that’s how I roll. And so far this thing is blazingly fast, and I haven’t been ripped off or taken to international spy prison. So I am calling this a success!

Multiple Outputs Bad

As promised I have attempted a neural network with multiple outputs. This is a misnomer on my part I think, because it is still a single output, just with multiple possible values. Instead of a 0 or 1, the network outputs a number from 0..12, one value for each of the possible “moods” of the input sentence.

I didn’t have to change much to get this to work. I changed the output size from 1 to 13, and then I had to make one little tweak to get it to match the example I was copying. Let’s see if I can show you with some spiffy code blocks.

    def forward(self, x, hidden):
        """
        Perform a forward pass of our model on some input and hidden state.
        """
        batch_size=x.size()

see that x.size() there? I had to change it like this:

    def forward(self, x, hidden):
        """
        Perform a forward pass of our model on some input and hidden state.
        """
        batch_size=x.size(0)

This fixed an error I was getting that looked like this:

Traceback (most recent call last):
  File "multiple_output.py", line 244, in <module>
    output, h = net(inputs.type(torch.LongTensor), h)
  File "C:\Users\John\AppData\Local\Programs\Python\Python38\lib\site-packages\torch\nn\modules\module.py", line 550, in __call__
    result = self.forward(*input, **kwargs)
  File "multiple_output.py", line 172, in forward
    sig_out=sig_out.view(batch_size, -1)
RuntimeError: shape '[55, 44]' is invalid for input of size 31460

There now, aren’t those nice code blocks? I am glad they are, because I have no idea why I had to make that change. There is one clue within the error: 55 x 44 x 13 just happens to equal 31460. So, one could presume that our new output scheme caused this sig_out thing to multiply in size by a factor of 13. But how does batch_size=x.size(0) address that? There is no factor of 13 in there; x is 55 x 44, and x.size(0) gives us 55. Well, I will have to revisit this topic once I know what I’m talking about. For now, consider it magic fairy dust.

Or maybe not so magic, because the accuracy of this new network is pretty sad: 10%.

On its surface this does not seem all that surprising, since we now have a single network that is trying to accomplish 13 different things instead of 13 different networks each trying to accomplish a single thing. Why wouldn’t it be terrible? There are a lot of reasons why this whole scheme might be terrible, which I will pick apart in future posts. But now it is time to take a break from the mysteries of neural networks, and actually put these things in a UI where they can be tested with live input. For this I am going to attempt to use Django, since that is another tool that all the hip kids can’t live without. This dovetails nicely since all this stuff is in Python anyway.

Oh one last code block… I should probably let you know what my data looks like, in case you want to try this at home. Here’s a sample:

    {
        "sentence": "Here's a sentence in which I am happy",
        "grateful": 0,
        "happy": 1,
        "hopeful": 0,
        "determined": 0,
        "aware": 0,
        "stable": 0,
        "frustrated": 0,
        "overwhelmed": 0,
        "angry": 0,
        "guilty": 0,
        "lonely": 0,
        "scared": 0,
        "sad": 0
    }, {
        "sentence": "Here's a sentence in which I am sad",
        "grateful": 0,
        "happy": 0,
        "hopeful": 0,
        "determined": 0,
        "aware": 0,
        "stable": 0,
        "frustrated": 0,
        "overwhelmed": 0,
        "angry": 0,
        "guilty": 0,
        "lonely": 0,
        "scared": 0,
        "sad": 1
    }

Repeat some multiple of 55 times.

Old Dog New Tricks

I have set up a github repository! I have no idea what I’m doing, but fortunately they have a nice friendly GUI and tutorial bots. You can now, hopefully, view the code from my last post – the single output neural network.

Unfortunately I have not yet completed the multiple-output network as promised, because WordPress was complaining about not having this or that, and then I figured why not upgrade the server, and there goes the evening. Next time hopefully!

PyTorch

So I am getting down to something serious now, something that might actually be useful in finding me some future employment. I am going to train a neural network! I studied these back in school, in 2000-2001, back when we had to write them ourselves and walk uphill to school both ways. Now there are libraries that do it all! I put the first sample together in a night. Well it took me a while to prepare the data actually, but once I had the data prepared the rest was easy. I basically copied this guy.

My dataset is a bunch of posts I wrote to a facebook group I’m in. This facebook group came out of a website called mycounterpane.com, which is no longer active. It was basically a kind of shared journaling website where you could attach one of thirteen emotions to your post based on how you were feeling.

I split my facebook posts into 1112 sentences, and assigned each one an emotion. I used sentences instead of posts because I figured they would be more uniform in length, and it would give me more data points. They break down like so:

aware: 251
determined: 154
grateful: 130
stable: 100
hopeful: 97
frustrated: 92
overwhelmed: 90
happy: 78
scared: 57
guilty: 31
sad: 19
lonely: 7
angry: 6

For my first attempt I created thirteen separate networks, one for each emotion with a single output. This seemed to work oooookay. The sparse emotions were claiming 99% accuracy, which sounded great until I realized that if I say I’m lonely 1 out of 100 times and the network says I’m lonely 100 times, then the network is 99% accurate! But by that measure you could also get 99% accuracy from a rock, or a sandwich.

So I’m going to try combining it all into one network with thirteen outputs, because that’s a thing. Results in next post! Also I should post some code here. Or get a github account or something. That’s what all the hip kids are doing.

Freeeeeeeeee

I have set donkware.com free to be snapped up by Mr. Justin, to show my gratitude for actually visiting the site. He may be the only person to have done so. I look forward to seeing what he comes up with.

So now I have borland.us, which is my name and all, so I should be sticking with it for a while. It’s not really that fun. I wanted “dingdong.fun” but it is taken. I also considered “sanctimonious.life” which made me laugh, but the problem with gag website names is what happens when the novelty wears off? Then what are you left with? An empty husk.

Bricked!

Yesterday I decided to pick up where I left off with the Hackintosh. I got it running, everything looked great. I read on my favorite Hackintosh web site that I could install the latest system update just like a regular Mac, so I did that… and not only is the Hackintosh unbootable, but my motherboard is now bricked! Ouch! I think I have learned my lesson about messing with Apple.

Fortunately my son has stopped using his computer. He was only using it for Minecraft, and apparently Terraria is way more awesome than Minecraft so his computer has been gathering dust. So I popped my hard drives in there and at least I still have a Windows machine, although the display settings are somewhat jacked up.

All of this nonsense started just so I could have a test environment where Firebase wouldn’t work, so I could see how the error handling played out. So I think I am just going to forget about that! I am certainly not going to go out and buy Apple products as a reward for weaponizing their OS. I don’t have the money to be an Apple customer anyway.

Thanks for the offer

To Eric and the wonderful folks at DomainAgents.com – I want to thank you for conveying the very kind offer to buy donkware.com. I cannot imagine what anyone could possibly need it for other than a silly website like mine, and I cannot imagine anyone offering more than five bucks for it. I wouldn’t have paid any more than that. I think I got it for about two dollars. I can’t even remember.

Anyways, I can’t see the offer without joining DomainAgents.com or responding to Mr. Eric, and unfortunately I have no desire to do either of those things. If you’re willing to send me the offer up front I might consider it. Otherwise I’m afraid you’re out of luck, and I do apologize for my laziness. I just have a policy of not responding to unsolicited anything. If I wanted to sell the domain I’d list it somewhere. But who knows, if there is really someone out there willing to pay actual money for donkware.com, maybe I could be talked into it. But I am as yet unconvinced that person exists! It is preposterous to think so.

Hackintosh

So I discovered that Firebase actually does work in my development environment, which surprised me. Now how do I test my fallback? I have to find a device that won’t work with Firebase. How about an iPhone! Well I don’t have an iPhone. An iPhone simulator? The only mac I have is this ancient Mac Mini that I have turned into an Ubuntu server. Even if I reinstalled Snow Leopard on this Mac Mini, there’s no way I am running an iPhone simulator on that thing. iPhones barely existed back then. I’m not going to go out and buy a new Mac just for the iPhone simulator. So… Hackintosh! I have tried this several times in the past with no success. But I decide to give it one more go over my Christmas vacation.

I start with my Snow Leopard cd and some instructions from tonymacx86.com. I manage to make a VirtualBox virtual machine running Snow Leopard! This is exciting. I can’t get any farther than Snow Leopard in the VM, though, so I have to go around the house and start taking apart computers. My son’s HP seems to be the friendliest to this endeavor, so I swap hard drives with the Ubuntu machine that I use as a TV so I won’t ruin his Minecraft setup. I get Snow Leopard running on that, and then upgrade it to El Capitan, and then Catalina. Success! I still have to start the thing with a USB stick, but it seems to work. I haven’t tried developing on it yet, because getting to Catalina took up the entire winter break. It was not easy, and involved many failed attempts. It was pretty thrilling when I finally got it working though.

Hackintosh is a funny thing. Apple would have you think it was illegal to do such a thing, and perhaps it is. But if Apple really did not want this to happen, how hard would it really be to shut it down? The operating system knows what hardware it’s on. It could just refuse to run on anything but Apple hardware. Are we supposed to believe that instead of just shutting that door, Apple would rather let everyone loose and then run around trying to prosecute them? It doesn’t make any sense. I think Apple is perfectly content to let people like myself, who wouldn’t touch their products at all save for Hackintosh, have their harmless fun. I’m certainly not making any money off of it.

Firebase

I have gotten a conversation working between the web client and the android app relying entirely on firebase for notifications. Yay! Except both ends only work in the production environment. So development is slow, because my deployment process is slow.

It also raises a philosophical question of when to fall back to another technology. How would I be able to tell the difference between firebase not working, and just not getting any messages? There is no way, because I can’t confirm something that isn’t happening. So every once in a while, it may be necessary to poll the server anyway, just to see if firebase is working. Granted, firebase will probably be working 99.99% of the time, so it may not even be worth checking. But I might just throw it in there for good measure. Maybe only if the app/webpage is active for some long amount of time with no messages received.