0%

1. 起因

今晚看到了Simon Willison 的只使用自己的博客内容来训练nanoGPT的实验,觉得挺有意思,突发奇想,能不能在鲁迅的文集上训练一个nanoGPT,然后生成很具辨识度的鲁迅风格的文字呢?由于nanoGPT结构简单,鲁迅的文集在GitHub上可以下载到,因此通过简单的代码修改加实验,就得到一个在鲁迅作品上训练的GPT2模型(无别的语料库的预训练),简单测试下,以“故乡”开头,让模型生成鲁迅风格的文字:

1
2
3
4
故乡,债是佩服的。
我一向对于新青年的态度,先来说话,谢容易做的,然而伏园已经见过几样,感觉的是另外捧之数,以为先前的例子。今但近来做了做事,自己也还不做,不能先行通,所以生在冷静和“人生”,三妇一苦闷,觉得大约是如此隔膜
和曹操,于是非意模茶炛,可以说是太高了,所以现在便能教育,竟�如此。
但汝实在有给法历代的,不久就在绝末年间,我想显出向大家饮一趟,而汉子大毒是怀旧的,就要贫足有打劫,可以永掠的。这种事情,中国有一个大官左翼阿,(陀思妥习),有敢请佛喜,总要适说一点�

还算有鲁迅文字的风格,但逻辑一窍不通,整体还是难让人满意,不知道是GPT2能力的问题还是我实验设置的问题。 Anyway,这里共享一下我实验的流程,有兴趣的朋友可以参考,进行改进。本文涉及的代码修改代码已经提交到这个仓库了,可以参考,文末会附上更多例子。

阅读全文 »

1. 概述

在Numpy 1.24版本中,删除了像np.floatnp.int 这样的 Python 内置类型的 alias,因此以后在代码中使用这些类型会报错AttributeError: module 'numpy' has no attribute 'float', 涉及的类型包括:

  • numpy.bool
  • numpy.int
  • numpy.float
  • numpy.complex
  • numpy.object
  • numpy.str
  • numpy.long
  • numpy.unicode

那该怎么解决这个错误呢?

TL;DR

  • 对于在标量上的操作,直接使用Python内置类型替换
    1
    2
    3
    4
    5
    foo = np.random.rand(10)
    # 原先用法,注意foo[0]是一个标量
    bar = np.float(foo[0])
    # 新用法
    bar = float(foo[0])
  • 对于在np.ndarray 上的操作,使用np.float64np.float32 来替代,具体选择哪个需要自己根据情况来确定,不同类型精度会有不同,下面举两个例子:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 原先用法
    foo = np.random.rand(10, dtype=np.float)
    # 新用法
    foo = np.random.rand(10, dtype=np.float32)

    # 原先用法
    foo = np.random.rand(10).astype(np.float)
    # 新用法
    foo = np.random.rand(10).astype(np.float32)

这里列出来了删除类型在标量和np.ndarray 上的替代,方便查找

原先类型 标量替换类型 np.ndarray替换类型
np.int int np.int32/np.int64
np.float float np.float32/np.float64
np.bool bool np.bool_
np.complex complex np.complex128
np.object object -
np.str str np.str_
np.long int np.int32/np.int64
np.unicode str np.str_

详细说明参考NumPy 1.20.0 Release Notes

下面详细说说事情的来龙去脉。

阅读全文 »

有时候想要在手机上访问Arxiv上的论文,打开arxiv.com,发现体验比较差,没有响应式设计,需要不断移动页面才能读完一行文字,影响阅读。偶然发现了arxiv-vanity这个网站,发现能很好的满足手机上看arxiv论文的需求,收藏了。

阅读全文 »

在某个目录下有很多代码创建的空文件,分布在不同层级的子目录中,我们有没有办法可以快速地全部把它们删掉呢?

find是Linux系统中的一个强大的命令,通过它我们可以找到空文件,然后将它们进行删除。

TL;DR
最终命令如下:

1
find . -type f -size 0 -print -delete

几个参数详细的说明见下。

阅读全文 »

在读《流畅的Python》时,偶然看到下面的语句:

1
2
with urlopen(URL) as remote, open(JSON, 'wb') as local:
local.write(remote.read())

突然才发现,原来多个with语句可以写到一起!

阅读全文 »

使用ffmpeg可以方便地从视频中抽取图像帧:

1
ffmpeg -i /path/to/video.mp4 image-folder/%06d.jpg

但实际测试发现,抽取的图像帧比较模糊,有明显的块效应。

搜索时有人说可以加-q:v 1 -qmin 1 -qmax 1来提高图像质量

1
ffmpeg -i /path/to/video.mp4 -q:v 1 -qmin 1 -qmax 1 image-folder/%06d.jpg

测试发现确实有一些提升,但还是能看到明显的模糊。

最后发现,把抽取的图像格式从.jpg修改为.png,结果就是高清且无块效应的了:

1
ffmpeg -i /path/to/video.mp4 image-folder/%06d.png

另外PNG格式的图像存储大小要大一些,但不会太大,还是能接受的。

概述

前段时间突然发现,我之前对git stash的使用都是错误的。

具体说来,我是这么使用的:在远端有新的提交,需要git pull来拉取合并时,发现本地有一些未提交的修改,功能也没实现,不适合做一次commit。这时候我执行git stash隐藏本地的修改,然后执行git pull来拉取远端的更新,在最新代码基础上重新实现stash的那些代码中的功能。

这里的问题是,重新实现stash代码中的那一步,其实完全可以用git stash pop来替代,执行这个命令会在最新代码基础上作用stash的代码,不用再重新实现一遍了(不过这时可能会有代码冲突需要解决)。所以我之前是把git stashgit checkout -- .来用了,也就是抛弃了本地的代码更新,显然是有问题的。

正确流程基本上是这样:

1
2
3
git stash # 或者 git stash push,效果一样
git pull # 可能有冲突需要手动合并
git stash pop # 可能有冲突需要手动合并

下面记录一下 git stash 提供的功能和一些参数。

阅读全文 »

多年以后,想起2022,我会回忆起哪个画面?为了解答这个问题,我回想过去的这些年份,2021,2020,……2005,看能想到什么。除了有些年份里,我结婚,毕业,所以有记忆深刻的事件,大部分年份我甚至想不起任何事情。对于一个模糊的数字,在多年以后,我们确实难以将它和自己一天天度过的日常事情关联起来。虽然2022年发生了很多事情,但大部分还是会被遗忘,但我还是尽量想用详细的文字记录下来,这样当以后想会看那年我身上发生了什么的时候,我知道只要在浏览器里面输入vra.github.io/2022/12/31/summary-2022,这些时刻都会清晰地浮现在我眼前。

阅读全文 »

概述

有时候我们在git commit后才发现,之前的一些提交有些问题,比如有些代码忘提交了或者有一些typo需要修改。如果要修改的地方是需要添加到最后一次提交上的,那么可以参考我的这篇博文修改,如果是在非最后一次提交上的,那么就需要用git rebase来操作。这里简单记录一下操作的过程。

TL;DR
操作命令简要来说是这样:

1
2
3
4
5
6
7
8
9
10
11
12
# 使用git log 查看历史提交,得到需要修改的那次提交的commit id
git log
# 执行rebase命令,注意<commit-id>后面有一个^,表示修改在此次提交前
git rebase -i '<commmit-hash>^' # 如果是修改第一次提交,使用 git rebase -i --root
# 修改代码
vim changed-file
# git add 添加更新后的文件
git add changed-file
# git commit 提交,注意需要使用后面三个选项,并且不需要加commit信息,因为会采用之前的commit信息
git commit --all --amend --no-edit
# 使用--continue来完成 git rebase
git rebase --continue

后面会使用一个具体的(假)例子来演示这个过程。

阅读全文 »

1. 概述

在我们使用Python中的dict时,常常需要判断某个关键字是否已经在dict中,如果不存在则创建,非空则进行另外的操作。例如统计一篇文章中所有单词出现次数的代码,大致写法如下:

1
2
3
4
5
6
7
words_num = {}

for word in words:
if word not in words_num.keys():
words_num[word] = 1
else:
words_num[word] += 1

这样写总是需要判断key是否在dict中,不是很优雅。

Python标准库collections中defaultdict类可以很好的解决这个问题。这个类使用与dict几乎一样,除了可以在初始化时设置key的默认类型和数值。类的声明格式为defaultdict(default_factory=None, /[, ...])default_factory是一个callable的变量。

别的使用与dict无异,正常使用即可。

阅读全文 »