Around the end of 2020 I learned to train Generative Adversarial Networks, or GANs, on image datasets to create art generators. I used a bunch of book and font data and made a series i call Language Arts.

To display those in the fastpages framework I need to make markdown files for each of the projects, with its own date and description, and a list of image tags to display. Also a header image and video tags for any interpolation videos. And of course I'll need to copy some images over from the folder itself.

Creating a template string has worked so far, for generating markdown folders. I can't do it entirely programmatically because I want to insert relevant comments for each one as I recall them. And I want to hand select the images, so I don't just copy over a bunch of crappy early-epoch training images. Probably the best way to do this is to hcopy images for each GAN project to subfolder of images with its name, then use a function of the folder name and manually-added metadata to build a markdown file over the contents of the folder. There are only so many projects I've built, and the marginal cost for adding a new one will be small if I can re-use the function.

from IPython.display import Markdown
from pathlib import Path

in_dir = '../images/book_cover_gan'

images = [file for file in Path(in_dir).iterdir()]

The following will display all the images when printed into the notebook, but doesn't get picked up by the fastpages converter, so it looks bad on the website. Maybe some day I will fix the converter myself, but until then I'm okay with generating markdown files that will work

images[:5]
[PosixPath('../images/book_cover_gan/95-ema.jpg'),
 PosixPath('../images/book_cover_gan/74-ema.jpg'),
 PosixPath('../images/book_cover_gan/117-ema.jpg'),
 PosixPath('../images/book_cover_gan/99-ema.jpg'),
 PosixPath('../images/book_cover_gan/48-ema.jpg')]
images[0].name
'95-ema.jpg'
title = in_dir.split('/')[-1].replace('_', ' ').capitalize().replace('gan','GAN')

           
images_md = ' '.join([f'![generated image]({str(image.parent)[2:]}/{image.name})' for image in images])

description = "An early experiment with the [lightweight-gan](https://github.com/lucidrains/lightweight-gan) architecture trained on a 55K-image book dataset."

images_html = '</n>'.join([f'<img src="{str(image.parent)[2:]}/{image.name}" alt="generated image">' for image in images])


template_md = f'''---
title: {title}
layout: post
toc: false
badges: false
image: {images[0]}
categories: [synthetic-media]
---

{description}

<div style=" display: flex; flex-flow: wrap">
{images_html}
</div>
            '''
date = '2020-11-28'
with open(f'../_posts/language-arts/{date}-{title.replace(" ", "-")}.md', 'w') as f:
    print(template_md, file=f)

Wrap it all in a function with minimum necessary inputs, and we can print a few in quick succession! ALthought it will be good to separate the pure markdown function from teh effect of writing to disk.

def get_md(title, date, description, images, video):
    
    images_html = ' '.join([f'<img src="{str(image.parent)[2:]}/{image.name}" alt="generated image">' for image in images])

    video_html = f'{{% include video_small.html url="{video}" %}}' if video != "" else ""
        
    
    template_md = f'''---
title: {title}
layout: post
toc: false
badges: false
image: {str(images[0])[2:]}
categories: [synthetic-media]
---

{description}

{video_html}

## Samples
<div style="display: flex; flex-flow: wrap; gap: 2rem">
{images_html}
</div>
            '''
    
    return(template_md)
get_md('../images/book_cover_gan',
       '2020-11-28',
      "An early experiment with the [lightweight-gan](https://github.com/lucidrains/lightweight-gan) architecture trained on a 55K-image book dataset.",
      images,
      "/images/book-gan.mp4")[:500]
'---\ntitle: ../images/book_cover_gan\nlayout: post\ntoc: false\nbadges: false\nimage: /images/book_cover_gan/95-ema.jpg\ncategories: [synthetic-media]\n---\n\nAn early experiment with the [lightweight-gan](https://github.com/lucidrains/lightweight-gan) architecture trained on a 55K-image book dataset.\n\n{% include video_small.html url="/images/book-gan.mp4" %}\n\n<div style="display: flex; flex-flow: wrap; gap: 2rem">\n<img src="/images/book_cover_gan/95-ema.jpg" alt="generated image"> <img src="/images/book'
def write_md(in_dir, date, description, video=""):
    images = [file for file in Path(in_dir).iterdir()]
    title = in_dir.split('/')[-1].replace('_', ' ').capitalize().replace('gan','GAN')
    
    post_md = get_md(title, date, description, images, video)
#     print(post_md)
    with open(f'../_posts/language-arts/{date}-{title.replace(" ", "-")}.md', 'w') as f:
        print(post_md, file=f)
write_md('../images/book_cover_gan',
       '2020-11-28',
      "An early experiment with the [lightweight-gan](https://github.com/lucidrains/lightweight-gan) architecture trained on a 55K-image book dataset.",
      "/images/book-gan.mp4")
write_md('../images/symbol_gan_unscii',
       '2021-02-03',
      """My first experiment with trying to generate new language glyphs. I used the [unscii](http://viznut.fi/unscii/) font because it has glyphs for most of the Unicode characters.
      
Unfortunately, since it's a bitmap font suitable for ASCII terminals, the end result is very pixelated is hard to imagine as letters. It also tended toward
mode collapse, as the generator figured out it could fool the discriminator with a very faint grid of dots in a gridlike pattern.""",
      "/images/unscii-gan.mp4")
write_md('../images/symbol_gan_noto',
       '2021-02-05',
      """A model finetuned from my unscii GAN. I tried with Noto font from Google, but the underlying model was too deranged. 
Also, Noto has a lot more Eastern ideograms than Western characters and I don't know how to tell if those are even translating properly.""",
      "/images/noto-gan.mp4")
write_md('../images/symbol_gan_code2000',
       '2021-02-09',
      """I recreated my Unicode glyphs dataset with the abandonware font [Code2000](https://web.archive.org/web/20110108105420/http://code2000.net/), which has great coverage for Western characters as well as a funky, humanist design.

This time I started to see real characters emerge among the imagined ones. It was at this point that I began to wonder if this was a good thing to do to my brain.

But it was too late...""",
      "")
write_md('../images/symbol_gan_4word',
       '2021-03-08',
      """After many false starts and dead ends, I finally found a concept that would truly drive me insane. I finetuned my Code2000 symbol GAN model on a set of generated images.

These images consisted of the 1,000 most commonly used four-letter words in English. With the newly trained model, I generated some new ones.

If you would like to purchase one of these word worms, you can find them in NFT form at the [Language Arts Marketplace](https://opensea.io/collection/language-arts). I can't imagine why you would, but there it is.

**Warning: I don't know what happens if you stare at these for too long! Use at your own risk.**""",
      "")