在Julia中使用元编程技术实现GR后端多个子图绘制

文章目录

  • 遇到的问题
  • 知识点:Julia中的元编程
  • 最终的解决方案
  • 最后的吐槽

遇到的问题

最近在试图使用Julia语言来完成*吴恩达《机器学习》*的课后习题,进行到exercise3时,想要仿照这里对数据实现以下的可视化效果:
在Julia中使用元编程技术实现GR后端多个子图绘制_第1张图片
对于每一个子图,只需使用Plots.heatmap()函数来绘制即可。但怎么才能绘制多个子图呢?
如果使用pyplot作为Plots的后端(backend),则相对比较容易,最明显的方法是在循环中逐一使用subplot()函数即可,但我无法成功安装PyPlot包,其依赖包ORCA一build就出错!我只能用成功编译了的GR包作为后端!但翻了翻Plots的官方文档中有关GR的部分,我却没找到能便捷绘制许多个子图的命令(也可能是我没有细致查阅吧)!如果我要实现一个5*5的子图集,一个比较繁琐的方式是:

p1=heatmap(...)
p2=heatmap(...)
...
p25=heatmap(...)
plot(p1,p2,...,p25,layout=(5,5))

这是要写到猴年马月去了!而且蠢到家了!
但是上述语句有一个特点:相似性很高,所以可以考虑使用元编程+循环的形式来精简代码。

知识点:Julia中的元编程

这里不作过多的介绍,我只使用其中两个简单的函数:eval()Meta.parse()

  • eval(expr):Evaluate an expression in the global scope of the containing module.
  • Meta.parse():Parse the expression string and return an expression (which could later be passed to eval for execution).

简单的用例如下:

Meta.parse("x=3")  # 返回一个Expression:`:(x = 3)`,注意`:`是Symbol类型的标识符
eval(Meta.parse("x=3"))
println(x)  # 返回3,说明上式执行了x=3的语句

下面假设我要生成100个变量,分别命名为x1,x2,...,x100,且想让它们分别等于1,2,...,100,就可以这样写:

for i in 1:100
	eval(Meta.parse("x$i=$i"))
end
println(x49)  # 返回49

仿照此例,最终的解决方案呼之欲出!

最终的解决方案

涉及了Julia的元编程+循环+字符串拼接

# 准备阶段:数据读入
using MAT
dict=matread("ex3data1.mat")
size(dict["X"]),size(dict["y"])  # ((5000, 400), (5000, 1))

# 数据可视化
using Plots;gr()
function show_one_img()
    i=rand(1:size(dict["X"],1),1)
    s=dict["X"][i,:]
    s=reverse(reshape(s,(20,20)),dims=1)  # 每个样本都是20*20的灰度图
    return heatmap(s,colorbar=:none)
end
show_one_img()  # 重复几次看看
str_ps=""
for i in 1:25
    eval(Meta.parse("p$i=show_one_img()"))
    global str_ps *= "p$i,"  # 注意:julia的字符串拼接符是*,而非+
end
println(str_ps)  # p1,p2,p3,p4,...,p22,p23,p24,p25,
eval(Meta.parse("plot(" * str_ps * "layout=(5,5))"))

最终的成品图如下:
在Julia中使用元编程技术实现GR后端多个子图绘制_第2张图片
以上。

最后的吐槽

求求了,哪家机构搭建个Julia包的国内镜像吧!

你可能感兴趣的:(机器学习,可视化,机器学习)