-
样条线怎么挤出平面_【Revit Vs Blender】新手实战项目 两种方法做一个建筑平面三维图【下篇Blender】...
2020-12-19 01:24:27【前言】本篇还没有做完,还剩摆放小物件啥的,那都是次要的事情,都是体力活,随后再添加,诸君且先看吧。个人觉得UE4世界大纲的选择隐藏模式可以向Blender好好学学,参见本文第五节和第十节,这样直接在UE4中建模...【前言】
本篇还没有做完,还剩摆放小物件啥的,那都是次要的事情,都是体力活,随后再添加,诸君且先看吧。
个人觉得UE4世界大纲的选择隐藏模式可以向Blender好好学学,参见本文第五节和第十节,这样直接在UE4中建模也不是没有可能。
【导图】
一、导出DXF格式图纸
- 从Revit中直接导出DXF格式的图纸
- CAD的话,直接W write block写块导出DXF
如下,这是要导出的图纸
二、Blender中勾选自带DXF插件
Ctrl+N新建项目,General。
这里也是直接可以访问到偏好设置的,不至于每次老到Edit中去找。
勾选导入导出DXF格式插件
可以看到支持导入啦
我们还可以直接在其上右键自定义导入DXF图纸快捷键,不至于每回都得跑到偏好设置中去改,很方便哒~
三、导入图纸
- 先A X 删除默认Cube和Camera
- 然后Ctrl+E 导入
3.可以复制文件夹路径后,添加路径到喜爱中,就跟Windows的Quick Access一样,可以实现快速访问啦~
4.导入,默认选项,灯光文字啥的,全部默认。
5.可以看到,导入进来就只有两种类型,文字和Curve,正好。
12 6.导入进来后,我们可能看不见图纸,那是因为Curve/Text的距离太远了,我们可以改动Clip Start /End调节视野范围 或者是更改项目单位
~ 切换到顶视图,更多Blender快捷键可以看这篇文章。
X Tesla:【Blender】快捷键大全(超级详细,应有尽有,不断更新)zhuanlan.zhihu.com或者是直接改项目单位,公制,缩放0.1倍,这样clip 就不需要改动了。
四、文字/Curve调试
由于Blender本身不支持中文字体,当然可以从外面复制粘贴进去,所以只会有英文字体显示
复制粘贴的话,别忘了是要Tab进Edit Mode 从Edit这里点击粘贴,或Ctrl+V粘贴。
而且还要更改字体,如微软雅黑,否则字体显示不出来。
其实说白了,文字和Curve都是一种曲线,我们都可以对图纸中的文字或Curve进行挤出或Bevel操作。
我们甚至可以直接选中外墙体曲线,通过挤出和倒角的协同配合,来制造墙体(厚度图纸已经画好了,所以不用管),之后Curve To Mesh转化为三维模型即可
五、显示选择相关
Z切换渲染模式,固态、渲染、材质、网格。固态可选法线Shading,这样在旋转相机视角的时候,可以很清楚地看到哪些面是垂直、倾斜的。
世界大纲中默认的只有小眼睛来控制Visibility的。
我们还可以选其他的,如选择、显示、渲染等
这样在顶视图中的话,可以只框选我们想要的模型,其他设置为不能被选择。
- H 隐藏
- Alt+H 取消全部隐藏(后面的那个小电脑如果是灰显的话,就一直是隐藏状态,Alt+H针对小眼睛的)
- Shift+H 隐藏没有选中的
- / 分隔单个物体
- . 是聚焦,周围物体都还存在,分隔是周围物体都暂时消失
六、整理分类模型
我们可以先A选中全部模型,Set Origin To Geometry,设置枢轴点到模型处,要不然枢轴点非常乱。
- M新建文件夹分类,Shift加选模型
- 可Alt+H 显示所有模型后,用数字 1 2 3 来切换不同的Collection
分类好之后,剩下的就只有外边缘了,我们需要对顶点进行一些操作:
- Tab 进入Edit Mode中,选中曲线后,P Seperate 可将当前曲线分离为一个单个的曲线
- Tab 在Object Mode中,选中两曲线后,Ctrl+J 可将两曲线合并到一个曲线中
- X 删除曲线点
- F连接两曲线点
差不多之后我们Shift+D备份一份外墙曲线,然后将曲线转换为Mesh,可以进行点线面的操作。
七、制作外墙体(Snapping+Solidify)
制作外墙体总共有多种方式:
【1.】可以将曲线分割开,然后用一个小长方体+Array Modifier+Curve Modifier
参见:
X Tesla:【Blender】如何用 8 种 Modifier 快速制作各种摩天大楼(建模提升工作效率必看!)zhuanlan.zhihu.com【2.】也可以删减曲线点,转化为Mesh后两点成线,四点成面,然后挤出面即可。
Alt+M Merge By Distances 删除多余挤出来的点
【3.】还可以通过Snapping工具来挤出平面+Solidify加厚Modifier生成墙体
这个其实就类似上面第四节中讲到过的调节Curve曲线的Extrude值,只不过有些DXF图纸比较复杂,我们可能需要重新手动添加。
我们这里着重讲解第三种。
- Shift+Tab 开启Snapping 对齐工具
- Ctrl+Tab 是切换Mode(Object、Vertex这些)
- Ctrl+Shift+Tab是切换Snap的对象,比如捕捉到点、线、面等(可以Shift加选)
【7.1】Shift+A 添加Plane(Size =30m,即高度为3m,乘10是因为我们的场景单位Unit Scale=0.1)
【7.2】开启面朝向(Face Orientation)
开启这个面 就是只有红绿蓝三种颜色。如果用的是Solid Normal Shading的话,那么会被红绿蓝三色覆盖掉。
【7.3】把Plane Snap 到图纸上
Ctrl+Shift+Tab选择Vertex 捕捉。
【7.4】Tab Edit Mode 选中两点G挪动(挪动的顶点就是左边那两个)/E挤出(挤出就直接成面了)
外墙体挤出完毕:
- 内墙体需要先随便选两个垂直地面的顶点,Shift+D复制到里面。
- 然后P 分离成单个的模型
忘了也没关系,Blender的选择功能也非常强大,循环边、指定面、相同长度的面、相同材质的面等等。
- 选中外围墙的单根边
- Select 内部边
- Ctrl+I反选
- P Seperate By selection(Loose Part是分离成好多个碎块模型)
内墙体挤出完毕:
【7.5】使用Solidify Modifier 加粗墙体
- 外围 3(30cm)
- 内侧 1(10cm)
调整Offset可以偏移墙体位置,如果缝隙过大的话。
可以关掉Face Orientation,这下墙体是处理好了
八、制作地板
- 选中外墙体
- ~ 切换到左视图
- Shift+Z X-Ray(可以选中后面看不见的顶点)
- 框选下方顶点
- F 成面
九、启用自带Archimesh和Archipack插件(做建筑小物件非常方便)
十、添加各式各样的门
- 门宽
- 门高
- 门厚
- 门Inset
- 门旋转角度
- 开门方向(右开门、双开门、左开门)
- 门的类型(普通、玻璃等等)
- 扶手的类型(圆的、把儿的、推的)
三开门:
门的种类:
门把手:
Shift加选设置可见、但是不能被选中,这样A全选就选中门的全部组件了,G好移动。
然后添加完一个门就在世界大纲中Shift加选 设置这个门的所有组件不能被选中,之后再添加下一个门的时候,A全选就是这个新门了。
或者是在世界大纲中选中父层,然后Shift G Select Group Chirdren即可。
好了,门体添加完毕
十一、添加窗户
Rail Window小窗户
Panel Window落地窗
在移动位置的时候,可以打勾Align Rotaion to Target,这样物体就会自动地根据点线面位置进行旋转啦。(如果垂直于表面,可以把Rotate也打上勾,然后R X/Y/Z就可以自动转向了)
落地窗可以Snap To Edge Center。
- < 可切换 Transform Orientation
- > 可切换Transform Pivot Point
十二、添加小物件
我们先把它这里能添加的先添加上,其他的我们就不添加了,时间有限。
- 楼梯和屋顶
- 窗帘
- 书架和书
- 灯泡
- 小柜子(cabinets)
【书架和书:】
小物件就不再放了,大概就是这样子。
其他随后再进行深化添加,可能还有很多的问题。
要睡觉了。。。。
-
Python-字符版gif图
2019-07-12 07:37:41上一篇文章我们讲了怎么做自己的炫酷二维码,需要的移驾Python-炫酷二维,本片文章我们讲述下怎么把一张图片处理成字符版图片,就是说使用字符替代每个像素的颜色,形成一个由字符组成的图片,并且字符的颜色是由...
原文链接:Python-字符版gif图一、背景
上一篇文章我们讲了怎么做自己的炫酷二维码,需要的移驾Python-炫酷二维,本片文章我们讲述下怎么把一张图片处理成字符版图片,就是说使用字符替代每个像素的颜色,形成一个由字符组成的图片,并且字符的颜色是由原始的图片像素决定
二、准备环境
对图片的操作我们可以使用PIL、imageio和image2gif库,处理像素我们选择使用opencv-python这个库。NumPy是Python语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。
因此我们需要安装以下几个包:PIL、imageio、numpy、cv2、images2gif
- pip install pillow
- pip install imageio
- pip install numpy
- pip install opencv-python
- pip install images2gif
以上扩展包安装时应该都可以顺利安装,但使用的时候有几个坑
1、导入cv2时,如果发生找不到dll的情况,大多数的原因都是当前的python版本和opencv版本不匹配,pip安装时默认选择了最新的版本,因此我们安装时需要制定安装的版本pip install opencv-python==3.4.1.15
2、使用images2gif这个库时,可能会出现无法导入writeGif接口的情况这个时候需要改下源码,把images2gif.py文件中的两个from 后边加上英文点号,修改如下
from .images2gif import readGif as readGif from .images2gif import writeGif as writeGif
三、字符版动态图
首先我们需要搞清楚gif是个什么玩意儿,其实gif是将多幅图像保存为一个图像文件,从而形成动画,最常见的就是通过一帧帧的动画串联起来的搞笑gif图,所以归根到底gif仍然是图片文件格式。
什么?原来gif就是一帧一帧的图片,那么字符版动态图其实也就是字符版图片的连续播放,思考到这儿,我们有了如下思路:
1、拿到一张gif图
2、把fig图拆分成多张png图片,或者其他格式的图片
3、循环遍历拆分后的图片,并处理成字符版图片
4、把处理后的字符版图片在连接成一个guf文件
5、保存gif文件
通过以上5个步骤,我们即可实现我们的需求,是不是很简单,下边我们分布来讲解实现过程
四、gif和png转换
1、要想获得静态图片,我们需要有一个gif图,然后把gif图拆分成多张png图片,以下是3中处理gif图片的方式
方式1
def Gif2Png(): gif = Image.open(gifpath) try: while True: current = gif.tell() gif.save(saveFloder + "/%d.png" % current) gif.seek(current + 1) except: pass
方式2
def Gif2Png_2(): try: im = Image.open(gifpath) except IOError: print ("Cant load", gifpath) sys.exit(1) i = 0 mypalette = im.getpalette() try: while 1: im.putpalette(mypalette) frame = im.convert('RGBA') new_im = Image.new("RGBA", im.size) #new_im.paste(im) new_im.paste(frame) new_im.save(saveFloder + "\\%d.png" % i) i += 1 im.seek(im.tell() + 1) except EOFError: pass # end of sequence
方式3
#使用imageio处理gif图 def Gif2Png_3(): images = imageio.mimread(gifpath) #把上面的每帧图片进行保存 for i, img in enumerate(images): img = np.asarray(img) imageio.imwrite(saveFloder + "\\%d.png" % i, img)
2、把图片处理成gif图,以下是处理的两种方式
方式1
def Png2Gif(): fileOrder = sorted([int(os.path.splitext(x)[0]) for x in os.listdir(savePath)]) frames = [] for order in fileOrder: filename = str(order)+ '.png' filePath = savePath + "/" + filename frames.append(imageio.imread(filePath)) imageio.mimsave(newFilePath, frames, 'GIF', duration = 0.1)
**方式2 **
def Png2Gif_2(): fileOrder = sorted([int(os.path.splitext(x)[0]) for x in os.listdir(savePath)]) filenames = [] # 存储所需要读取的图片名称 for order in fileOrder: filename = str(order)+ '.png' filePath = savePath + "/" + filename filenames.append(filePath) # 将使用的读取图片汇总 frames = [] for image_name in filenames: # 索引各自目录 im = Image.open(image_name) # 将图片打开,本文图片读取的结果是RGBA格式,如果直接读取的RGB则不需要下面那一步 im = im.convert("RGB") # 通过convert将RGBA格式转化为RGB格式,以便后续处理 im = np.array(im) # im还不是数组格式,通过此方法将im转化为数组 frames.append(im) # 批量化 writeGif(newFilePath, frames, duration=0.1, subRectangles=False) # 生成GIF,其中durantion是延迟,这里是1ms
测试生成效果如下图所示
五、处理动态图片
生成字符版gif图时,如果把拆分开来的图片先进行保存硬盘,然后在进行图片处理在合成最终gif效率会比较慢,因此我们把整个过程都放在内容中处理,即拆分开来的png图片不进行存盘,而是直接处理,然后在合成gif图
def Gif2Gif(gifpath): A = [] images = imageio.mimread(gifpath) #把上面的每帧图片进行保存 for img in images: u, v, channels = img.shape c = img * 0 + 255 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) for i in range(0, u, 6): for j in range(0, v, 6): pix = gray[i, j] b, g, r, a = img[i, j] zifu = string[int(((len(string) - 1) * pix) / 256)] if a != 0: cv2.putText(c, zifu, (j, i), cv2.FONT_HERSHEY_COMPLEX, 0.3, (int(b), int(g), int(r), int(a))) A.append(c) oldFileName = os.path.splitext(os.path.basename(gifpath))[0] newFilePath = os.getcwd() + '/{}/'.format(saveFloder) + oldFileName +"_new.gif" imageio.mimsave(newFilePath, A, 'GIF', duration=0.1)
测试生成效果如下图所示
六、字符版动态二维码
有了普通的gif图生成动态二维码的方式,字符版gif图也就顺理成章的可以。
测试生成效果如下图所示七、源码下载
需要全部代码的到csdn直接下载:Python-字符版gif图
如果您觉得文章不错,不妨给个打赏,写作不易,感谢各位的支持。您的支持是我最大的动力,谢谢!!!
很重要–转载声明
-
本站文章无特别说明,皆为原创,版权所有,转载时请用链接的方式,给出原文出处。同时写上原作者:朝十晚八 or Twowords
-
如要转载,请原文转载,如在转载时修改本文,请事先告知,谢绝在转载时通过修改本文达到有利于转载者的目的。
-
webots自学笔记(五)使用物理插件ODE建立铰链
2017-11-16 17:12:14在webots中,怎样建立一个铰链呢,我做了一个简单的例子,小区门口的那种可以控制的栏杆,效果图如下。 那每一个杆件,它们的关系在怎么定义呢?其实关系是在ODE中定义的,我们只需要建立一些没有约束关系的...在一些三维制图软件或仿真软件里,都有运动副的概念,webots的节点里好像没有,不要担心,在物理插件里可以做到,不过要学习有关于ODE(开源动力学引擎的)一些内容。在webots中,怎样建立一个铰链呢,我做了一个简单的例子,小区门口的那种可以控制的栏杆,效果图如下。
那每一个杆件,它们的关系在怎么定义呢?其实关系是在ODE中定义的,我们只需要建立一些没有约束关系的杆件就行。场景树贴出在下面,虽然这些节点是以servo定义的,但是在不需要约束关系的杆件,例如连杆3,将type改成none,那么,杆件3与gan Robot的关系就不是servo关系了,在仿真中可以看成两个零件。模型就不介绍怎么建立了,后面会给出整个仿真的文件。
建立完模型之后,点击菜单栏的 向导 —>新物理插件,代码如下:
1 //来自“博客园,_阿龙clliu” http://www.cnblogs.com/clliu/, 2 #include <ode/ode.h> 3 #include <plugins/physics.h> 4 5 6 7 dBodyID getBody(const char *def) { 8 dBodyID body = dWebotsGetBodyFromDEF(def); 9 if (! body) dWebotsConsolePrintf("Warning: did not find body with DEF name: %s", def); 10 return body; 11 } 12 13 14 void webots_physics_init(dWorldID world, dSpaceID space, dJointGroupID contactJointGroup) { 15 16 //得到杆件的ID 17 dBodyID link1 = getBody("link1"); 18 dBodyID link2 = getBody("link2"); 19 dBodyID link3 = getBody("link3"); 20 dBodyID link4 = getBody("link4"); 21 dBodyID link5 = getBody("link5"); 22 dBodyID link6 = getBody("link6"); 23 24 //创建一个铰链副 25 dJointID hingeJoint = dJointCreateHinge(world, 0); 26 //定义铰链副约束的两个零件,link1和link3 27 dJointAttach(hingeJoint, link1, link3); 28 29 //定义铰链的作用点 30 dVector3 hinge_interface; 31 //将link1零件自身坐标系的(0,0,0)点转为全局坐标系坐标,赋给hinge_interface 32 dBodyGetRelPointPos(link1, 0, 0, 0, hinge_interface); 33 34 //设置铰链作用点 35 dJointSetHingeAnchor(hingeJoint, hinge_interface[0], hinge_interface[1], hinge_interface[2]); 36 //设置铰链作用轴(作用方向) 37 dJointSetHingeAxis(hingeJoint, 0, 0, 1); 38 39 //link4?link3?? 40 hingeJoint = dJointCreateHinge(world, 0); 41 dJointAttach(hingeJoint, link4, link3); 42 43 dBodyGetRelPointPos(link4, 0, -0.05, 0, hinge_interface); 44 45 dJointSetHingeAnchor(hingeJoint, hinge_interface[0], hinge_interface[1], hinge_interface[2]); 46 dJointSetHingeAxis(hingeJoint, 0, 0, 1); 47 48 //link5?link3?? 49 hingeJoint = dJointCreateHinge(world, 0); 50 dJointAttach(hingeJoint, link5, link3); 51 52 dBodyGetRelPointPos(link5, 0, -0.05, 0, hinge_interface); 53 54 dJointSetHingeAnchor(hingeJoint, hinge_interface[0], hinge_interface[1], hinge_interface[2]); 55 dJointSetHingeAxis(hingeJoint, 0, 0, 1); 56 57 //link6?link3?? 58 hingeJoint = dJointCreateHinge(world, 0); 59 dJointAttach(hingeJoint, link6, link3); 60 61 dBodyGetRelPointPos(link6, 0, -0.05, 0, hinge_interface); 62 63 dJointSetHingeAnchor(hingeJoint, hinge_interface[0], hinge_interface[1], hinge_interface[2]); 64 dJointSetHingeAxis(hingeJoint, 0, 0, 1); 65 66 //link4?link2?? 67 hingeJoint = dJointCreateHinge(world, 0); 68 dJointAttach(hingeJoint, link4, link2); 69 70 dBodyGetRelPointPos(link4, 0, 0.05, 0, hinge_interface); 71 72 dJointSetHingeAnchor(hingeJoint, hinge_interface[0], hinge_interface[1], hinge_interface[2]); 73 dJointSetHingeAxis(hingeJoint, 0, 0, 1); 74 75 //link5?link2?? 76 hingeJoint = dJointCreateHinge(world, 0); 77 dJointAttach(hingeJoint, link5, link2); 78 79 dBodyGetRelPointPos(link5, 0, 0.05, 0, hinge_interface); 80 81 dJointSetHingeAnchor(hingeJoint, hinge_interface[0], hinge_interface[1], hinge_interface[2]); 82 dJointSetHingeAxis(hingeJoint, 0, 0, 1); 83 84 //link6?link2?? 85 hingeJoint = dJointCreateHinge(world, 0); 86 dJointAttach(hingeJoint, link6, link2); 87 88 dBodyGetRelPointPos(link6, 0, 0.05, 0, hinge_interface); 89 90 dJointSetHingeAnchor(hingeJoint, hinge_interface[0], hinge_interface[1], hinge_interface[2]); 91 dJointSetHingeAxis(hingeJoint, 0, 0, 1); 92 } 93 94 void webots_physics_step() { 95 96 } 97 98 void webots_physics_draw() { 99 100 } 101 102 int webots_physics_collide(dGeomID g1, dGeomID g2) { 103 104 return 0; 105 } 106 107 void webots_physics_cleanup() { 108 109 }
设置完成物理引擎,在worldInfo节点下physics节点下选择该物理插件。控制器代码如下:
1 //来自“博客园,_阿龙clliu” http://www.cnblogs.com/clliu/, 2 #include <webots/robot.h> 3 #include <webots/servo.h> 4 #include <assert.h> 5 #include <math.h> 6 7 #define TIME_STEP 32 8 #define rad_2_deg(X) ( X / pi * 180.0 ) 9 #define deg_2_rad(X) ( X / 180.0 * pi ) 10 #define pi 3.1415926 11 #define frep 1 12 13 int main(int argc, char **argv) 14 { 15 16 double t = 0; 17 double servo_pos; 18 19 20 wb_robot_init(); 21 22 WbDeviceTag servo; 23 servo = wb_robot_get_device("link2"); 24 assert(servo); 25 26 while (wb_robot_step(TIME_STEP) != -1) { 27 28 29 servo_pos = 45 + 45 * sin(frep * t + pi); 30 wb_servo_set_position(servo,deg_2_rad(servo_pos)); 31 32 t += (double)TIME_STEP / 1000.0; 33 }; 34 35 36 wb_robot_cleanup(); 37 38 return 0; 39 }
如果没有什么错误,就能实现之前GIF的效果了,如果没做出来,也没关系,给出原文件,仿真文件下载地址。
如果有什么疑问,欢迎再下方提问。
-
-
-
-
:exclamation:怎么刷 LeetCode? 我是如何刷 LeetCode 的 算法小白如何高效、快速刷 leetcode? 刷题效率低?或许你就差这么一个插件 力扣刷题插件 《91 天学算法》限时活动 第一期讲义-二分法 第一期讲义-双...
-
用tensorflow做机器翻译时训练代码有问题
2019-05-27 16:45:17MakeSrcTrgDataset函数产生的五种张量如下(全部为张量) src_input: 编码器输入(源数据) src_size : 输入大小 trg_input:解码器输入(目标数据) trg_label:解码器输出(目标数据) trg_size: ... -
林轩田《机器学习基石》(十三)—— Hazard of overfitting
2020-07-28 17:09:15先从一个例子出发,我们现在要做一个一维的回归分析,资料中有五个点,然后输出一个实数。 资料:,N = 5 目标函数f:f是一个二次函数(图中为蓝色曲线) label:,由f产生再加一点点很小的噪音 解决方案1:4次...上节课讲了如何解决非线性问题:通过特征变换,将非线性模型映射到另一个空间,转换为线性模型,再来进行分类。我们说这样会增加额外的模型复杂度。今天我们说这个额外的复杂度会造成机器学习过拟合(overfitting)现象。今天讲困难怎么产生的以及如何解决它。
一、什么是过拟合?
先从一个例子出发,我们现在要做一个一维的回归分析,资料中有五个点,然后输出一个实数。
资料:
,N = 5
目标函数f:f是一个二次函数(图中为蓝色曲线)
label:
,由f产生再加一点点很小的噪音
解决方案1:4次多项式做回归分析,即用四次多项式把x空间中的点转换到z空间,再进行线性回归。
我们知道,四次多项式通过五个点,会有一个唯一解。所以
,图中为红色曲线。
我们发现红色曲线和真实的蓝色曲线一点都不像,实际上的
很大,因为除了那五个点,其他未知点的效果都不是很好。
所以
很小,而
很大,这是一种坏的泛化性。
我们回过头来看一下VC曲线:
就像上次说的,如果
,那么实际上的
与
差距越来越大(
很大,
很小)
可以看到随着vc维越来越大,
越来越小,in-sample error曲线一直下降,model complexity曲线就上升;
所以造成
先下后上。
从最好的vc维
往右看,
一直下降,
一直上升。我们看样子是把fitting做好了,但其实过头了(over)。所以
变小,
变高这个过程叫做overfitting,过拟合。(常见,不容易解决)
从最好的vc维
往左看,
处于高位,
也比较大,我们做的fitting不够好,所以导致
也不够好(under),所以叫做underfitting,欠拟合。
给出一个比喻来描述overfitting,把overfitting比作出了车祸,那么我们分析产生的原因:
- 开太快,油门太重,即使用了太大的vc dimension。
- 道路崎岖,也就是有太多noise。
- 对路况不熟悉,在机器学习中就是资料太少。
二、noise与资料
我们从问题出发
资料:
(图中为黑色圆圈)
目标函数f:f是一个十次函数(图中为蓝色曲线)
label:
,由f产生再加一点点很小的噪音
可以看到由于加了噪音,数据并非全部落在蓝色曲线上
另一个问题:
资料:
(图中为黑色圆圈)
目标函数f:f是一个50次函数(图中为蓝色曲线)
label:
此时,无噪音,数据全部落在蓝色曲线上
我们知道上面两个问题了,现在来看看我们选用的两个模型,一个是2阶多项式
,另一个是10阶多项式
,分别对上面两个问题进行建模。
对于第一个问题来说,(目标函数f是一个十次多项式)
首先要明确
是在已知样本上的err,是看线与圆圈的重合程度,重合越多,
越小。
是在未知样本上的err,是看我们模型的线与真实的线是否相同,模型的线越接近蓝色线,
越小。
可以看到,线与圆圈的重合程度方面,红线赢了,在模型的线与真实的线是否相同方面,在图像的左端和右端,红线和蓝线十分的不接近。于是通过计算有:
虽然10阶模型的
比2阶的小,但是它的
要比2阶的大得多,而2阶的
和
相差不大,显然地,从二次切换到十次,发生了overfitting。
同样对于另一个高维问题:
可以看到,线与圆圈的重合程度方面,红线再一次赢了,也就是说10阶模型的
比2阶的小;在模型的线与真实的线是否相同方面,红线和蓝线十分的不接近。也就是说
的
非常糟糕。
但是我们想,比如目标函数是十次的情况,用二阶多项式
就是选择了放弃完美解(因为真实f是十次,只有选择十次多项式
才有可能找到一模一样的或者几乎接近的线)。实际上却常常是“以退为进”,意思是就算你知道真正的f是十次多项式,你也选择一个看起来好的十次多项式作为g,那么最终结果也不一定好。
来看看为什么会这样?
从learning curve来分析一下具体的原因,learning curve描述的是
和
随着数据量N的变化趋势。下图中左边是2阶学习模型的learning curve,右边是10阶学习模型的learning curve。我们首先要认识一个事实:如果你选择我们已知的点靠近一点点,那么在已知err上会小一点点,就是
会小一点,在图中
的线会往下一点,但是在未知err会远离一点点(因为可能向noise靠近了一点点),
会大一点,在图中
的线会往上一点。之前讲过有noise的情况的公式,之前讲过d为多项式次数,所以可以发现10阶的偏移量更大(
受到noise的影响大)。
在左边区域,左右两张图比较,
一定是右边的比较低,
则是右边比较高,那么在左边区域(资料量不够多的时候),高阶的多项式表现都不会好,都会overfitting。所以资料量不够多的时候,千万不要选择过于复杂的多项式作为g。
上面讲了资料,下面就讲noise。
另一个例子中,目标函数是50阶多项式,且没有加入noise。这种情况下,我们发现仍然是2阶的模型拟合的效果更好一些,明明没有noise,为什么是这样的结果呢?
刚才我们说,对于f是50阶的情况,
和
都做不好,但
会稍微好一点。灵魂一问:真的没有noise吗?今天学的事情很复杂,无论
和
都做不好,这个复杂的行为就和noise一样。即复杂度造成了类似noise的影响。下一节会具体讲解这个问题。
三、什么时候要小心overfit可能发生?
我们把产生资料的过程分为两个步骤,一个是用目标函数f,
阶多项式,但要注意的是我们是产生真正的这么多阶的多项式,而不是伪装的
阶多项式;再加上noise,noise服从高斯分布。接下来我们讨论Gaussian分布的noise强度不一样的时候(
),对我们的overfitting的影响是什么?(资料数设置为N),我们现在有三个变数,
(影响noise强度)、N、
。于是我们研究这三个变数对overfit的影响。
还是之前的两个模型
和
,
,
, 以及显然有
我们用
来度量过拟合的程度。
- 情况一
下面展示了在
固定为20时候,横坐标为样本数量N,纵坐标为噪声水平
的图像,图里的颜色代表有多么overfit,越靠近红色,过拟合程度越大,越靠近蓝色,则过拟合没有那么严重。可以发现,好的情况一般发生在N大,noise水平小的情况。
- 情况二
下面展示了噪声水平
在固定为0.1时候,横坐标为样本数量N,纵坐标为阶数
的图像。图里的颜色代表有多么overfit,越靠近红色,过拟合程度越大,越靠近蓝色,则过拟合没有那么严重。大部分情况下,和上面的图比较接近,坏的情况都发生在左上角,好的情况都发生在右下角,也就是说目标越复杂。
我们把上面情况一中的noise叫做stochastic noise,随机噪声;第二节中我们说了,模型复杂度也是一种噪声,于是把情况二中的这种noise叫做deterministic noise,可以计算出来的噪声。
总之,在给出定以后,我们从上面两个情况来看看发生过拟合的时间点有:
- 资料太少
- stochastic noise太多
- deterministic noise太多(目标函数f很复杂,目标函数一旦很复杂,那么它一定存在某个地方无法被任何一个h很完美的描述,这个地方也就产生了噪音,这些噪音如图中灰色的部分,在实际中也比较常见比如电脑生成伪随机。)
- vc维太多
overfitting其实很容易发生。如果教一个小朋友数数字,我们不会从实数的完备性开始讲起,我们只会举一些简单例子。同样,在学hypothesis也不用学太复杂,这样deterministic noise会小一些。
四、如何避免overfitting呢?
之前把overfitting比作出了车祸,我们分析了产生的原因,现在给出解决方法:
- 油门太重,即使用了太大的vc dimension。解决方法:开慢点,即从简单的模型开始学起。
- 道路崎岖,也就是有太多noise。解决方法:把这些崎岖的地方搞清楚,即数据清洗。数据提纯(data cleaning/pruning)。
- 对路况不熟悉,在机器学习中就是资料太少。解决方法:增加路况资料,即现有的资料或对这个问题的了解中产生新的、多的资料(data hinting)。
- 开太快。解决方法:适时地踩刹车,即添加正则项。
- 其他。解决方法:时时刻刻看看仪表板,即validation 验证/交叉验证。
本节课主要介绍简单的data cleaning/pruning和data hinting两种方法。
比如对于手写数字问题,如果有人字写得不好看,比如图中左上角,我们看不出它为什么是“5”.若是现在有一个方法,我们可以检测出它不是真的‘5’(比如是不是靠近不同的类,而与相同的类离得远;或者是这个点err很大),这样我们有理由相信这个点是noise,接下来怎么做?
data cleaning:把这个noise的label改过来。
data pruning:把这个noise丢掉。
这就是说如果知道那些点是noise,用上面两个方法做就行,难点是如何找到这个noise(现在还没有比较完美的找法)。
如果手写字稍微转了转角度,那么这些字也是属于同一个字的。比如现在我们一共就这么多资料,当我们没有更多的资料却想告诉电脑更多的知识,那么我们可以把手上的资料转一转角度,变成新资料,然后再学习。所以,data hinting是针对N不够大的情况,如果没有办法获得更多的训练集,那么data hinting就可以对已知的样本进行简单的处理、变换,从而获得更多的样本。但是加进来的这些资料要有道理,不要和原来的差太远,不然会偏离原来的资料的分布,导致学习效果不好。
总结:
-
我自己总结的测试面试问题
2018-10-09 23:13:595. 测试的六条基本法则是什么:一功(功能)二可(可靠性)三效(效率)四易(易用性)五维(可维护性)六移(可移植性) 6. 回答不上来:这一块我不是很熟悉,确实学过,但是很久以前我做过,但是好长时间没用了,我... -
excel的使用
2012-11-25 17:06:01以便编辑修改,可以这样做:用鼠标左键单击“工具”菜单,选取“选项”命令,出现“选项”对话框,单击“视图”选项卡,接着设置“窗口选项”栏下的“公式”项有效,单击“确定”按钮(如图2)。这时每个单元格中的... -
MAPGIS地质制图工具
2013-05-06 16:15:301、 首先用Section打开工程文件,把所有文件设为编辑状态,然后对地形等高线文件进行高程赋值——新建线属性高程字段(原MapGis需要这样做,用Section剖面图菜单下的自动赋高程不需新建此字段(拖动操作))。... -
软件工程-理论与实践(许家珆)习题答案
2011-01-12 00:49:42A) 系统流程图和模块图 B) DFD图、数据词典、加工说明 C) 软件结构图、加工说明 D) 功能结构图、加工说明 5. 画分层DFD图的基本原则有(A C D)。 A) 数据守恒原则 B) 分解的可靠性原则 C) 子、父图... -
蚂蚁金服发布新一代数据可视化引擎G2
2020-12-02 18:53:14但是刚才那个图中虽然展示了四维的信息,但是各个维度都叠加在一起,不利于观察,这个时候我们就可以使用一些特别的技巧了,其中一个技巧叫分面。它可以将原来的一个图形按照某种分类规则... -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
C语言执行效率如何保证,看这一文就够了!
-
龙芯实训平台应用实战(希云)
-
win10任务栏透明
-
朱老师C++课程第3部分-3.6智能指针与STL查漏补缺
-
基于Flink+Hudi构建企业亿级云上实时数据湖教程(PC、移动、小
-
一个故事告诉你比特币的原理及运作机制
-
自旋轨道耦合操纵原子-分子玻色-爱因斯坦凝聚物中的复合拓扑自旋纹理
-
Golang零基础-->高级编程
-
Linux版opencv
-
C++11 14 17 20 多线程从原理到线程池实战
-
Python启蒙到架构师的核心技术精讲课程
-
羰基铁硫代硼酸铁:在双核配合物对离解React的生存能力中硫取代氧的作用
-
vue 爬坑 Can‘t resolve ‘sass-loader‘
-
SU(3)自旋轨道耦合玻色气体中的双量子自旋涡
-
逻辑回归二分类问题数学推导 免费公开版
-
Sensitivity enhancement of distributed polarization coupling detection in Hi-Bi fibers
-
工程亮孤子以增强两组分玻色-爱因斯坦凝聚物的稳定性
-
微服务架构(MicroserviceArchitecture)
-
【Python入门基础】Pycharm格式化代码常用快捷键
-
分布式事务(2PC/3PC/TCC 最终一致性详解)