Jupyter(iPython)笔记本当之无愧地被认为是一个很好的工具,用于对代码进行原型设计并以交互方式进行各种机器学习.但是当我使用它时,我不可避免地遇到以下问题:
假设我在jupyter中开发了一个整机学习管道,包括从各种来源获取原始数据,清理数据,特征工程和培训模型.现在用高效可读的代码从中制作脚本的最佳逻辑是什么?到目前为止,我曾经用几种方法解决它:
只需将.ipynb转换为.py,只需稍加修改,就可以将笔记本中的所有管道硬编码为一个python脚本.
制作一个包含许多函数的单个脚本(对于每一个或两个单元格大约有1个函数),尝试使用单独的函数组成管道的各个阶段,并相应地命名它们.然后通过指定所有参数和全局常量argparse.
与point(2)相同,但现在将所有函数包装在类中.现在,所有全局常量以及每个方法的输出都可以存储为类属性.
使用多个脚本将笔记本转换为python模块.我没有试过这个,但我怀疑这是解决这个问题的最长方法.
我想,这种整体设置在数据科学家中非常普遍,但令人惊讶的是我无法找到任何有用的建议.
伙计们,请分享您的想法和经验.你有没有遇到过这个问题?你是怎么解决它的?
从我读到的关于Eigen(这里)的内容来看,它似乎operator=()充当了懒惰评估的"障碍" - 例如它导致Eigen停止返回表达式模板并实际执行(优化的)计算,将结果存储到左边的=.
这似乎意味着一个人的"编码风格"对性能产生影响 - 即使用命名变量来存储中间计算的结果可能会对计算的某些部分进行"太早"评估,从而对性能产生负面影响. .
为了验证我的直觉,我写了一个例子并对结果感到惊讶(完整的代码在这里):
using ArrayXf = Eigen::Array <float, Eigen::Dynamic, Eigen::Dynamic>;
using ArrayXcf = Eigen::Array <std::complex<float>, Eigen::Dynamic, Eigen::Dynamic>;
float test1( const MatrixXcf & mat )
{
ArrayXcf arr = mat.array();
ArrayXcf conj = arr.conjugate();
ArrayXcf magc = arr * conj;
ArrayXf mag = magc.real();
return mag.sum();
}
float test2( const MatrixXcf & mat )
{
return ( mat.array() * mat.array().conjugate() ).real().sum();
}
float test3( const MatrixXcf & mat …Run Code Online (Sandbox Code Playgroud) 我不确定这里的最佳实践是什么,但我经常看到缩写变量名称,尤其是当范围很小时.所以(使用简单的Ruby示例)而不是def add_location(name, coordinates),我看到类似的东西def add_loc(name, coord)- 我甚至可能会看到类似的东西def add_loc(n, x, y).我想,当他们习惯于看到缩写词时,较长的名字可能会让一个人厌倦.
冗长是否有助于提高可读性,还是只会伤害每个人的眼睛? - 人们更喜欢缩写和缩短名称吗?
我正在阅读" 更好,更快,更轻的Java "(由Bruce Tate和Justin Gehtland撰写)并且熟悉敏捷类型团队的可读性要求,例如Robert Martin在其清晰的编码书中所讨论的内容.在我现在的团队中,我被告知明确不使用+运算符,因为它在运行时创建了额外的(和不必要的)字符串对象.
但是这篇文章,写于04年,讨论了对象分配是关于10个机器指令的.(基本上免费)
它还讨论了GC如何帮助降低此环境中的成本.
什么是使用之间的实际性能的权衡+,StringBuilder还是StringBuffer?(就我而言,它StringBuffer仅限于Java 1.4.2.)
StringBuffer对我来说导致丑陋,不太可读的代码,正如Tate的书中的几个例子所示.而且StringBuffer是线程同步的,这似乎有它自己的成本是大于中使用了"危险" +操作.
思想/意见?
它实际上不必添加新行,只是可读的东西.
有什么比这更好的?
str = "line 1" +
"line 2" +
"line 3";
Run Code Online (Sandbox Code Playgroud) 考虑到你有这样的代码:
doSomething() // this method may throw a checked a exception
//do some assignements calculations
doAnotherThing() //this method may also throw the same type of checked exception
//more calls to methods and calculations, all throwing the same kind of exceptions.
Run Code Online (Sandbox Code Playgroud)
现在我知道,实际上在构造异常时会出现性能损失,特别是展开堆栈.我还阅读了几篇文章,指出在输入try/catch块时会有轻微的性能损失,但这些文章似乎都没有结论.
我的问题是,是否建议将try catch中的行保持最小?,即只在try子句中包含可以实际抛出正在捕获的异常的行.try子句中的代码运行速度较慢或导致性能下降吗?
但考虑到这一点,更重要的是最佳实践/更易读的解决方案:
try {
doSomething() // this method may throw a checked a exception
//do some assignements calculations
doAnotherThing() //this method may also throw the same type of checked exception
//more calls to methods and calculations, all throwing …Run Code Online (Sandbox Code Playgroud) 比如为什么在STL实现大多数成员_M_或_或__前缀?为什么有那么多样板代码?
C++缺少哪些功能可以使make vector(例如)实现更清晰,更简洁?
假设我有两种方法bool Foo()和bool Bar().以下哪项更具可读性?
if(Foo())
{
SomeProperty = Bar();
}
else
{
SomeProperty = false;
}
Run Code Online (Sandbox Code Playgroud)
要么
SomeProperty = Foo() && Bar();
Run Code Online (Sandbox Code Playgroud)
一方面,我认为短路&&是一个有用的功能,第二个代码样本要短得多.另一方面,我不确定人们通常习惯于&&在条件陈述之外看到,所以我想知道是否会引入一些认知失调,这使得第一个样本成为更好的选择.
你怎么看?还有其他影响决策的因素吗?比如,如果&&表达式长于可以放在屏幕上的一行,我应该更喜欢前者吗?
答案后澄清:
我应该把一些事情包括在答案提出的最初问题中.
Bar()可能比执行起来更昂贵Foo(),但这两种方法都不应该有副作用.Foo()归结为类似CurrentUserAllowedToDoX()和Bar()更像是,XCanBeDone()有时我发现自己处于需要执行多个顺序命令的情况:
try:
foo(a, b)
except Exception, e:
baz(e)
try:
bar(c, d)
except Exception, e:
baz(e)
...
Run Code Online (Sandbox Code Playgroud)
只需要忽略异常时就会出现相同的模式.
这感觉多余,并且过多的语法使得在阅读代码时难以理解.
在C中,我很容易用宏来解决这类问题,但不幸的是,这不能在直接的python中完成.
问题:在遇到这种模式时,如何才能最好地减少代码占用空间并提高代码可读性?
在下面的代码中,我们进行了listType.getDescription()两次调用:
for (ListType listType: this.listTypeManager.getSelectableListTypes())
{
if (listType.getDescription() != null)
{
children.add(new SelectItem( listType.getId() , listType.getDescription()));
}
}
Run Code Online (Sandbox Code Playgroud)
我倾向于重构代码以使用单个变量:
for (ListType listType: this.listTypeManager.getSelectableListTypes())
{
String description = listType.getDescription();
if (description != null)
{
children.add(new SelectItem(listType.getId() ,description));
}
}
Run Code Online (Sandbox Code Playgroud)
我的理解是JVM以某种方式针对原始代码进行了优化,尤其是嵌套调用children.add(new SelectItem(listType.getId(), listType.getDescription()));.
比较两个选项,哪一个是首选方法,为什么?这就是内存占用,性能,可读性/易用性以及其他我现在不想到的内容.
后一个代码片段何时变得比前者更有利,也就是说,listType.getDescription()当使用临时局部变量变得更加理想时,是否存在任何(近似)调用次数,因为listType.getDescription()总是需要一些堆栈操作来存储this对象?
readability ×10
performance ×4
java ×3
c++ ×2
python ×2
c# ×1
c++11 ×1
eigen ×1
exception ×1
javascript ×1
jupyter ×1
refactoring ×1
ruby ×1
stl ×1
string ×1
try-catch ×1