序言

阳历生日。今年因为年过得早的缘故,很多事情都相对提前了(比如情人节)。往年过生日的时候基本都还在家,所以一家子出去吃个饭也就罢了。今年承蒙凯爹厚爱,正好也有小半年没聚,他前天也刚正式拿到offer,于是狠狠地宰了他一顿哈哈(srds下个月他过生日还得还回去)。

难得跟人一逛老半天,从乳山四村到正大广场,吃完饭再回来,一路上交换见解与心得,从九点多一直到晚上六点多才走,凯爹的阅历让我受益颇多。我其实很羡慕凯爹这样的人,每一个能从二战走出来的都是勇士中的勇士,就是那种生活很有激情,并且目标明确,矢志不渝,这两个词我觉得是越来越难能可贵。

回来这些天除了泡实验室,每天还是至少会去遛五圈,前天浅浅地跑了5000米,其实也不是很吃力。说起来差不多停跑了有十天,相当致命,不过我发现因为这么多年来屡屡从低谷恢复训练,身体已经习惯了这种节奏,至少今年开始恢复的时候跑起来还是挺轻快的,虽然耐力明显很差,但也没有那么笨重。

初心难追,但是谁又愿意就如此屈服于生活呢?


文章目录

  • 序言
    • 20230216
    • 20230217~20230220
    • 20230221
    • 20230222~20230224
    • 20230225~20230226
    • 20230227
    • 20230228
    • 20230301
    • 20230302
    • 20230303~20230304
    • 20230305~20230306
    • 20230307
    • 20230308
    • 20230309
    • 20230310~20230311
    • 20230312
    • 20230313~20230314
    • 20230315
    • 20230316
    • 20230317
    • 20230318
    • 20230319
    • 20230320~20230321
    • 20230322
    • 20230323
    • 20230324~20230325
    • 20230326~20230327
    • 20230328
    • 20230329


20230216

因果推断之遐想,今年NSFC的通告里着重强调了这个方向,严格上来说这是一个统计学范畴,但是他越来越受到ML以及DM领域的关注,原因在于数据中难免存在难以捕获的偏见。

最近一篇非常好的CasualLM: Causual Model Explanation Through Counterfactual Language Models,提出了一种基于反事实构造的反事实语言模型,可以修整数据中固有的偏见。

但是现阶段因果推断和NLP的结合的工作大多是基于现有的因果图做检验会调整,其实有一个很关键的核心问题是如何捕获混杂因子(在没有因果图的情况下),一些工作会介绍如何从复合变量中分离得到混杂变量以及调整变量,如http://www.meng-jiang/pubs/tee-aaai17/tee-aaai17-paper.pdf与https://arxiv/abs/arXiv:2006.07040,但是这些工作也是建立在因果图已知,候选的变量已经给定的前提下得到的,一般的情况是只给你上下文语料,如何判断一个基于该语料的任务存在混杂因子。

其实在预训练数据是足够充分的条件下,我们应当认可模型预测的结果是无偏的。问题在于预训练数据总是不够充分的,所以我们需要构造反事实来使得它更为均衡。还有就是Pearl的因果推断理论框架是完全建立在因果图之上的,问题在于没有任何理论保证因果图的有效性,这在因果推断与NLP结合时确实是令人费解的事情,这就有点射箭画靶的意思,为了论证存在混杂,特意构建了一个能够导出混杂的因果图。


20230217~20230220

  • 昨天颜烨即兴约我和王凯小聚,在很久以前羊肉串,就很巧,颜烨最近也在看因果推断,不过他是用在推荐上,于是在等王凯时交换了不少意见。吃完去政民路上的一家小酒吧搓了两把以色列麻将,最后险些完成华丽的逆转(7张牌反杀颜烨2张牌,就是有1张怎么想都出不去),狗颜烨手气贼好把把起手百搭,我两把一个百搭都没摸不到(笑)。
  • 下个月19号锡马,说实话把握不是很大,但是目标肯定还是要进95分钟,其实说起来我已经有14个月没有跑过20km以上的距离了。恢复期目前练了六天,但是周末歇了两天,今天是2km+1km+1km的间歇,配速4分整,间歇5分钟,心率上到190,痛苦得要死,但是要快速恢复就必须依赖高强度的变速和间歇,耐力还得靠跑量堆上去。目前水平持平去年九月底,想要跑半马至少也要达到去年十一月底的水平。就过往的经验来看只要能把10km跑到43分钟左右,基本上在最佳状态下就有能力冲击半马。
  • 说实话也许是我最后一次跑步了,我也确实地感觉到各种压力而无法坚持下去,也许赶不上最后的一次校运会,仍是遗憾无比,除非我愿意能够在高压下坚持训练到4月底,以后大概率是以养生跑为主。尽管大概率还是不能在最巅峰的状态下完成比赛,但跑一次半马是最后的倔强,虽然以后有机会我也许会去跑全马,跑铁三,但是我不愿意自己这么三年多以来的阶段性跑步生涯就如此无疾而终,它应该配得上一个荣誉作为句号。

谈谈我对chatGPT的看法,昨天也跟yy和wk探讨了这个问题。其实去年十一二月的时候,就已经可以在B站上刷到不少chatGPT大战弱智吧的视频,当时我也不是很关注,总觉得是跟以前那种废话文学生成器是一样的toy model。直到今年一月搞科技部课题申报的时候事实上接触chatGPT时才真正震惊于其恐怖的性能。

现在网络上的评价趋于两级分化,有的人奉chatGPT为神,有的人对之嗤之以鼻。就我浅薄的认知而言,假若chatGPT的背后确实没有任何人类技术员的干预(或者说白了就是人工作弊),我认为chatGPT将是一个划时代的产物,以2017年BERT横空出世作对比,chatGPT的创新性至少比BERT要高出一个档次。

因为就我所理解,chatGPT在许多NLP任务上(问答、对话、代码改错、目标文本生成、自然语言推断、阅读理解、文本综述)都远远超过了目前相应领域SOTA模型的性能。具体的细节我也不想写太多,因为我是做这方面工作的,这种效果让我非常震惊。

以前说强AI会取代很多工作,现在看来强AI的出现,第一批失业的或许就是我们这批踩着末流踏进AI研究的,就有点像49年假如guo军的感觉(苦笑)。试想,你针对一个特定任务的做的模型,做得再好也比不过chatGPT,chatGPT在广度和深度上已经超过了大部分研究者的上限,这是一件非常可怕的事情。很多大企业追逐潮流,就会对业务和人员进行结构性调整,谁又能确保之后不会出现第二个chatGPT呢,特别特别有危机感。说实话,保守估计我觉得国内近一年不可能有产品可以超越chatGPT。

所以现在很多的想法就是去做chatGPT做不了的事情,即要跳出NLP,比如图像、推荐等,如果还是要和NLP挂钩,那么要么在方法论上创新,要么只能向多模态发展。这可能也是为什么因果推断成为今年NSFC的一个重要突出领域。

提一个,写开题看到VisualMRC,一开始以为就是VQA,结果VisualMRC竟然是所有的上下文就是一张图像,不过图像中包含区块性的文字以及贴图,VQA是直接给一张图(可能会有简短的描述),然后直接答题。VisualMRC提出的动机是因为大部分现实世界文本都不是以纯文本出现的(比如PDF和HTML),所以只能处理包含文本的图片,不过总觉得只是用OCR识别一下即可划归到一般的VQA,感觉又是为了发paper画靶射箭。


20230221

  • 昨晚wyl破天荒开组会从六点开到十点半,我跟黄名媛实在是顶不住了,黄名媛本来晚上约人吃饭,我说估计一个多小时就结束了,可以等结束再去吃。结果她连晚饭都没吃到,离大谱。
  • 降温,长袖长裤拉耐力,10圈17’20",配速4’20",其实挺满意的,一周就可以上到4km,比九月份恢复得快(那时候挣扎了半个多月都没能跑10圈)。结识了一下经常来跑的光头大叔,我一直以为他是老师,原来是家属,上周也偷偷跟他跑了几次,发现三年来一点长进没有,配速还是4’40"~4’50"的水平,有点失望,要不然就可以找个pace差不多又看起来很专业的一起练。他都是每天下午三点半之后到操场,我一般是四点,但他拉伸时间很长,所以起跑时间很接近。他不跑比赛,单纯是锻炼身体,但是今年还是本着10km跑进45min在训练,有个目标跑起来确实更有动力一些,这也是我一直拒绝养生跑的原因。如果真的只是以锻炼身体去养生跑,根本是无法坚持长久的。

SQuAD1.1和2.0的下载链接:

https://data.deepai/squad1.1.zip
https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v2.0.json

然后NewsQA直接可以在https://download.microsoft/download/1/D/8/1D830CEE-F8D1-4807-9224-DE35A8F08DC4/newsqa-data-v1.zip下载,问题是NewsQA里没有上下文(story),只有storyid,因为story的版权不在微软,在CNN,那个要翻墙(https://cs.nyu.edu/~kcho/DMQA/),给翻不了墙的留个门cnn_stories&&dailymail_stories.7z

然后就是昨晚复旦大学对话机器人MOSS,我是真的服了,第一次看到这么能蹭热度的,哗众取宠,还同时蹭两个。国内最先能接近chatGPT的模型肯定不可能是高校首先发布,如果能做出来一定是BAT,学校再有钱也不可能这么去烧。


20230222~20230224

  • 周三订酒店,锡马也就上周日才官宣定档,两三天时间周边的酒店预定就已全部售罄,最后好不容易抢到一个距离起点2km以内的,还只剩一个家庭房。毕竟算是疫情后的第一场高规格赛事,可见一斑。
  • 这周基本上每天都有5km的量,但是想要从突破到10km依然十分困难,最后三周,尽力而为罢。

SQuAD process:

# -*- coding: utf-8 -*-
# @author: caoyang
# @email: caoyang@163.sufe.edu

import json
import pandas

from setting import (SQuAD_JSON_PATH_SUMMARY,
					 SQuAD_ARTICLE_PATH,
					 SQuAD_QUESTION_PATH,
					 )

def SQuAD_to_csv(article_export_path=SQuAD_ARTICLE_PATH, question_export_path=SQuAD_QUESTION_PATH):
	
	article_dict = {'article_id'	: list(),
					'title'			: list(),
					'article'		: list(),
					'type'			: list(),
					'version'		: list(),
					}
	question_dict = {'question_id'		: list(),
					 'article_id'		: list(),
					 'question'			: list(),
					 'answers'			: list(),
					 'answer_starts'	: list(),
					 'answer_ends'		: list(),
					 'type'				: list(),
					 'version'			: list(),
					 }
	
	for key, data_path in SQuAD_JSON_PATH_SUMMARY.items():
		type_, version = key.split('-')
		with open(data_path, 'r', encoding='utf8') as f:
			data = json.load(f)
		count = -1
		for sample in data['data']:
			title = sample['title']
			paragraphs = sample['paragraphs']
			for paragraph in paragraphs:
				count += 1
				article_id = f'{type_}-{version}-{str(count).zfill(5)}'
				article = paragraph['context']
				for question_and_answer in paragraph['qas']:
					question_id = question_and_answer['id']
					question = question_and_answer['question']
					candidate_answers = question_and_answer['answers']
					answer_starts = list()
					answer_ends = list()
					answers = list()
					for candidate_answer in candidate_answers:
						answer_start = int(candidate_answer['answer_start'])
						answer = candidate_answer['text']
						answer_end = answer_start + len(answer)
						# assert answer == article[answer_start: answer_end]
						answer_starts.append(answer_start)
						answer_ends.append(answer_end)
						answers.append(answer)
					# Write question Dictionary
					question_dict['question_id'].append(question_id)
					question_dict['article_id'].append(article_id)
					question_dict['question'].append(question)
					question_dict['answers'].append(answers)
					question_dict['answer_starts'].append(answer_starts)
					question_dict['answer_ends'].append(answer_ends)
					question_dict['type'].append(type_)
					question_dict['version'].append(version)
				# Write article dictionary
				article_dict['article_id'].append(article_id)
				article_dict['title'].append(title)
				article_dict['article'].append(article)
				article_dict['type'].append(type_)
				article_dict['version'].append(version)
	# Convert to dataframe
	article_dataframe = pandas.DataFrame(article_dict, columns=list(article_dict.keys()))
	question_dataframe = pandas.DataFrame(question_dict, columns=list(question_dict.keys()))
	# Export dataframe
	article_dataframe = article_dataframe[['article_id', 'title', 'article', 'type', 'version']]
	question_dataframe = question_dataframe[['question_id', 'article_id', 'question', 'answers', 'answer_starts', 'answer_ends', 'type', 'version']]
	if article_export_path is not None:
		article_dataframe.to_csv(article_export_path, sep='\t', header=True, index=False)
	if question_export_path is not None:
		question_dataframe.to_csv(question_export_path, sep='\t', header=True, index=False)
	return article_dataframe, question_dataframe

20230225~20230226

  • 下午绝好天气,3000米跑到11’55",感觉已经恢复到八九成(之前3000米最快能跑到11’40"以内,不过恢复两周能跑进12分钟也并无不满)。我感觉状态绝佳的情况下已经有能力冲击10km(只是今天碰到卢星雨和黄懿嘉在跑间歇,跑得太快,节奏给搞得有点崩),感觉还是很可期的,下周如能继续保持强度与状态,有信心下个周末就能把10km跑进43分钟,然后最后两周拉体能,直到19号能达到半马水平。
  • 浪潮发布了源1.0大型中文模型,目前准备开源其训练语料,已经毕业的师兄王明回来准备以组的名义去申请数据,顺便找我们几个小咸鱼搞些合作,确是极好的。王明在阿里也在搞它们的chatGPT,我跟他说现在chatGPT做的这么好,我们这些底层科研狗真的很难实现模型性能上的创新,只能在方法论上做一些横向突破。王明说他也不指望国内短期能做到chatGPT的水平,至少阿里目前确实没有这个水平。这就是现实,别人确实是做到了我们做不到的事情,有时候真的不服不行,而且这行是很可怕的,一旦chatGPT真正投入商用,国内无法跟进脚步,用户群体被垄断后,这个差距就会被进一步拉大,chatGPT会以更加恐怖的速度积累语料训练并不断完善模型,到时候真的很难想象国内到底还有没有机会赶上chatGPT的步伐。我有一种隐隐地感觉,最坏的情况下,chatGPT将会在不久的将来彻底垄断NLP研究领域,因为再也没有机构能在数据积累和模型规模上超越chatGPT,除非天降猛男开辟出一个全新的高效模型训练框架,打破目前这种研究开发的范式,否则确实是一件让人,搞不好大家长又会彻底墙掉chatGPT,来保护国内的资源发展。

吊命的异步下载(拒绝吸血雷):

#coding:utf-8
import asyncio
import sys
import time
import os
import cgi
import re

from urllib import parse
from urllib.parse import urlparse, unquote_plus

file_name_pattern = re.compile(r"utf|UTF-8'\s+'")
import aiohttp
def get_file_name(content_disposition):
    _, params = cgi.parse_header(content_disposition)
    if "filename" in params:
        return params["filename"]
    elif "FILENAME" in params:
        return params["FILENAME"]
    elif "filename*" in params:
        return re.split("utf-8'\s+'", params['filename*'], 1, flags=re.IGNORECASE)[1]
    elif "FILENAME*" in params:
        return re.split("utf-8'\s+'", params['FILENAME*'], 1, flags=re.IGNORECASE)[1]
    else:
        return None

async def fetch(session, url, startpos, endpos, filename):
    headers = {
        "Range":"bytes=%s-%s"%(startpos,endpos),
        "accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "accept-encoding":"gzip, deflate, br",
        "accept-language":"zh-CN,zh;q=0.9",
        "upgrade-insecure-requests":"1",
        "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36",
    }
    print("fetch...", startpos, endpos)
    async with session.get(url, headers=headers) as response:
        with open(filename, 'rb+') as fd:
            fd.seek(startpos)
            while True:
                chunk = await response.content.read(1024)
                if not chunk:
                    break
                fd.write(chunk)
        

async def main(url, thread_num):
    
    #获取文件的大小和文件名
    urlobj = urlparse(url)
    filename = ""
    start = 0
    end = -1
    step = 0
    tasks = []
    headers = {
        "accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "accept-encoding":"gzip, deflate, br",
        "accept-language":"zh-CN,zh;q=0.9",
        "upgrade-insecure-requests":"1",
        "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36",
    }
    #https://wwwblogs/momoxingchen/p/6493317.html
    async with aiohttp.ClientSession() as session:
        async with session.head(url, headers=headers) as response:
            headers_content = response.headers
            print("headers_content", headers_content)
            if "Content-Length" not in headers_content:
                raise Exception("can't get file size")
            filename = urlobj.path.rsplit('/',1)[1]
            if 'Content-Disposition' in headers_content:
                tmp_file_name = get_file_name(headers_content["Content-Disposition"])
                if tmp_file_name is not None and tmp_file_name:
                    filename = tmp_file_name
            filesize = int(headers_content["Content-Length"])
            step = filesize // thread_num
            print("%s filesize:%s"%(filename,filesize))
    with open(filename,'w') as tempf:
        tempf.seek(0)
        tempf.write("hello")

    async with aiohttp.ClientSession() as session:
        while end < filesize -1:
            start = end +1
            end = start + step -1
            print("start:end:", start,end)
            if end > filesize:
                end = filesize
            task = asyncio.ensure_future(fetch(session,url,start, end, filename))
            tasks.append(task)
        await asyncio.gather(*tasks) 
    

if __name__ == "__main__":
    url = "https://rajpurkar.github.io/SQuAD-explorer/dataset/train-v2.0.json"
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(url, 2))

20230227

  • 晚上跟王英林吃了个饭,最近很多事情要跟他当面汇报一下才清楚。明天韩明月预答辩,有一个师姐要离我而去了,她毕业之后我就真的成了组里的老大头,可是依然有所迷惑。实话说明月姐运气确实很好,讲道理那篇ACL我仔细看过,质量不算很高,但是就是被接收了,然后就一篇CCF-A直接定乾坤,其他三篇都是特别水的凑数。但是即便如此她硕士阶段和博士阶段各拿了一次国奖,实力也是强的离谱,反正我这届硕博没有一个人在硕士阶段拿过国奖(因为都被金工的scx和dyt给拿捏了,怎么说硕士阶段我也是硕博这边的综评第一,真是难受)。而且我也看了她的论文初稿,131页,工作量比胡振达要小不少,但是最后两页纸的致谢确是真情流露,人的实力和运气都很重要。
  • 晚上3km慢跑,穿羽绒服和老重老重的板鞋跟着lxy和hyj,她俩是真的能跑,估计有15圈,还是外道。权且休整状态,一想到明月姐和胡振达都那么强,我也确不能辱没师门呐,留给我的时间真的不多了。
 # -*- coding: UTF-8 -*-
# @author: caoyang
# @email: caoyang@163.sufe.edu

import os
import time
import urllib
import requests
import traceback

from tqdm import tqdm
from multiprocessing import Process, Pool, Manager, cpu_count

class Downloader(object):
	
	def __init__(self) -> None:
		
		pass
		
	
	def multi_processing_download(self, url: str, n_process: int=None) -> None:
		"""
		Download file with multiprocessing.
		
		:param url		: The URL of the resource needed to download.
		:param n_process: Total number of processes in pool. 
		"""
		if n_process is None:
			n_process = cpu_count() - 1
		parse_result = urllib.parse.urlparse(url)
		filename = parse_result.path.rsplit('/', 1)[1]
		headers = requests.head(url).headers
		filesize = int(headers.get('Content-Length', None))
		manager = Manager()
		queue = manager.Queue(10000)
		process = Process(target=self._display_download_speed, args=(filesize, queue))
		start = 0
		end = -1
		with open(filename, 'w') as f:
			f.seek(0)		
		pool = Pool(processes=n_process)
		step = filesize // n_process
		print('Step: {}'.format(step))
		while end < filesize - 1:
			start = end + 1
			end = start + step -1
			print('start: {} - end: {}'.format(start, end))
			if end > filesize:
				end = filesize
			pool.apply_async(self._partially_download, args=(url, start, end, filename, queue))
		pool.close()
		process.start()
		pool.join()
		process.join()
		print('Process join done')
		
	def multi_threading_download(self, url: str) -> None:
		pass
	
	def _display_download_speed(self, filesize, queue): 
		write_size = 0
		print('Check download speed')
		while True:
			speed = 0
			current_timestamp = time.time()
			while not queue.empty():
				item = queue.get(True)
				size = item.get('size', 0)
				timestamp = item.get('timestamp', current_timestamp - 10000)
				write_size += size
				if current_timestamp - timestamp > 1:
					break
				speed += size
			ratio = write_size / filesize
			try: 
				self._display_process(ratio, speed)
			except:
				pass

	def _display_process(self, ratio: float, speed: float, n_bar: int=100) -> None:
		end_char = '\r'
		if ratio >= 1:
			end_char = '\n'
		bar_number = 100
		done_number = round(ratio * bar_number) 
		done_char = '#' * done_number
		remain_char = '-' * (bar_number - done_number)
		process_bar = '[{done_char}{remain_char}] {percentage}% speed:{speed}'.format(
			done_char=done_char,
			remain_char=remain_char,
			percentage='%0.2f' % (ratio * 100),
			speed=speed,
		)
		print(process_bar, end=end_char)

	def _partially_download(self, url, start_position, end_position, filename, queue) -> None:
		try:
			with open(filename, 'rb+') as f:
				print('Start downloading****')
				headers = {'Range': 'bytes=%s-%s' % (start_position, end_position)}
				response = requests.get(url, headers=headers, stream=True)
				f.seek(startpos)
				for data in response.iter_content(chunk_size=1024):
					f.write(data)
					queue.put({'timestamp': time.time(), 'size':len(data)})
		except Exception as e:
			print('download error', e)
			traceback.print_exc()

if __name__ == '__main__':
	d = Downloader()
	url = 'https://web.stanford.edu/~hastie/CASI_files/PDF/casi.pdf'
	url = '"https://codeload.github/lrs1353281004/CS224n_winter2019_notes_and_assignments/zip/refs/heads/master.zip"'
	# d.multi_processing_download(url)
	d.multi_processing_download(url, 4)


20230228

  • 昨晚又是开会到十点半,这周极限冲刺,7号前要把NFSC初稿弄出来,头大。
  • 下午把浪潮的申请签好盖章寄掉,时间太晚还是去操场混了二十分钟训练,其实已是末尾冷身,我顺带着跟陈嘉伟晃了四圈顺带热身。嘉伟终于还是被一个寒假给干倒了,嘉伟说他一个寒假没动,前几天跑了个2km就躺了几天,这样的从低谷慢慢恢复的痛苦我已经经历过N多次。暑假相对来说要好一些,但是过年要坚持每天训练,你自己能坚持得下来,家人也不会让你这么去像个神经病在路上狂奔,还要承受别人异样的目光。
  • 今天状态跟预估有差距,可能是跑前跑后费了些力气,而且热身的时候跟嘉伟跑得太快,后来4分配跑了2km就直接垮掉,补了一个800米,感觉这周要能上10km挺悬,然时不我待,只剩不到20天了。

Census X12和X13调整需要使用美国统计局已封装号的X12a.exe和X13AS.EXE二进制程序,找了半天只有CSDN上有个资源比较靠谱一些,里面提供了测试代码和两个可执行程序(https://download.csdn/download/zhouhao707/12717511?spm=1001.2101.3001.5697)

然鹅需要积分,但是我已经传到盘里了,有需求自取:

https://pan.baidu.com/s/1hDWVXeGp6ovTsLq2i0Dvgg?pwd=957n 

另外我做了一个测试程序:

# -*- coding: utf-8 -*-
# @author: caoyang
# @email: caoyang@163.sufe.edu

import numpy as np
import pandas as pd
from datetime import datetime
from X12a_X13as import X12a, X13as

a = X13as() # 调用这个类的方法

# 随机造了一组数据dataframe, dataframe的index必须是日期格是
df = pd.DataFrame({'data': np.random.random(36)})
df.index = [datetime(2020, i, 1) for i in range(1, 13)] + [datetime(2021, i, 1) for i in range(1, 13)] + [datetime(2022, i, 1) for i in range(1, 13)]

result = a.x13(df)

for k, v in result.items():
	print(k, v)

调整后的序列有三个,虽然不是很懂是什么意思(给凯爹做的)。


20230301

  • 状态又很迷,下午慢跑10圈都感觉吃力,可能是跟gjw边跑边说话的缘故,我发现不管我用多少配速跑(虽然再慢也不会掉出5分配),时间长了心率都要到170以上,像很多人慢跑心率都能控到150以下。其实就是跑量太少,听说跑量过10000km心率才会有明显降低,现在连5000km都不到。
  • 从2月13日恢复训练起算,距离3月19号前只有33个训练日,到目前已经是17个训练日,过半,但跑万米的把握都不到三成,这周虽然很push,但也得设法抽出时间试跑一次万米了,不然真的来不及了。

因果推断遐想(二):

明月姐的预答辩如预期一般的通过了,其实五个老师一个都不懂因果推断,所以基本都是听得云里雾里,牛B哄哄的崔万云都没提一点有意义的建议,只是说因果推断似乎是实验室研究,现实世界是行不通的。诚然如是,但是不可否认的是目前的确因果推断在工业界也是有应用的。我认为因果推断如果想要做出实际意义,那就得做出和知识图谱一般的因果图谱,然而因果图谱要比知识图谱复杂得多,目前的因果图都是确定的有向边,其实现实世界哪有那么多绝对呢?所以因果图理论上应该是概率边,但是如果是概率边,似乎就要破坏目前因果推断的理论基石(do算子、后门调整、前门调整之类的)。

一种主题干预的后门调整情感分析示意图,我改了个超科幻的自动混杂生成的设想图,反正是写本子,天马行空了:

20230302

  • 晚上训练陈嘉伟陪跑,成功恢复到场地万米,节奏很好,有人一起跑动力十足。用时42’22",均配4’14"。前5000米我领跑,用时21’09",后5000米换嘉伟领跑,用时21’13",说到底男人的话一个标点都不能信,嘉伟说他一个寒假没动,现在耐力垮得很,所以这就是指就是轻松跑完10km,又做了100个俯卧撑,最后还补了7圈追逐跑(其实我跑完也不是很累,但是追逐跑了5圈就不想坚持了,这种节奏稳定的万米跑完确实超级享受)。
  • 今晚很冷,其实并不适合跑,本来下午阳光明媚,但是我又很想等训练时一起跑,所以下午只是养生晃了三圈,等到晚上跟嘉伟尽兴一下。现在距离锡马开赛还有16天,14个训练日,只要能保持这个状态,跑进95分钟应该是绰绰有余,就看能否稳中求进冲击90分钟大关了。

跟明月姐拉扯了一下午,来看看最终这版天马行空的架构图(难道混杂未知就是你虚空索敌的理由???


20230303~20230304

  • 下午训练,状态极佳本以为可以轻松拿下八组400米间歇,结果前两组跑完从臀部到大腿就已经麻得站都站不稳。第一组1’10",第二组1’13",然后就痛苦到死,站着难受,坐着更难受,接着两组掉到1’20",纯靠一丝意志在冲刺,四组跑完所有人都瘫倒在地,再起不能。时隔三个多月,再次被死亡400打回原形。
  • 3月11日高百资格赛将在武东田径场进行,这也是疫情后校友们第一次返回学校参赛,作为锡马前的一次热身是再好不过。

关于虚假线索与因果特征的识别,可以基于特征的域适应差异性来进行区分:


20230305~20230306

  • 下午计划慢跑十圈,结果刚进场就看到宋镇均在练1000米间歇。上学期十月yq爆发后他就离校一直未归,我以为他真又废了,这学期刚来时我问他多久没跑,他说二月还是练了几次,结果前天400米间歇先是给我一个下马威,今天进场看他的速度还以为是在跑第一个1000米,跑完他告诉这已经是第4个了。我直接震惊了,当即说最后一个我来带他跑,顺便胜之不武地拿捏一下他。尽管我是穿长袖长裤来准备慢跑,但第一圈还是带到3’40"以内的配速,我看他似乎有点不支,于心不忍还是故意放慢等了他一下,结果这年轻人不讲武德,第二圈到一半就把我超了,还真就一直追不上,给我整不会了。
  • 后来补了3000米慢跑,气温太高,而且右脚踝隐隐作痛,大约是前天间歇跑得太猛的缘故。明天下午的训练大概率是5×1000米间歇,由于近期已经在为锡马作准备,尽可能地早睡早起,自我感觉状态很好,跑起来却相当吃力(一方面可能是气温太高的原因),但总是觉得很悬的了。

其实变分自编码器是个很理想地产物,反正我觉得实际应用上很难很难用,一个是假设太强,理论上可以进行运用,但是不可能用于实际产品。

最近看孙健老师对一个经典命题的证明,即证明 2 + 3 + 5 + . . . + p \sqrt{2}+\sqrt{3}+\sqrt{5}+...+\sqrt{p} 2 +3 +5 +...+p ,对于任意素数 p p p,都不是有理数。

当然其实直接证明 ∑ i = 0 n i \sum_{i=0}^n\sqrt{i} i=0ni 不是有理数也是一样的。

这里有一个很巧妙的证法,就是定义这样一个多项式:

f ( x ) = ∏ ( x ± 3 ± . . . ± p ) f(x)=\prod (x\pm{\sqrt{3}\pm...\pm\sqrt{p}}) f(x)=(x±3 ±...±p )

令:
r = 2 + 3 + 5 + . . . + p r = \sqrt{2}+\sqrt{3}+\sqrt{5}+...+\sqrt{p} r=2 +3 +5 +...+p

那么 f ( r − 2 ) f(r-\sqrt{2}) f(r2 )显然等于零(因为 r r r f ( x ) f(x) f(x)的一个零点)

如果 r r r是一个有理数,那么 r + 2 r+\sqrt{2} r+2 r − 2 r-\sqrt{2} r2 的一个共轭根,即 f ( r + 2 ) f(r+\sqrt{2}) f(r+2 )也是零,但是显然 f ( r + 2 ) > 0 f(r+\sqrt{2})>0 f(r+2 )>0(因为 f ( x ) f(x) f(x)里每一项都是正数)。

确实很精妙,但是事实上这个用Galois或者伽罗瓦理论可以直接证明,我这辈子是学不到高等代数里面的数域和群论了,总觉得这辈子数学可能也就学到现在这个水平为止了唉,好难过。


20230307

  • 今天并没有跑1000米间歇,东哥让我们弹力带拉了100个引体(我是真废,用最粗的弹力带,拉10个都费事,细一个档次的就完全拉上不去),然后连续跳栏10组,最后接7圈变速+7圈追逐。7圈变速我强行跟住了陈嘉伟(感觉嘉伟确实状态距离巅峰差太多了,放以前不可能让我跟这么轻松),快圈1’20",慢圈1’50",成功套其他四人各一圈,东哥说我最近状态挺好,那可不是么,想要跑半马,当然得保持状态。
  • 分手见人品,我说廖是深咋这么久都不来训练,原来是跟李婷玉分了。说实话我是觉得姐弟恋不靠谱,尤其是女博士,男生多少是有一些支配欲的,双方阅历都不是一个层面的,更不要说廖本科都还没毕业,能不能上岸都不靠谱。但是廖在pyq里话说的实在是太难听,摆明了要把对方名声搞臭,对错不论,也不至于恶化到这种程度,男生总归还是要大气一点。

关于引入混杂表示生成的文本分类模型去混杂,想了一个目标二的具体显式表示:

L 2 = ∑ i = 0 c d i f f ( { H t } t : y t = i ) − ∑ 0 ≤ i < j ≤ c d i f f ( { H t } t : y t = i ∪ { H t } t : y t = j ) L_2=\sum_{i=0}^{c}diff\left(\{H_t\}_{t:y_t=i}\right)-\sum_{0\le i<j\le c} d i f f\left(\{H_t\}_{t:y_t=i}\cup\{H_t\}_{t:y_t=j}\right) L2=i=0cdiff({Ht}t:yt=i)0i<jcdiff({Ht}t:yt=i{Ht}t:yt=j)

这里为了使得学习到的混杂表示能够影响样本标签,因此考虑从聚类角度出发,使得标签相同的样本对应的混杂隐层表示的差异性尽可能小,而样本标签不同的样本对应的混杂隐层表示的差异性尽可能大。从而确保混杂隐层表示与预测标签地强关联性。 d i f f diff diff是预先设置好的一个表示差异化程度的函数。


20230308

  • 扬州鉴真国际半程马拉松报名开始,两万人,4月16日开赛。虽说计划是锡马后跑步训练告一段落,但是扬马毕竟是家门口的比赛,也是我最希望参加的比赛。查了一下2019年的市民组成绩,1小时25分进前10,1小时30分进前30,1小时35分进前50,可惜今年只奖励前10,就目前我的水平,稳进135,但130需要极好的状态,125几乎不可能完成,所以想拿奖金难度极大。不过反正报名抽签不要钱,就碰个运气呗,抽中血钻,就当是圆梦了。抽不中就一心一意搞论文咯。
  • 晚上wyl又开会到十点半,明月姐天高皇帝远,于是我跟黄名媛两个倒霉蛋跟wyl拉扯了近四个小时。本来今天想好好休息休息,昨天练引体和跳栏,今天背和腰都疼得不行,下午慢跑10圈保持状态,然后网上这么一出,明明ddl还有好几天,真是push起来就不当人。

关于基于软提示的生成。其实目前就硬提示而言,总觉得没什么研究价值,就一帮人在哪儿给PLM喂模板吃,模板不好就改,模板好就发文章,一点意思没有,纯纯的工程项目。但是软提示的确还是挺有趣的,下面是本次申报做的一个反事实增强的生成框架,提示的好处感觉是可以大大缩小训练量,当然代价是需要大模型,因为大模型的参数是freeze的,本质上是在学一个好的提示向量表示。


20230309

  • 揠苗助长,状态终归还是一个周期性的数值,虽然这几天感觉饮食作息都ok,晚上计划要跑15km,然后晚饭吃特别多,结果两个多小时没能消化完,五点吃完到七点半都撑得厉害,跑了5km就歇菜了(陈嘉伟有事没来,也有点缺乏动力,本来晚上的状态就稍差些)。随队练了两组蛙跳,然后箭步跳4×60个,做完我就知道明天大腿肯定废了,不过这两天在赶工,下午跟黄名媛又给wyl关了半天牢,11号到晚必须要把稿子修好,万一废了干脆休两天拉倒。我总是觉得赛前至少要拉一个15km,否则至少从心理上来说会有些动摇,但我又不想到临近比赛太过度训练,所以很想这周能把15km给跑掉,还是太急了,但毕竟是首马,总是想以万全的状态去迎战。
  • 葛智杰和卢星雨两个倒霉蛋,前天居然食物中毒,据说是吃了新园的啥团子,急性肠胃炎连带发烧,不得不花了大几百去长海吊水,然后今晚又来卷,结果葛智杰直接被卢星雨带崩了,太丢人啦。

关于python字符串输出的几个小技巧:

n = int(input('输入奇数n:'))
if n % 2 == 0:
    n = int(input('输入奇数n:'))
m = (n + 1) // 2

string_formatter = '{:^' + str(n + 2) + '}'

for i in range(m + 1):
    print(string_formatter.format('*' * (2 * i + 1)))

比如'{:^9}'.format('*')就是划出一个长度为9的空当,然后把*插在中间。

但是如果想要把9替换成任意的n,就得写成上面string_formatter = '{:^' + str(n + 2) + '}'的形式。


20230310~20230311

  • 状态低迷的两日,昨天起初大腿还不是很酸,下午硬撑着晃了10圈,就已经站不起来了。
  • 今天ddl,决定翘了训练,稿子还没整完,大概率也溜不掉,索性跑休一日。明天降温,也是锡马最后一周倒计时,就是拼了老命,也必须拉一次长距离。

HRCA复现

# -*- coding: utf-8 -*-
# @author: caoyang
# @email: caoyang@163.sufe.edu
# Implementation of HRCA

import torch
from torch.nn import Module, Linear, NLLLoss, functional as F

from setting import DEVICE
from src.tool.pretrained_model_tool import load_transformer_model
from src.module.attention_module import MultiHeadAttention


class HRCA(Module):
	"""Forward propagation algorithm of HRCA and HRCA+
	Reference: [HRCA+: Advanced Multiple-choice Machine Reading Comprehension Method](www.lrec-conf/proceedings/lrec2022/pdf/2022.lrec-1.651.pdf)
	- Input:
	  - $P \in \R^{d×p}$ 
	  - $Q \in \R^{d×q}$
	  - $A = \{A_1, ..., A_m\}, A_j \in \R^{d×a}$
	- Output:
	  - $L \in \R^m$"""
	loss_function = NLLLoss()
	def __init__(self, args):
		super(HRCA, self).__init__()
		self.p = args.max_article_token
		self.q = args.max_question_token
		self.a = args.max_option_token
		self.m = args.n_choices
		self.l = args.hrca_encoding_size
		self.k = args.hrca_num_layers
		self.fuse_method = args.hrca_fuse_method
		self.plus = args.hrca_plus

		self.multi_head_attention = MultiHeadAttention(d_model=args.hrca_encoding_size, num_heads=args.hrca_mha_num_heads, dropout_rate=args.hrca_mha_dropout_rate)
		self.fuse_linear_x = Linear(self.l, self.l, bias=True)
		self.fuse_linear_y = Linear(self.l, self.l, bias=True)
		self.fuse_linear_z = Linear(self.l, self.l, bias=True)
		if self.fuse_method in ['mul', 'sum']:
			self.W = Linear(self.l, 1, bias=False)
		elif self.fuse_method == 'cat':
			self.W = Linear(3 * self.l, 1, bias=False)
		else:
			raise Exception(f'Unknown fuse method: {self.fuse_method}')
		if args.load_pretrained_model_in_module:
			self.pretrained_model = load_transformer_model(model_name=args.hrca_pretrained_model, device=args.pretrained_model_device)
			self.pretrained_model.eval()
		else:
			self.pretrained_model = None
	# @param P	: {'input_ids': tensor, 'token_type_ids': tensor, 'attention_mask': tensor}, tensor(batch_size, max_article_token)
	# @param Q	: {'input_ids': tensor, 'token_type_ids': tensor, 'attention_mask': tensor}, tensor(batch_size, max_question_token)
	# @param A	: {'input_ids': tensor, 'token_type_ids': tensor, 'attention_mask': tensor}, tensor(batch_size * N_CHOICES, max_option_token)
	def forward(self, P, Q, A, pretrained_model=None):
		E_P, E_Q, E_A = self.contextualized_encoding(P, Q, A, pretrained_model=pretrained_model)
		O = self.human_reading_comprehension_attention(E_P, E_Q, E_A)	# O				: (batch_size, N_CHOICES, ?)
		L_unactived = self.W(O).squeeze(-1)								# L_unactived	: (batch_size, N_CHOICES)
		L = F.log_softmax(L_unactived, dim=-1)							# L				: (batch_size, N_CHOICES)
		return L

	# @param P		: {'input_ids': tensor, 'token_type_ids': tensor, 'attention_mask': tensor}, tensor(batch_size, max_article_token)
	# @param Q		: {'input_ids': tensor, 'token_type_ids': tensor, 'attention_mask': tensor}, tensor(batch_size, max_question_token)
	# @param A		: {'input_ids': tensor, 'token_type_ids': tensor, 'attention_mask': tensor}, tensor(batch_size * N_CHOICES, max_option_token)
	# @return E_P	: (batch_size, N_CHOICES, max_article_token, hrca_encoding_size)
	# @return E_Q	: (batch_size, N_CHOICES, max_question_token, hrca_encoding_size)
	# @return E_A	: (batch_size, N_CHOICES, max_option_token, hrca_encoding_size)
	def contextualized_encoding(self, P, Q, A, pretrained_model=None):
		batch_size = P['input_ids'].size(0)
		size_of_split_choice = (batch_size, self.m, self.a)
		A['input_ids'] = A['input_ids'].view(*size_of_split_choice)
		A['token_type_ids'] = A['token_type_ids'].view(*size_of_split_choice)
		A['attention_mask'] = A['input_ids'].view(*size_of_split_choice)
		E_list = list()
		for i in range(self.m):
			concat_inputs = {'input_ids'		: torch.cat([P['input_ids'], Q['input_ids'], A['input_ids'][:, i, :]], axis=-1),				# (batch_size, max_article_token + max_question_token + max_option_token)
							 'token_type_ids'	: torch.cat([P['token_type_ids'], Q['token_type_ids'], A['token_type_ids'][:, i, :]], axis=-1),	# (batch_size, max_article_token + max_question_token + max_option_token)
							 'attention_mask'	: torch.cat([P['attention_mask'], Q['attention_mask'], A['attention_mask'][:, i, :]], axis=-1),	# (batch_size, max_article_token + max_question_token + max_option_token)
							 }
			E_list.append(pretrained_model(**concat_inputs).last_hidden_state.unsqueeze(1) if self.pretrained_model is None else self.pretrained_model(**concat_inputs).last_hidden_state.unsqueeze(1))
		E = torch.cat(E_list, axis=1)			# E		: (batch_size, N_CHOICES, max_article_token + max_question_token + max_option_token, hrca_encoding_size)
		E_P = E[:, :, :self.p, :]				# E_P	: (batch_size, N_CHOICES, max_article_token, hrca_encoding_size)
		E_Q = E[:, :, self.p:self.p+self.q, :]	# E_Q	: (batch_size, N_CHOICES, max_question_token, hrca_encoding_size)
		E_A = E[:, :, self.p+self.q:, :]		# E_A	: (batch_size, N_CHOICES, max_option_token, hrca_encoding_size)
		return E_P.to(DEVICE), E_Q.to(DEVICE), E_A.to(DEVICE)

	# @param E_P: (batch_size, N_CHOICES, max_article_token, hrca_encoding_size)
	# @param E_Q: (batch_size, N_CHOICES, max_question_token, hrca_encoding_size)
	# @param E_A: (batch_size, N_CHOICES, max_option_token, hrca_encoding_size)
	# @return O	: (batch_size, N_CHOICES, ?) where ? could be hrca_encoding_size or 3 * hrca_encoding_size
	def human_reading_comprehension_attention(self, E_P, E_Q, E_A):
		O_list = list()
		for i in range(self.m):
			E_P_U, E_Q_U, E_A_U = self._hrca(E_P[:, i, :, :], E_Q[:, i, :, :], E_A[:, i, :, :])
			if self.k > 1:
				# Stack k layers
				for _ in range(self.k - 1):
					E_P_U, E_Q_U, E_A_U = self._hrca(E_P_U, E_Q_U, E_A_U)
			O_i = self._fuse(E_P_U, E_Q_U, E_A_U)	# O_i	: (batch_size, ?)
			O_list.append(O_i.unsqueeze(1))
		O = torch.cat(O_list, axis=1)				# O		: (batch_size, N_CHOICES, ?)
		return O

	# @param E_P_U	: (batch_size, max_article_token, hrca_encoding_size)
	# @param E_Q_U	: (batch_size, max_question_token, hrca_encoding_size)
	# @param E_A_U	: (batch_size, max_option_token, hrca_encoding_size)
	# @return E_P_U	: (batch_size, max_article_token, hrca_encoding_size)
	# @return E_Q_U	: (batch_size, max_question_token, hrca_encoding_size)
	# @return E_A_U	: (batch_size, max_option_token, hrca_encoding_size)
	def _hrca(self, E_P_U, E_Q_U, E_A_U):
		if self.plus:
			# HRCA: Q2Q -> O2Q -> P2O
			E_Q_U = self.multi_head_attention(queries=E_Q_U, keys=E_Q_U, values=E_Q_U)	# E_Q_U: (batch_size, max_question_token, hrca_encoding_size)
			E_A_U = self.multi_head_attention(queries=E_A_U, keys=E_Q_U, values=E_Q_U)	# E_A_U: (batch_size, max_option_token, hrca_encoding_size)
			E_P_U = self.multi_head_attention(queries=E_P_U, keys=E_A_U, values=E_A_U)	# E_P_U: (batch_size, max_article_token, hrca_encoding_size)
		else:
			# HRCA+: Q2Q -> Q2O -> O2O -> O2Q -> O2P -> Q2P -> P2P -> P2Q -> P2O
			E_Q_U = self.multi_head_attention(queries=E_Q_U, keys=E_Q_U, values=E_Q_U)	# E_Q_U: (batch_size, max_question_token, hrca_encoding_size)
			E_Q_U = self.multi_head_attention(queries=E_Q_U, keys=E_A_U, values=E_A_U)	# E_Q_U: (batch_size, max_question_token, hrca_encoding_size)
			E_A_U = self.multi_head_attention(queries=E_A_U, keys=E_A_U, values=E_A_U)	# E_A_U: (batch_size, max_option_token, hrca_encoding_size)
			E_A_U = self.multi_head_attention(queries=E_A_U, keys=E_Q_U, values=E_Q_U)	# E_A_U: (batch_size, max_option_token, hrca_encoding_size)
			E_A_U = self.multi_head_attention(queries=E_A_U, keys=E_P_U, values=E_P_U)	# E_A_U: (batch_size, max_option_token, hrca_encoding_size)
			E_Q_U = self.multi_head_attention(queries=E_Q_U, keys=E_P_U, values=E_P_U)	# E_Q_U: (batch_size, max_question_token, hrca_encoding_size)
			E_P_U = self.multi_head_attention(queries=E_P_U, keys=E_P_U, values=E_P_U)	# E_P_U: (batch_size, max_article_token, hrca_encoding_size)
			E_P_U = self.multi_head_attention(queries=E_P_U, keys=E_Q_U, values=E_Q_U)	# E_P_U: (batch_size, max_article_token, hrca_encoding_size)
			E_P_U = self.multi_head_attention(queries=E_P_U, keys=E_A_U, values=E_A_U)	# E_P_U: (batch_size, max_article_token, hrca_encoding_size)			
		return E_P_U, E_Q_U, E_A_U

	# @param x	: (batch_size, x_length, hrca_encoding_size)
	# @param y	: (batch_size, y_length, hrca_encoding_size)
	# @param z	: (batch_size, z_length, hrca_encoding_size)
	# @return	: (batch_size, ?) where ? could be hrca_encoding_size or 3 * hrca_encoding_size
	def _fuse(self, x, y, z):
		x_project = self.fuse_linear_x(x)					# x_project			: (batch_size, x_length, hrca_encoding_size)
		y_project = self.fuse_linear_y(y)					# y_project			: (batch_size, y_length, hrca_encoding_size)
		z_project = self.fuse_linear_z(z)					# z_project			: (batch_size, z_length, hrca_encoding_size)
		x_project_pooled = torch.max(x_project, axis=1)[0]	# x_project_pooled	: (batch_size, hrca_encoding_size)
		y_project_pooled = torch.max(y_project, axis=1)[0]	# y_project_pooled	: (batch_size, hrca_encoding_size)
		z_project_pooled = torch.max(z_project, axis=1)[0]	# z_project_pooled	: (batch_size, hrca_encoding_size)
		if self.fuse_method == 'mul':
			return torch.sigmoid(x_project_pooled * y_project_pooled * z_project_pooled)					# @return	: (batch_size, hrca_encoding_size)
		elif self.fuse_method == 'sum':
			return torch.sigmoid(x_project_pooled + y_project_pooled + z_project_pooled)					# @return	: (batch_size, hrca_encoding_size)
		elif self.fuse_method == 'cat':
			return torch.sigmoid(torch.cat([x_project_pooled, y_project_pooled, z_project_pooled], axis=-1))# @return	: (batch_size, 3 * hrca_encoding_size)
		else:
			raise Exception(f'Unknown fuse method: {self.fuse_method}')

20230312

  • 昨天到晚状态跌落到极点,疲乏,虚汗,我甚至怀疑是不是要发烧,这一周五个工作日开了四次会,两次都是晚上开到十点半,昨天更是从早到晚,都没有抽出时间午睡。回去十点倒头就睡,早上六点半起,但是半夜醒了几次,似乎状态未能恢复几分。
  • 结果今早寒潮降雨,但是我既然已经准备了今早起跑,补给都准备完毕,无论如何也不愿意就这么放弃,换上背心三分裤硬顶着5℃的寒风细雨,结果5000米就给我干废了。
  • 下周日也是同样的时点起跑,无论如何我都想在今天能模拟一次比赛日的场景,所以天气再恶劣也要拼命去冲一次。如此的挫败让我大失所望,我甚至怀疑自己能否真的完赛。
  • 最后一周,五个训练日,成败犹未可知。
  1. torchvision.transforms.ToTensor
  • 把一个取值范围是 [ 0 , 255 ] [0,255] [0,255]PIL.Image或者shape ( H , W , C ) (H,W,C) (H,W,C)numpy.ndarray,转换成shape ( C , H , W ) (C,H,W) (C,H,W),取值范围是 [ 0 , 1.0 ] [0,1.0] [0,1.0]torch.FloadTensor;

    • 注意会把channel(大部分图片的channel都是在第三个维度, channel维度值一般为 3 3 3 4 4 4, 即 R G B \rm RGB RGB R G B A \rm RGBA RGBA对应的维度提到了shape的最前面;
    • 注意该变换并不是直接转为张量, 对于 R G B \rm RGB RGB值的图片型的张量, 观察源码可发现会作除以 255 255 255的归一标准化;
    • 不符合上述图片型张量的形式的张量(如输入二维矩阵), 将直接不作任何数值处理直接转为 t o r c h \rm torch torch中的张量;
  • 可以使用torchvision.transforms.ToPILImage作逆变换, 这两个函数互为反函数;

    • 这是一个只针对PIL.Image输入的反函数, 即必然乘以 255 255 255再返回成图片数据类型;
  • 代码示例:

    import cv2
    import torchvision as tv
    
    # torchvision.transforms.ToTensor
    f = tv.transforms.ToTensor()
    numpy2tensor = f(np.array([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]))
    image = cv2.imread(r'D:\media\image\wallpaper\1.jpg')
    image2tensor = f(image)
    print(numpy2tensor)
    print(image.shape)
    print(type(image2tensor))
    print(image2tensor.shape)
    
    # torchvision.transforms.ToPILImage
    f1 = tv.transforms.ToTensor()
    f2 = tv.transforms.ToPILImage()
    image = cv2.imread(r'D:\media\image\wallpaper\1.jpg')
    image2tensor = f1(image)
    tensor2image = f2(image2tensor)
    print(type(tensor2image))
    print(np.asarray(tensor2image))
    
  1. torchvision.transforms.Normalize
  • 这也是个很诡异的函数, 目前没有看出到底是怎么进行标准化的, 两个参数分别为meanstd;

    • 我现在看明白了,其实是 x : = ( x − mean ) / std x:=(x-\text{mean})/\text{std} x:=(xmean)/std,这里的meanstd是可以对应 c h a n n e l \rm channel channel数来写的
  • 也只能对图片型张量进行处理

  • 代码示例:

    import torchvision as tv
    
    f1 = tv.transforms.ToTensor()
    f2 = tv.transforms.Normalize([.5], [.5])
    image = cv2.imread(r'D:\media\image\wallpaper\1.jpg')
    image2tensor = f1(image)
    normal_tensor = f2(image2tensor)
    print(image.shape)
    print(image2tensor.shape)
    print(normal_tensor.shape)
    

20230313~20230314

  • 昨天下午一点开会,又没能睡到午觉。四点补了两个绿豆糕进场。晴朗,10℃,无风,绝佳的天气,结果跑得异常笨重,完全没有两周前的那种轻盈感,将将5000米就顶不下去了,跑得我一头问号,就这臭水平还想把跑进130???太失望了。
  • 后来还是冷静了下来,终是我对首马看得太重,谁又能一次就成功呢?急也没有用,现在做的也只有早睡早起,保证睡眠饮食,所以从昨晚起,11点半前必睡,7点起,中午补1小时觉。最后5天我终究不可能强行冲10km以上的长距离,以目前的体能来说,这样的强度后必然需要长时间恢复休息,然而我已经没有时间了。
  • 所以今天下午我还是选择跟队练6×1000米间歇,第一组全力冲到3’23"(PB,之前最快到3’25"),仅次于陈嘉伟3’11",最后100米反超了专项练800米的徐瀚韬;后面几组就废了,二三两组掉到3’48"和3’50",第四组间歇了10分钟,又冲回到3’43",第五组摸鱼,最后一组全力冲到3’42",整体来看平均水平仍然不及去年12月(那时每组都能进3’45",而且头尾两组都能进3’30",其实今天还是最后三组陈嘉伟溜了,少了兔子确实很难顶住强度)。
  • 给凯爹搞了台打印机,虽然有点笨重,但是男人之间送生日礼物还是实际点儿[偷笑]。

因果推断里面有个比较重要的点是作因果特征分析,其目的是剔出虚假关联。现在常用的一个策略是选取处置变量进行样本加权,来解决处置变量在整体数据中的不平衡问题。具体而言:

w ∗ = arg ⁡ min ⁡ i ∑ i = 1 K ∑ m = 1 M i ∥ 1 N 1 i ∑ j : T j i = 1 C m , j i ⋅ w j − 1 N 0 i ∑ j : T j i C m , j i ˆ ⋅ w j ∥ 2 2 w^*=\arg\min_i\sum_{i=1}^K\sum_{m=1}^{M_i}\left\|\frac1{N_1}^i\sum_{j:T_j^i=1}C_{m,j}^i\cdot w_j-\frac1{N_0^i}\sum_{j:T_j^i}C_{}m,j\^i\cdot w_j \right\|_2^2 w=argimini=1Km=1Mi N11ij:Tji=1Cm,jiwjN0i1j:TjiCm,jiˆwj 22

对应到文本任务中,如果是特征工程类的模型,如one-hot编码的词特征, T j i = 1 T_j^i=1 Tji=1代表当前处置变量(词特征) T i T^i Ti出现在样本 j j j中; T j i = 0 T_j^i=0 Tji=0则代表 T i T^i Ti未出现在样本 j j j中; C m , j i C_{m,j}^i Cm,ji代表当前的处置特征 T i T^i Ti的第 m m m的混杂特征在第 j j j个样本中取值; N 1 i N_1^i N1i代表词特征 T i = 1 T^i=1 Ti=1的样本数目; N 0 i N_0^i N0i代表词特征 T i = 0 T^i=0 Ti=0的样本数目。

这里就衍生出一个推广问题,one-hot的词表示显然是太low了,有没有可能推广到一般的词向量。但是这很难,因为我们是可以解释one-hot词表示每一维的含义的(比如这里就是表示词袋的含义,词是否出现在样本中),但是一般的词向量就没有这种含义,那太过于抽象了,所以至少也是不能称为是样本加权。

其实如果熟悉Gensim里各种语言模型,比如TFIDF,LSI,HDF之类的,会发现除了TFIDF是从词袋模型(即one-hot)上进行计算得到新的词表示,LSI之类的都是在TFIDF的词表示上进一步计算,所以理论上来说是可以将上面这个加权方法推到(至少在)TFIDF这个层面上,此时我们说的因果特征和虚假特征就是非常抽象的概念了,可能是词表示的某几维,而事实上也有关于PLM输出的嵌入的每一维的具体表示含义的研究,即试图去解释词嵌入的每一维表示什么含义。


20230315

  • 结果昨晚又被王英林关到十点半之后,刚坚持了两天早睡早起就又被迫破戒。完会跟黄名媛走了一路,因为都住三门路,我也不知道她是否单身,但我感觉练街舞的肯定交际圈很广。怎么说呢,确是喜欢的类型,圆滚滚的脸蛋儿,带些婴儿肥,笑起来直接眯成月牙,还是个川妹子(经常平翘舌不分),谁能不动心呢。可惜大概已经过了那个一见钟情的年纪,地域不同约莫也不会有啥结果。实际点儿cy,女人,只会影响你跑步的速度!
  • 晚23:49,我想我可能真的是喜欢上了黄名媛,我对自己真的好失望好失望。今晚又是开会到23点之后(其实是开了一天),结束后我就莫名想等她一起走,在那儿等她跟王英林说了好久。昨晚还只是骑车半路碰到,今天我故意没有去拿车,就是想跟她一起走地下通道回三门路,就这么有些拘谨又有些欣喜地聊了一路。自从上一段已经过了整整两年,这对跑者来说并不是无法承受的孤独,但是当我心里开始有今晚这种念想时,回想以前又对sxy总有那些情愫,我觉得真的是差劲到顶了。

定义混杂

  • E E E D D D相关;以 D D D为条件时, E E E C C C相关, E E E不在 D D D C C C的因果关系路径中。则称 E E E是混杂因子

再说明条件独立 D D D-分离的概念:

  • 三种结构:

    • 链式结构: A → B → C A\rightarrow B\rightarrow C ABC,在 A A A C C C的路径中, B B B称为中介变量。
    • 叉式结构: A ← B → C A\leftarrow B\rightarrow C ABC,在 A A A C C C的路径中, B B B称为混杂变量。
    • 对撞结构: A → B ← C A\rightarrow B\leftarrow C ABC,在 A A A C C C的路径中, B B B称为碰撞变量。

20230316

  • 17号0:35,不写点儿心里难受得很。
  • 喜提连续三日被王英林拷打到23点之后,昨晚一直到23:30才放人,不过我也是自愿的,王英林知道我要比赛并没有强留,但是我觉得留黄名媛一个人跟王英林对线实在是太残忍了(当然肯定还是有私情的缘故),事实上从结果来看如果我不去push王英林的进度,以他那龟速这本子指定是要流产了。反正我也是打着跟黄名媛一起回三门路的算盘,早睡?不存在的,状态就听天由命吧,反正锡马跑不好还有扬马可以跑,俺又中签了。
  • 昨晚还是去队里训练了,因为明天下雨,后天就已经去无锡了,这是最后一练,我请陈嘉伟带我再冲最后一次10000米。我终于又找回了感觉,前5000米还是我带,因为体力充沛,嘉伟5000米过后超上来给我拉住配速,可惜第8个1000米带到了4’05",直接把我带崩了,最后是4’13"的均配跑完了8000米,停了一圈跟嘉伟把最后2000米冲完。我觉得至少八九成的状态是有的,不至于太悲观。
  • 前天夜里失眠,很久不失眠了,上次可能还是两年前了,有心事就睡不着,到夜里1点半才睡着,凌晨5点半就醒了,后来就一直睡不着,干脆七点起床算了。

对于叉式结构,具体可以用公式表达:

  • 首先根据 A ← B → C A\leftarrow B\rightarrow C ABC p ( a , b , c ) = p ( a ∣ b ) p ( c ∣ b ) p ( b ) p(a,b,c)=p(a|b)p(c|b)p(b) p(a,b,c)=p(ab)p(cb)p(b)

  • 我们求 p ( a , c ) p(a,c) p(a,c),如果 p ( a , c ) = p ( a ) p ( c ) p(a,c)=p(a)p(c) p(a,c)=p(a)p(c),则 A , C A,C A,C是在 B B B条件下独立分布:

    • B B B值不确定(未被观测),则:
      p ( a , c ) = ∑ b p ( a ∣ b ) p ( c ∣ b ) p ( b ) p(a,c)=\sum_{b}p(a|b)p(c|b)p(b) p(a,c)=bp(ab)p(cb)p(b)
      A , C A,C A,C不是在 B B B条件下独立分布。

    • B B B值确定,则可以知道 B B B取某个 b b b状态的概率为 p ( b ) p(b) p(b),则 b b b条件下 a , c a,c a,c发生的概率为:
      p ( a , c ∣ b ) = p ( a , b , c ) p ( b ) = p ( a ∣ b ) p ( c ∣ b ) p(a,c|b)=\frac{p(a,b,c)}{p(b)}=p(a|b)p(c|b) p(a,cb)=p(b)p(a,b,c)=p(ab)p(cb)
      满足条件独立。


20230317

  • 疲乏的一天。昨晚十二点回寝,今早八点半又要出门。一直搞到下午五点,终于把破事给摆平了。但是我并不高兴,因为这意味着似乎也没啥机会再跟黄名媛有啥交集。本来临走时候想问她晚上要不要一起出去吃个饭啥的,毕竟一起忙活近一个月,但是发现她一直跟一个昵称叫Lu’minous的vx好友在聊天(其实我早就有注意到,因为我一直想搞清楚到底是不是单身),而且我也疲惫得很,计划晚上九点多就要睡,明早还要赶高铁。想想真的太猴急,搞不好人家是异地恋,同在屋檐下,以后组会也躲不了要见面,闹得怪尴尬的。
  • 然后我发现今天二月廿四,sxy的农历生日。我之前是有想要不等她生日请她吃个饭,毕竟上学期结束一直欠着。但是今天肯定没指望,只能等到下周阳历生日看看情况,总觉得她最近看起来状态不是很好的样子。
  • 总之罢了,万事且等锡马结束,为了满足自己那点小心思(真的很可爱呀,可能是我阅历少,但这么多年来能用可爱形容的女生还真不多),这周已经把我这身老骨头都快整散架了。说到底春天是荷尔蒙爆发的季节,多少春心萌动。过了就好,过了就好,谈毛恋爱,省点精力它不香嘛。
  • 后来仔细研究了一下她的pyq,远比我想象的要精彩得多,确是异地恋,而且已经有几年了。散了散了,就当是一场梦呗,还好很快就醒了。

对于链式结构,具体可以用公式表达:

  • 首先根据 A → B → C A\rightarrow B\rightarrow C ABC p ( a , b , c ) = p ( a ) p ( b ∣ a ) p ( c ∣ b ) p(a,b,c)=p(a)p(b|a)p(c|b) p(a,b,c)=p(a)p(ba)p(cb)

  • 分两种情况:

    • B B B值不确定(未被观测),则:
      p ( a , c ) = p ( a ) ∑ b p ( b ∣ a ) p ( c ∣ b ) = p ( a ) p ( c ∣ a ) p(a,c)=p(a)\sum_{b}p(b|a)p(c|b)=p(a)p(c|a) p(a,c)=p(a)bp(ba)p(cb)=p(a)p(ca)
      A , C A,C A,C不是在 B B B条件下独立分布。

    • B B B值确定:
      p ( a , c ∣ b ) = p ( a , b , c ) p ( b ) = p ( a ) p ( b ∣ a ) p ( c ∣ b ) p ( b ) = p ( a ∣ b ) p ( c ∣ b ) p(a,c|b)=\frac{p(a,b,c)}{p(b)}=\frac{p(a)p(b|a)p(c|b)}{p(b)}=p(a|b)p(c|b) p(a,cb)=p(b)p(a,b,c)=p(b)p(a)p(ba)p(cb)=p(ab)p(cb)
      满足条件独立


20230318

  • 昨晚10点熄灯后心脏跳得厉害,锡马临近,也有因为窥探黄名媛pyq后的胃疼感。一直到快12点才着,5:30又醒,就再也睡不着了。到无锡后补了个下午觉,状态勉强回过来。短短半周失眠了两次,还是不同原因,也是服了我这老六。
  • 人呐,总是要在理想与现实间分清界限与寻求平衡,一旦逾越便会自讨苦吃。至少我应该庆幸,这半个多月的高压时光有人陪伴,久违的心动让我很享受,但这并不属于我,当以等价的痛苦来偿还。
  • 此页翻过。不管怎样,今天锡马报到的氛围真的太令人太兴奋啦,第一次有一种找到归属、那种跑者圣地的亲切感,许多严肃跑者,追求自己的极限。我本来立的FLAG是1:30:00,但又觉得太难,于是想到可以定1:31:40,均配刚好是4’20"/km,而且凑了个1314。
  • 终于,在我第3年的跑步生涯,我即将正式站在马拉松赛道,非常非常激动。多天来我收到了许多田径队朋友以及其他好友的加油,我热爱跑步以及它为我所带来的快乐与满足,尽管我也失去了许多。愿明天我能跑出自己的水平,在半马首战不留遗憾地圆梦,这是首战,或许也是my last war
  • 锡马,加油。

这首诗本是第一次失眠后作,现在看来似乎更适合第二次失眠后的心境吧。

《流年》
山隐水迢雾朦胧,扁舟一叶探萍踪。
无言何复凭栏意?嫣然回笑花正浓。
一梦一醒一夜终,一叹一咏一枯荣。
歌且不思情何往,但托遗念于悲风。

20230319

  • 昨晚只睡着了两个小时,一周失眠三天(昨晚单纯是兴奋),开跑时状态不佳,热身时明显感觉步伐沉重。但是气氛使然,勉强能有八九成气力,然而全浪费在前半程的变速穿插,前半程我跟打了鸡血似的,甚至飙出3’22"配速的分段,但是E组慢摇的人太多了,跟着跑是很轻松,但肯定出不了成绩。后半段明显乏力,但是总归还是成功完赛。
  • 晚上回来后再不能顶住,真的要好好睡一觉了。
  • 真的累了。

对于对撞结构,具体可以用公式表达:

  • 首先根据 A → B ← C A\rightarrow B\leftarrow C ABC p ( a , b , c ) = p ( a ) p ( c ) p ( b ∣ a , c ) p(a,b,c)=p(a)p(c)p(b|a,c) p(a,b,c)=p(a)p(c)p(ba,c)

  • 同样分两种情况讨论:

    • B B B不确定(未观测),由于所有 p ( b ∣ a , c ) p(b|a,c) p(ba,c)相加和为一,所以 p ( a , c ) = p ( a ) p ( c ) p(a,c)=p(a)p(c) p(a,c)=p(a)p(c),即条件独立

    • 否则 B B B给定,有:
      p ( a , c ∣ b ) = p ( a , b , c ) p ( b ) = p ( a ) p ( c ) p ( b ∣ a , c ) p ( c ) p(a,c|b)=\frac{p(a,b,c)}{p(b)}=\frac{p(a)p(c)p(b|a,c)}{p(c)} p(a,cb)=p(b)p(a,b,c)=p(c)p(a)p(c)p(ba,c)
      无法因式分解,因此不是条件独立。


20230320~20230321

  • 19号晚上回来后再起不能,这可能是这辈子以来最累的一天,出去找了点吃的回来就洗洗睡了,从11点睡到早上8点,完全是自然醒,舒服得要死,中午回来又补了2小时,原地满血复活。
  • 锡马净成绩1:42:07,跟预估差不多,半马人数8000,男子排名519,年龄段排名69,总排名601(算上女选手),排名差强人意,虽然比真实水平差了10分钟不止(稳进135,而且大概率能冲到130。142是三年前的水平)。
  • 约了sxy,三年了。再不约,可能就…,唉。

使用matplotlib制作mp4或gif动图:

from matplotlib import animation
from IPython.display import HTML
from matplotlib import pyplot as plt

def display_frames_to_video(frames):
    # figsize是以英寸为单位,dpi表示每英寸上多少个像素点
    plt.figure(figsize=(frames[0].shape[0] / 72, frames[0].shape[1] / 72), dpi=72) 
    plt.axis('off')
    patch = plt.imshow(frames[0])
    def animate(i):
        patch.set_data(frames[i])
    anim = animation.FuncAnimation(plt.gcf(), animate, frames=range(len(frames)), interval=50)
    # anim.save('cartpole.mp4')
    anim.save('cartpole.gif', writer='imagemagick')
    HTML(anim.to_jshtml())

display_frames_to_video(frames)

解释:fig是一开始定义好的图形对象(如plt.gcf()),关键是animate函数,这里的frames是一个列表,每个元素是一张RGB图像张量,这里只是简单的把每一帧给扔进patch,也有在一张静态图上不断移动一个点的写法:

import matplotlib.pyplot as plt
%matplotlib inline

line, = ax.plot([0.5], [2.5], marker='o', color='g', markersize=60)

from matplotlib import animation
from IPython.display import HTML

def init():
    line.set_data([], [])
    return (line, )

def animate(i):
    state = state_history[i]
    # 根据state确定点的移动坐标
    x = state % 3 + 0.5 
    y = 2.5 - state // 3
    line.set_data(x, y)

# 一秒5帧
anim = animation.FuncAnimation(fig, animate, init_func=init, 
                               frames=len(state_history), interval=200, repeat=False)
anim.save('maze_0.gif', writer='imagemagick')
HTML(anim.to_jshtml())

HTML可以在notebook里做出类似播放器的效果。


20230322

  • 阴雨绵绵,让人提不起兴致。下午四点多去操场准备养生一会儿。发现东哥居然在练3000米(五月底有个上海市教工运动会),这不趁机给东哥上个强度,穿牛仔裤也得给他好好拿捏一下。
  • 东哥目标进14分钟,带他跑出13’09",最后100米轻松绝杀。对我来说只是热身,而对东哥已是极限,只是可惜忘了给东哥来几张表情包。不过他下周还想进13分钟,机会有的是(ಡωಡ)。就怕到时候例训公报私仇,12×400米间歇给我直接干废哈哈。

最近发现一个很强的UP,五道口纳什,CSDN也有博客,全栈算工,真的是太全面了,啥都会,而且大多数面都要比我要精好多,所以准备把他的vlog全部学一遍,真的很有用。

使用meshgrid方法可以实现3D作图的坐标轴控制:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm

xs, ys = np.meshgrid(np.arange(-2, 2.01, .01), np.arange(-2, 2.01, .01))
zs = np.exp(-(xs**2+ys**2))

# xs: 401 × 401
# ys: 401 × 401

zs = np.exp(-(xs**2+ys**2)) # zs: 401 × 401

fig = plt.figure(figsize=(16, 12))
ax = fig.add_subplot(111, projection='3d')
surface = ax.plot_surface(xs, ys, zs, cmap=cm.jet)
fig.colorbar(surface)

另一种在jupyter里可交互的作图方式:

from mpl_toolkits.mplot3d import Axes3D
%matplotlib notebook

fig = plt.figure()
ax = Axes3D(fig)

xs, ys = np.meshgrid(np.arange(-2, 2.01, .01), np.arange(-2, 2.01, .01))

# creating the plot
surface = ax.plot_surface(xs, ys, zs, color='green', cmap=plt.get_cmap('rainbow'))

# setting title and labels
ax.set_title("3D plot")
ax.set_xlabel('x-axis')
ax.set_ylabel('y-axis')
ax.set_zlabel('z-axis')
fig.colorbar(surface)
# displaying the plot
plt.show()

20230323

  • 晚上例训。3000米乳酸阈跑(with嘉伟,11分整,中途要停一圈,这已经是我的极限了,自测3000米最快能到11’30",今天第一个1000米就被带到3’30",力不能及)+ 3000米放松跑(with东哥,13’39",东哥说他五年前能跑到9’08",超二级水平,太恐怖了,没想到现在垮得这么厉害)+ 2000米追逐+ 2000米冷身,外加4组箭步跳和蛙跳。
  • 锡马回来后四天在循序渐进地恢复,现在左胯仍抽痛,用力压会疼,其他地方都已经完全恢复,最近休息得很好,虽然没有拉强度,但是应该状态已经恢复到巅峰了,下周队内会有一次体测,争取把5000米再次跑进20分钟。
  • 嘉伟周日要去芜湖跑半马,本来卢星雨是芜湖人,可惜她也垮得很,说可以租个儿子去跑亲子欢乐跑,TM笑死。
  • 看了一下栾云平的无锡专场,便宜的位置都卖光了,剩余最低580,90分钟一场确实挺贵滴,小园子倒是便宜得多。因为我一直在想要不要送个生日礼物,或许搞个票是不错的选择,但莫名感觉sxy会不会已非单身。害,庸人自扰。

制作2048的环境,以及pygame渲染:

# -*- coding: utf-8 -*-
# @author : caoyang
# @email: caoyang@163.sufe.edu

import numpy
import random

from copy import deepcopy

class Env2048:
	initialize_proba_for_2 = .9	# Each round with some probability to generate tile 2 at random position
	n_initial_tile = 2			# The number of initial tiles in the start
	score = 0					# Log the game score
	actions = list(range(4))	# {0, 1, 2, 3} -> {U, R, D, L}
	
	def __init__(self, args, is_debug=False):
		self.args = deepcopy(args)
		self.is_debug = is_debug
		self.reset()

	# Restart game
	def reset(self):
		self.grid = numpy.zeros((self.args.order, self.args.order)).astype(numpy.int16)
		for _ in range(2):
			self.add_tile()
		self.mode = 'run'

	# Step to next state with some action
	def step(self, action):
		if self.mode in ['over', 'win']:
			return
		grid = self.grid.copy() if self.is_debug else self.grid
		score = 0
		if action == 0:
			# Upward 0
			for i in range(self.args.order):
				score += self.merge_bar(bar=grid[:, i])
		elif action == 1:
			# Rightwards 1
			for i in range(self.args.order):
				score += self.merge_bar(bar=grid[i, ::-1])
		elif action == 2:
			# Downward 2
			for i in range(self.args.order):
				score += self.merge_bar(bar=grid[::-1, i])
		elif action == 3:
			# Leftwards 3
			for i in range(self.args.order):
				score += self.merge_bar(bar=grid[i, :])
		if self.is_over():
			self.mode = 'over'
		if self.is_win():
			self.mode = 'win'
		self.add_tile()
		self.score += score
		return score

	# Sample the position of some empty tile 
	def sample_available_position(self):
		available_positions = list()
		for x in range(self.args.order):
			for y in range(self.args.order):
				if self.grid[y, x] == 0:
					available_positions.append((y, x))
		# assert available_positions, f'There is no empty tiles in grid: {self.grid}'
		return random.choice(available_positions) if available_positions else None

	# Randomly add 1 tile to grid
	def add_tile(self):
		position = self.sample_available_position()
		if position is not None:
			y, x = position
			self.grid[y, x] = 2 if random.random() < self.initialize_proba_for_2 else 4

	# Move one row or one column for merging
	def merge_bar(self, bar):
		score = 0
		bar_length = len(bar)
		for i in range(bar_length - 1):
			if bar[i] == 0:
				for j in range(i + 1, bar_length):
					if not bar[j] == 0:
						bar[i] = bar[j]
						bar[j] = 0
						score += 1
						break
			if bar[i] == 0:
				break
			for j in range(i + 1, bar_length):
				if bar[j] == bar[i]:
					bar[i] += bar[j]
					score += bar[j]
					bar[j] = 0
					break
				if not bar[j] == 0:
					break
		return score

	# Whether is game over
	def is_over(self):
		if 0 in self.grid:
			# There exist some empty tiles in grid
			return False
		for y in range(self.args.order - 1):
			for x in range(self.args.order - 1):
				# There exist some ways to merge tiles
				if self.grid[y][x] == self.grid[y][x + 1] or self.grid[y][x] == self.grid[y + 1][x]:
					return False
		return True

	# Whether is game wins
	def is_win(self):
		return self.args.game_goal in self.grid

	# Stringize
	def __str__(self):
		string = '====================\n'
		for row in self.grid:
			string += '-' * (5 * self.args.order + 1) + '\n'
			for e in row:
				string += '|{:4d}'.format(int(e))
			string += '|\n'
		string += '-' * (5 * self.args.order + 1) + '\n'
		string += '==================\n'
		return string


20230324~20230325

  • 春寒料峭,昨天状态又极度低迷,感觉这几天衣服穿太少给冻着了,有点发烧的征兆,早早睡了一觉又基本恢复过来了。
  • 下午例训,全员8×400米间歇,状态不错,能1’15"~1’20"的pace坚持到底,没有不适,最后两组甚至跑到前三,仅次于杨申宇和宋镇均(不得不说宋镇均的话一个标点不能信,第3组跑完跟我说上头了,让我站他前面出发,然后每组都超我,一点不给老学长面子)。再跟队练三周到扬马结束,至少进个135,了却这桩心愿。
  • 找工作确是玄学,尤其是近两年,但无论如何,sxy都确是足够优秀了,实话令人艳羡不已,能去中金真的已是天花板。与三年前很像,不过今天我是听众,熟悉的清澈,褪去了些青涩,多了些岁月的蹉跎,以及恍惚间的落差。好多话没能说出口,也不知道两年后我会何去何从,以后还能否再见。然,人生能有这么一段三年多的邂逅,cy,你也该知足了罢。

2048蒙特卡洛代理,利用两个经典的指标进行:

class MonteCarloAgent(BaseAgent):
	gamma = 2.8
	def __init__(self, args):
		super(MonteCarloAgent, self).__init__(args)
		self.env = Env2048(self.args, is_debug=False)
		
	# Generate the next action given grid state
	def generate_next_action(self, grid):
		action_grades = []
		n_empty_tiles = self.count_empty_tiles(grid)
		if n_empty_tiles >= self.args.order ** 2 / 3:
			# There exist so many empty tiles that we can act randomly
			if self.args.gather_to_corner == 'ul':
				return random.choice([0, 3]), {'grade': 0}
			elif self.args.gather_to_corner == 'ur':
				return random.choice([0, 1]), {'grade': 0}
			elif self.args.gather_to_corner == 'dl':
				return random.choice([2, 3]), {'grade': 0}
			elif self.args.gather_to_corner == 'dr':
				return random.choice([1, 2]), {'grade': 0}
		# Simulate
		n_simulate = min(max(n_empty_tiles ** 2, 20), 40)
		for action_list in itertools.product(self.env.actions, repeat=self.args.montecarlo_search_depth):
			candidate_grades = []
			for _ in range(n_simulate):
				grid_final = self.generate_simulated_grid(grid, action_list)
				candidate_grades.append(self.grade_grid(grid_final))
			action_grades.append([action_list, min(candidate_grades)])
		action_grades = sorted(action_grades, key=(lambda x: [x[1]]))
		for action_list, grade in action_grades[::-1]:
			self.env.grid = grid.copy()
			if not self.env.step(action_list[0]) == 0:
				# Return the first action in sorted actions list by grade
				return action_list[0], {'grade': grade / n_simulate}
		# Revert
		self.env.grid = grid.copy()
		return action_grades[-1][0][0], {'grade': action_grades[-1][1] / n_simulate}

	# Generate the final grid given a grid and a list of simulated actions
	def generate_simulated_grid(self, grid, action_list):
		env = Env2048(self.args, is_debug=False)
		env.grid = grid.copy()
		for action in action_list:
			env.step(action)
			env.add_tile()
		return env.grid

	# Grade the current grid 
	def grade_grid(self, grid):
		return self.grade_algorithm_1(grid) + self.gamma * self.grade_algorithm_2(grid)

	# Count the number of empty tiles in grid
	def count_empty_tiles(self, grid):
		return numpy.sum(grid == 0)

20230326~20230327

  • 昨日休整,去小姨家养了波胃。前晚肚子不适,不知是九鼎轩东西不干净还是一回来就跑高强度间歇的缘故,总之就是不舒服。陈嘉伟首半马顺利完赛,净成绩1:28:26,配速4’11",这还不是完全发挥出来的水平。半马跟嘉伟的差距要小一些,配速差大概在15秒。
  • 注册openai账号,打不过就加入呗,openai还不给china和russia提供服务,买了个巴西的虚拟号码才验证通过,梯子又不稳,凌晨搞到一点才弄好。
  • 主要是近半个月很多大模型的api都开放了,所以上周主要在追踪前沿,如提示工程,图像的diffusion之类的。其实prompt很早就有提出,那时候还以为只是简单的补全,现在看来真的是坐井观天。LLM和Prompt,这是方法论和工业应用的双重革新,有预感大变革真的要来了。
  • 下午晃了十圈,碰到宋镇均在自测5000米,结果这货少跑了一圈,18’32",亏我还长袖长裤、而且没热身就带了他两段。可惜明天临时要汇报,估计要错过队内测试,这么好的状态多想能重开一次20分大关。(说起来一年半前还打开一次20分钟,自己这么久就一点长进都没有,好菜)。

LLM与提示工程之遐想

其实现在看来提示学习的确是革新了传统的预训练方法,那些传统的预训练模型可能很快就要被淘汰,GPT崛起说明预训练根本不需要搞那么多花里胡哨地操作,做自回归就完事了,有种数学里常说的朴素简洁的美。

关于提示,几乎已经可以覆盖所有的NLP任务,虽说现在提示工程看似只是在对一个黑盒子进行不断地试错,没有什么理论依据可言,之前王英林坚持不肯在本子里写提示学习,就是觉得这种东西没有什么科研价值,就一群人在那儿写模板喂给模型,而且很多时候还需要人类来对模型的输出进行反馈。但是从另一个角度来看,提示工程有点类似在对人脑的思维逻辑进行解析,事实上我们也没有办法完全弄明白人脑的运行逻辑,所以提示工程里有很多提示构建的思路,比如思维链(CoT),ReAct,以及生成外部知识模板,甚至将逻辑用代码形式进行提示,其实都是在帮助模型学习推理的能力,但是这种推理能力并不是结构化的,它依然是非结构化的文本组成,你很难说模型到底学习到的是推理能力,还是只是以文本形式呈现的推理过程,抑或说本身推理确实也可以是非结构化的呢,只是人类更偏爱使用结构化的推理形式而已?

这波冲击对NLP是及其巨大,但是随着多模态提示的发展,图像领域可以预见到的很快也会受到冲击,其实diffusion作为一种MC也可以理解是一种自回归,这和文本预训练上的思路是一致的。其实我一开始以为diffusion是以像素点级别进行自回归扩散的,当时觉得这个思路好神奇,但是并不是这么做的,为什么不是这么做呢?比如对于图像补全,感觉上以像素点进行自回归扩散更合理,OR里面会用nuclear norm来进行优化实现图像补全,本身也是基于熵减的思想。

openai补全接口调用:

import openai
import os
import Ipython
from langchain.llms import OpenAI
from dotenv import load_dotenv

load_dotenv()

openai.api_key = os.getenv("OPENAI_KEY")

os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_KEY")
os.environ["SERPART_API_KEY"] = os.getenv("SERPART_API_KEY")

def set_open_params(model='text-davinci-003',
                    temperature=.7,
                    max_tokens=256,
                    top_p=1,
                    frequency_penalty=0,
                    presence_penalty=0):
    openai_params = {}
    openai_params['model'] = model
    openai_params['temperature'] = temperature
    openai_params['max_tokens'] = max_tokens
    openai_params['top_p'] = top_p
    openai_params['frequency_penalty'] = frequency_penalty
    openai_params['presence_penalty'] = presence_penalty
    return openai_params

def get_completion(params, prompt):
    response = openai.Completion.create(engine=params['model'], 
                                        prompt=prompt,
                                        temperature=params['temperature'],
                                        max_tokens=params['max_tokens'],
                                        top_p=params['top_p'],
                                        frequency_penalty-params['frequency_penalty'],
                                        presence_penalty-params['presence_penalty'])

20230328

  • 下午组会,错过训练(事后碰到谢震宇问了下,其实东哥根本没来,就没咋练,还好还好,主要状态是挺好,练不了有点可惜)。两天不到把锡马回来一周多看的东西整出来并讲了一遍,颇有所得,从gpt1到gpt4,再到提示工程的技术,以及这个月刚刚开放的各种OpenAI接口,做了一回LLM和AIGC的传教者。从我的角度来说,LLM和AIGC的到来确是令人激动的事情。虽然我们还不能直接无代价的接触到LLM,但只是摸到一点皮毛也足以令人兴奋。
  • 会后跟黄名媛回实验楼,在看暑期实习,跟我说加了颜烨,然后这B居然让她去投开发岗,是真TM离谱,颜烨这是人做出来的事儿?
  • 21级的时候就来了一个黄名媛,我过了差不多快一年才看到真人。今年进了4个,而且居然有个直博新生,我都以为王英林要退休了,居然还要带博士,这可至少五年,到时候都快70岁。
  • 晚上强行想认真跑会儿,之后可能要连着下雨。虽然下午感觉很好,但是到晚上毕竟还是太累了,没睡午觉状态又差,奔着10km去跑结果不到2km就报销了,又断断续续补到5km,说起来还是在扬马备赛期,不论配速,每天还是要把跑量补足。

LLM与提示工程之遐想(二)

提示工程指南:GitHub高星项目

如果说GPT4真就只靠无监督的自回归训练+多任务微调那确实太夸张了,它的训练过程中一定有很多细节没有公开,否则很难想象text-to-SQL以及代码生成等公认的高难度NLP任务就这么被一个说不清道不明的in-context learning一举拿下了。以Text-to-SQL著名的Spider挑战任务为例,上个月刚提出的SOTA模型也超过不了80%的正确率,根本不足以达到应用范畴,但是事实上这也不能在GPT4中测试,因为context太长,除非把Spider的整个数据库扔进去。

即便如此,正如昨天写到的那样,以提示为起点,自回归为方法的LLM&AIGC新方法,抛却了一切花里胡哨的结构化操作,确是一种简单朴素的美。以前总是认为规则、推理是需要用结构化的方式进行表达,比如一阶规则,现在看来自然语言几乎可以概括一切规则。不管你信不信这是不是推理能力,反正LLM就是能推出来。

最后推荐几个图像领域的,从GPT4开始已经可以进行提示生图的操作了,当然这些技术半年前就已经很成熟了,AI绘图早已不是,这么看来,图像还是要比文本要容易一些。我以前也是这么认为,因为文本的精确性要求更高,图像还是有一定容错的。https://civitai,Diffusion公式推导

Image Caption(调用Blip模型):

import torch
from transformers import BlipProcessor, BlipForConditionalGeneration
from PIL import Image

device = 'cuda:0'

processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-base")
model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image-captioning-base", torch_dtype=torch.float16).to(device)

# processor forward,模型的输入需要经过processor进行预处理
img_inputs = processor([Image.open('./flickr8r-samples/33108590_d685bfe51c.jpg'), 
                        Image.open('./flickr8r-samples/10815824_2997e03d76.jpg')], 
                       return_tensors='pt').to(device, torch.float16)

print(img_inputs['pixel_values'].shape)

out = model.generate(**img_inputs) # 输出结果是一个LongTensor

# 需要用processor解码
# processor.tokenizer.convert_ids_to_tokens(out[0])
captions = processor.decode(out[0], skip_special_tokens=True)
print(captions)
captions = processor.decode(out[1], skip_special_tokens=True)
print(captions)

20230329

  • 开始面实习,早上做阿里的行测,智商严重受辱,拿各种小学数学应用,阅读理解还有离谱的图形规律来恶心人。后晚要电面,因为是数算岗,跟近期看的内容不搭嘎,又得刷算法题准备机考,以及把之前写的pyspark和hadoop笔记拿出来复习。就是那种,想、又不想实习的矛盾感。
  • 晚饭后准备去操场散会儿步,路上碰见东哥刚练完,告诉我本来上周六3000米已经跑到12’49",结果三天不练又被打回原形。然后卢星雨和丁古丽也在慢跑,想想我也有好几天没有认真跑了,之后又要下雨,晚上状态虽低迷,还是换了衣服鞋子上场拉一拉强度,4000米用时16’04",配速4’01",马马虎虎。
  • 说起来,这学期若不是有嘉伟带,我很难两周就重回巅峰。非例训时间里,我一个人训练很难上大强度。以前习惯独自训练,一周也能跑出7个高质量的万米,现在变得越来越依赖随队氛围,就是那种被人认同也认同别人的氛围。然,越是依赖,越是遗憾,早晚会离开这样的欢乐与纯粹。聚少离多,能陪伴一生的人和物是何等的无价珍宝呢。

Legion笔记本,摄像头灯亮,但是显示黑屏问题解决:

摄像头的盖子没掀开阿,如果你发现摄像头最中间是一个红点,那就是被盖住了,看看摄像头上方有个很不起眼的像是滑槽(可以左右滑)的东西,往右边一滑就开了。TM下午搞了半小时,还以为是摄像头驱动坏了,差点准备卸了驱动重装,真是服了。

就特别搞,看网上说联想笔记本摄像头是有物理开关的,我还在想是不是右边那个小孔是开关,用针捅了半天旁边兄弟跟我说那应该是麦克风,我???

更多推荐

【更新】囚生CYの备忘录(20230216~)