遇到+容易忘的各种问题记录
2023/03/28
才知道,pytorch里的torch.Tensor是默认Float。torch.tensor才可以设置dtype
前段时间记录的一些内容:
- lmdb close readonly:多进程只读的时候要设置readonly=True,lock=False
- mp.Pool在一个Dataset里没法去做多进程,因为会有self参数的传入。在外部可以。initargs中因为每个是单独的进程,所以可以用global。可以在init里让每个进程有独立的数据库连接
- np.max和np.sum,前者会慢一些,因为是条件选择
- gpu和cpu的计算精度不同,cpu是double gpu是float。所以模型放到gpu上计算出来的数据可能会有不同。
- 教训:一定要跑下源代码看下效果
- 发现向collate_fn传参的方式:pytorch中collate_fn函数的使用&如何向collate_fn函数传参。我之前一直以为没法传参。。= =。
- 教训:一定要做模块测试。不然debug很想死。
__file__
可以读取当前py文件名- os.path的各种函数:
join
,relpath
,dirname
,abspath
。创建文件夹os.makedirs
- 好看地输出json,加
indent=2
:
with open(os.path.join(params.exp_dir, "params.json"), 'w') as fout:
json.dump(vars(params), fout, indent=2)
- debug卡死的时候看下是不是多进程num_workers不是0了
- torch的squeeze如果不加参数会把所有的都squeeze了
import torch
a = torch.Tensor([[1]])
b = torch.Tensor([[1, 2]])
aa = a.squeeze()
aaa = a.squeeze(0)
bb = b.squeeze()
bbb = b.squeeze(0)
print(aa, aaa) # tensor(1.) tensor([1.])
print(bb, bbb) # tensor([1., 2.]) tensor([1., 2.])
比如上面这个代码,aa的结果是单个数值了
- numpy中两个矩阵比较是否相等不可以用
==
。==
比较的是每个位置上的值然后返回True/False的矩阵。所以如果要比较ab两个矩阵是否全部相等(a==b).all()
,比较ab两个矩阵至少有一个元素相等(a==b).any()
2023/03/30
- 使用tqdm的时候发现一个问题:当前处理的三元组是第462个,但是bug终止后显示界面是456、460等各种情况。所以不能根据tqdm最后控制台显示的数据判断当前在处理第几个数据。一定要用enumerate来看。
2023/03/31
- pickle存储ndarray报错
TypeError: a bytes-like object is required, not '_io.BufferedReader'
最终做法:
import pickle
with open('a.txt', "wb") as f:
pickle.dump(split['pos'], f)
with open('a.txt', "rb") as f:
f = f.read()
ans = pickle.loads(f)
- collate_fn常用的代码,用于把输入数据整成一列一列:
def collate_fn(self, samples):
# The input `samples` is a list of pairs
graphs_pos, g_labels_pos, r_labels_pos = map(list, zip(*samples))
- dgl的几个属性获得
节点/边个数:g.number_of_nodes()
,g.number_of_edges()
ndata/edata_schemes:g.node_attr_schemes()
,g1.edge_attr_schemes()
节点/边:g.nodes()
,g.edges()
- 比较dgl对象。因为dgl不能直接通过
==
来比较,也不能像numpy一样用(array1==array2).all()
比较,所以只能单独比较里面的所有元素:
assert g1.node_attr_schemes() == g2.node_attr_schemes() # map 比较
assert g1.edge_attr_schemes() == g2.edge_attr_schemes()
def same(t1, t2):
return (t1 == t2).cpu().detach().numpy().all() # tensor比较 转换为numpy
assert same(g1.nodes(), g2.nodes())
assert same(g1.edges()[0], g2.edges()[0])
assert same(g1.edges()[1], g2.edges()[1])
- pycharm自动生成函数注释:Settings->Tools->Python Integrated Tools->Docstrings,常选reStructuredText
- 模块测试报错:
python: __main__ is not a package
,是因为用了相对应用.xxxpackage
,但是.
代表的就是__main__
此外,常用的确保当前文件是执行文件的代码是if __name__ == '__main__':
- 对lmdb的env下的数据读取做了个测试:
情况1:每次读取都open/close env
情况2:打开一个env,后面全部读取,最后关闭
测试数据是读100000条dict信息,时间对比是:10s vs 0.45 s
因此可见 open close很耗时
2023/04/01
- 在看rank里的一个常见代码:
rank = np.argwhere(np.argsort(curr_scores)[::-1] == 0) + 1
y=np.argsort(x)
是对x从小到大排序后的下标,此时x[y[0]]是x里最小的数;但是目标是找score最大的,所以通过[::-1]
倒序,此时x[y[0]]是x里最大的数
np.argwhere(x)
是找x里非零元素的下标
2023/04/03
- batch_size不同带来的测试变化,可能有没关BN层/padding不同/dropout层/还在训练 等原因。这次遇到的是BatchedDGLGraph。。。。会把一个批次的dgl图合成一个BatchedDGLGraph。。。。无语了。
- 测试的时候是否该关了dropout?。用
model.eval()
就可以了。但是我看有的人说不要关,因为会导致训练和测试的模型不一样;有的人说要关,因为需要保证模型的稳定性。
使用dropout是因为,参数过多带来 过拟合+训练慢 的现象,所以可以丢掉一些参数。在前向传播的时候,让某个神经元的激活值以一定的概率p失效,泛化性更好,因为不会太依赖某些局部的特征。
还有一个eval不一定能关掉dropout的天坑。。
后续[2023/04/04]问了下师兄,一般是要关掉nn.Dropout的,但是用eval就可以了
2023/04/04
- 遇到一个bug,在
y=x1矩阵乘x2
的情况下,y[:7]==x1[:7]矩阵乘x2[:7]
可能不成立,在毕设代码中发现的,后续在本地windows系统上做了一个实现,随机生成了22x32和32x32的float32矩阵,然后检查了上述情况,发现在取比较小的矩阵的时候比如[:3]就不会出错,但是大了就错;但是后续发现在服务器上运行、同学在linux系统上运行都不会有问题,只有在windows系统上出问题;但是我的毕设代码是放在服务器上跑的。。目前问题不知道是怎么造成的。把问题抛给师兄了。。。 - 关于dgl中的
update_all
中的前两个参数message_func
和。去年年底已经看懂了,今年看的时候又全忘了。。很懵
message_func
是返回每条边的信息,输入是一个EdgeBatch,是当前图g内的所有节点,返回需要返回一个字典,字典内是每条边的属性值,比如{'h':h,'feat':feat},h和feat应该是(edge_num, dim)的大小,确保每条边都有属性。
reduce_func
,GraIL代码里是是返回了一个nn.Module:Aggregator,forward的接收参数是node,是一个NodeBatch,官网的说法是接收同一群节点的node们。我画图理解了下,应该是指有相同邻居集合的一批节点们。比如有如下边:
1->4,2->4
1->5,2->5,3->5
1->6,2->6,3->6
易得56两个点有相同的邻居集合,那么56构成一个NodeBatch,而4的邻居是{1,2}不是{1,2,3},所以4是单独的一个NodeBatch。
node可以通过mailbox获得邻居传来的信息,比如node.mailbox['h],上述node是{5,6}的时候h的大小就是(2,3,dim),2是NodeBatch里的节点个数,3是邻居集合里邻居的个数。所以node.mailbox['h'][i,j,:]表示的就是当前NodeBatch里节点i的j邻居传过来的信息。
2023/04/05
- 突然理解了一行一直不理解的代码!
return g.ndata.pop('h')
。GraIL里我去年一直不理解为什么要pop掉然后在模型框架里重新接收。然后刚刚从师兄那知道,大多数表示学习的输入emb是可学习的,上一个epoch的训练结果数据可以用到下一epoch。
2023/04/06
- ccproxy问题,记得在HTTP/RSTP协议右边的ip也填上校园网的ip,不然虽然能连上本机但是还是连不了网
- pip报错
Cannot uninstall 'certifi'. It is a distutils installed project and thus we cannot accurately determine ...
。直接安装:pip install xxx --ignore-installed
2023/04/12
- 把分数映射到01区间,可以用softmax和sigmoid。二分类的时候softmax和sigmoid是一样的,sigmoid是特殊的softmax。如果正负样本不是1:1,推荐用sigmoid。
2023/04/17
- debug遇到报错:
unable to get repr for <class 'dgl.frame.Frame'>
和{DGLError}Invalid edge ID 4861
,没有搜到结果,但是有人说换成cpu,因为gpu可能不会显示真实错误。但是,鹅,我换了还是显示不了错误。。。
Heterogeneous Graph 异构图,可以有不同类型的节点和边,具有独立的ID空间和特征。
后续debug后发现,从一个异构图里抽取子图的时候会获得EID和NID,但是之后这个就不会变了;对于合并起来的图这个ID是没有效果的。因此我每次抽取之后重构EID和NID的数据:
@staticmethod
def reconstructID(subgraph):
if subgraph is not None:
subgraph.edata[dgl.EID] = torch.tensor(range(len(subgraph.edges()[0])), dtype=torch.long)
subgraph.ndata[dgl.NID] = torch.tensor(range(len(subgraph.nodes())), dtype=torch.long)
最后发现还是有点问题,在aggregator的传播部分抽取到的nodebatch是不一样的,目前不知道为什么;但是我发现可以直接不要_ID
这个东西。。解决一切。。。
@staticmethod
def reconstructID(subgraph):
if subgraph is not None:
if subgraph.ndata.get(dgl.NID) is not None:
subgraph.ndata.pop(dgl.NID)
if subgraph.edata.get(dgl.EID) is not None:
subgraph.edata.pop(dgl.EID)
- 比较两份代码参数都初始化为固定值后还是不一样:因为只记得固定weight但是忘了固定bias。。
2023/04/20
- 学习了装饰器,感觉有点好使。
类内装饰器:
def decorator_valid(function):
def decorated(self, *args, **kwargs):
self.model.eval()
data = function(self, *args, **kwargs)
self.model.train()
return data
return decorated
如果不要类内的,把decorated和function函数里的self参数删掉就可以了。
2023/04/27
- debug比较两个对象,pycharm里debug变量直接复制然后右键比较。为了统一比较,直接统一初始化变量:
nn.init.constant(m.weight, 1)
2023/05/05
- 过滤负三元组容易错的问题。①正确三元组不能过滤掉,label是False!②算auc的时候记得正确三元组的label是True!
2023/05/17
- 在bash里通过sed传参,修改properties文件的内容:
sed -i 's/^PATH_TRAINING=.*/PATH_TRAINING='${PATH_TRAINING//"/"/"\/"}'/' $PROP
sed -i 's/name=.*/name='${VARIABLE}'/' output.txt
注意!sed命令里无法识别/
,所以需要转义为\/
。
- 在bash里对一个字符串变量替换内容:
${VARIABLE/"a"/"b"}
${VARIABLE//"a"/"b"}
第一行表示把第一个字符a修改为b,第二行表示把所有的a修改为b。
2023/07/25
- 路径函数:
找到当前路径相对于某个文件的路径(比如根目录):
- 先通过
os.getcwd()
得到当前py的的绝对路径 - 通过
os.path.relpath(os.getcwd(), 'src')
得到当前py相对于src的路径
2023/07/28
- 安装环境报错:
You may need to close and restart your shell after running 'conda init'
解决方式:用source activate env_name
而不是conda activate env_name
- 安装环境报错:
PackagesNotFoundError: The following packages are not available from current channels
解决方式:进入环境后搜索可用的包,conda search -f package_name
- 安装环境:指定环境下载
比如conda install -c conda-forge package_name
,c是channel的缩写,意思是从https://anaconda.org/conda-forge
里下载该包
完整写法就是conda install --channel https://conda.anaconda.org/conda-forge package_name
- 安装环境报错:conda search找到包后install报错找不到包
解决方式:conda config --set offline false
。参考链接
还有建议用mamba的,但是问题是我用conda也安不上mamba。。
后续:因为是在autodl上找的服务器,所以要按帮助文档做一下部分事情。。我没做。。所以安装环境报错。。参考链接
2023/09/15
- python url下载github上的资源报错:
http.client.RemoteDisconnected: Remote end closed connection without response
。
尝试了一些方式无果。然后看到下载的url是https
开头的。
电光火石间,突然想到我的.bashrc文件和.condarc文件里的https的代理都是http开头的,所以协议没对上。
解决方式:代理改成https开头的就能下了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具