失败,失败

嘛,我果然还是荒废了一个暑假,不能妄想一个有意义的大学生活啊
不过,总还是要有点梦想的

X

最喜欢的奥特曼的十周年
也是我的生日
为了与你相连,而迸发出的
无限的可能性!

x!

再演

总之呢,反正经历过一堆不大不小的垃圾或无聊事件后,博客终于能重启了。。。
以后就把这个当日记来使用吧

计划:

  • vocaloid
  • ai
  • godot
  • 外语

不过,能不能换个好点的电脑和网络。。。

再会

与同学们的最后一次相见
再会了

初恋豚鼠

在朋友的怂恿下看了初恋豚鼠
在感动过后彻底认识到了自己人生的失败
今天就继续努力吧

7/14

虽然是生日

但是我们家是过农历的所以还没到(┬┬﹏┬┬)
发现好多动漫角色都是7月14生日啊

生日快乐ヾ(≧▽≦*)o

总想发生什么的盛夏

日复一日的蝉鸣

毕业了,和很多人见完最后一面,期待着夏天的改变,却还是无所事事的坐着
这就是我现在的样貌
到头来,还是什么都没发生
不过暂且,沉浸在这首歌里吧
毕竟前路还长

亚刻奥特曼!

亚刻奥特曼第一集!!!

终于看完了第一集,来说说我的感想吧
感觉这部氛围是轻松愉悦,非常适合小朋友观看ヾ(≧▽≦*)o
第一集男二的印象最深刻,本来以为是经典的傲娇,结果是一位非常可靠,有时蛮搞笑的正常人(怎么有单位不提供咖啡啊done,结果自己就带了一个咖啡机😂

奥特曼的打戏蛮有新意的,我最喜欢的是室内的视角(虽然前几部也有过
没有从男主遇到奥特曼开始拍,搞得我还以为放在特别篇里了

op和ed都非常好听!

总而言之,如果能一直保持这个势头就好了,跑起来,优马!

js小型llm计划

准备照着重打一遍代码,不过是用tensorflow.js

持续更新。

粗略理解

首先先粗略的理解一下文本生成的原理吧,虽然非常幼稚…

注意力:对应两个token之间的关系
文本生成:根据上个token预测下一个token
k,q,v:k与q相对应,v作为输入,输出v2,v2又作为下一个输入…
所以理论上,一层注意力也是能用来生成的,只要参数够大…
希望没有错的太离谱。

一个js transformer实现

在github上发现了一个有趣的项目
transformer-tfjs
直接在浏览器里训练模型,太牛逼了,准备照着做…

归一化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
tf.util.shuffle(data)

const epsilon = tf.scalar(1e-4) // 创建一个很小的标量epsilon
const inputs = data.map((d) => d.horsepower)
const labels = data.map((d) => d.mpg)

const inputTensor = tf.tensor2d(inputs, [inputs.length, 1])
const labelTensor = tf.tensor2d(labels, [labels.length, 1])

const sqrt_pow_mean = inputTensor
.square()
.mean(1)
.sqrt()
.expandDims(1)
.add(epsilon)
const label_pow_mean = inputTensor
.square()
.mean(1)
.sqrt()
.expandDims(1)
.add(epsilon)

最简单的,RMS_Norm归一化。

但我不是很懂mean()这个函数,沿着第1维和第2维好像都能出现结果。。。
(划掉)

而且出现了未完全归一化的结果…

呃…大体上是完成了吧。(还是用简单点的ba…)

data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 //import * as assert from 'assert'
import { getEncoding, encodingForModel } from 'js-tiktoken'
import * as fs from 'fs'
import * as nj from 'numjs'
//import * as os from 'os'
import * as path from 'path'
//import * as tf from '@tensorflow/tfjs'
//import { fileURLToPath } from 'url'

//const __filename = fileURLToPath(import.meta.url)
//const __dirname = path.dirname(__filename)
const enc = getEncoding('gpt2')
//assert.strictEqual(enc.decode(enc.encode('hello world')), 'hello world')

fs.readFile('./night.txt', 'utf8', (err: Error | null, content: string) => {
if (err) {
console.error('Error reading file:', err)
return
}
console.log(content.length)
const n = content.length
const train_data = content.slice(0, Math.floor(n * 0.8)) //切片,前80%
const val_data = content.slice(Math.floor(n * 0.8)) //后20%
let train_ids = enc.encode(train_data) //编码
let val_ids = enc.encode(val_data)
console.log('train tokens:', train_ids.length)
console.log('val tokens:', val_ids.length)

var train_ids_list = nj.array(train_ids, 'uint16')
var val_ids_list = nj.array(val_ids, 'uint16')

const trainArray = train_ids_list.tolist() // 转换为普通数组
const trainBuffer = Buffer.from(trainArray) // 转换为 Buffer 对象
const valArray = train_ids_list.tolist()
const valBuffer = Buffer.from(valArray)

fs.writeFileSync(path.join('./data', 'train.bin'), trainBuffer)

fs.writeFileSync(path.join('./data', 'val.bin'), valBuffer)
})

用numjs和js-tiktoken实现编码,模仿prepare.py保存为二进制。

一个简易的llm试用

之前在bilibili看到一个简易的llm:

虽然没完全看懂,不过还是先试着运行一下。

不过问题来了,我没有显卡,用cpu训练又太慢。
于是就打算在coloab平台上训练。

将文件夹上传到谷歌硬盘,再在coloab中装载。
不知为何相对路径没有用,就用绝对路径了。(估计是我填错了)

先准备数据集,用了自带的.

运行train.py

这里已经训练过两轮了
大小居然要1.7G…

运行sample.py

效果还不错。

之后:学习一下架构,继续削减参数,魔改网络。