【问题标题】:Singular Value Decomposition (SVD) in PHPPHP中的奇异值分解(SVD)
【发布时间】:2010-10-31 21:31:54
【问题描述】:

我想在 PHP 中实现奇异值分解 (SVD)。我知道有几个外部库可以为我做到这一点。但是我有两个关于 PHP 的问题: 1) 你认为用 PHP 编写 SVD 是可能和/或合理的吗? 2) 如果 (1) 是:你能帮我用 PHP 编码吗?

我已经自己编写了 SVD 的某些部分。 Here's the code 我在其中创建了 cmets 以执行操作。此代码的某些部分并不完全正确。

如果你能帮助我,那就太好了。非常感谢您!

【问题讨论】:

  • 您的德语 cmets 非常有帮助。为什么要在 PHP 中实现这么复杂的算法?
  • 如果有人需要英文的cmets,我当然可以翻译。我必须在 PHP 中实现它,因为我无法在我的网站空间上安装外部库。
  • 不,这不是家庭作业。我在学校没有计算机科学,我也不学习它。 ;) 这只是一种爱好......

标签: php svd eigenvector eigenvalue


【解决方案1】:

我知道这是一个旧的 Q,但这是我的 2 位:

1) 真正的 SVD 比使用微积分启发的近似值慢得多,例如,在 Netflix 奖中。见:http://www.sifter.org/~simon/journal/20061211.html

这里有一个实现(用 C 语言): http://www.timelydevelopment.com/demos/NetflixPrize.aspx

2) C 会更快,但 PHP 肯定可以做到。

PHP 架构师作者 Cal Evans:“PHP 是一种 Web 脚本语言...... [但是] 我使用 PHP 作为脚本语言来编写 DOS 等效的 BATCH 文件或 Linux 等效的 shell 脚本。我已经发现我需要做的大部分事情都可以在 PHP 中完成。甚至还有一个项目可以让您通过 PHP 构建桌面应用程序,即 PHP-GTK 项目。”

【讨论】:

    【解决方案2】:
    1. 是的。这完全有可能在 PHP 中实现。 我不知道执行的合理时间范围以及它可以计算多大。 我可能必须实现该算法才能得到一个粗略的想法。

    2. 是的,我可以帮你编写代码。但是你为什么需要帮助?你写的代码不行吗?

    就像一个问题。你用的是什么版本的PHP?

    【讨论】:

    • 非常感谢!许多与我交谈过的人告诉我 PHP 完全不适合 SVD。我不在乎时间限制是什么,我只想实现它。我的代码不起作用,因为它没有得到特征值。我尝试了一些近似程序,但效果不佳。如果你能帮助我,那就太好了。我使用 PHP 5。
    【解决方案3】:

    SVD-python 是一个非常清晰、简洁的 SVD 实现。 它实际上是伪代码,应该很容易理解 并比较/借鉴您的 php 实现,即使您不太了解 python。

    SVD-python

    也就是说,正如其他人所提到的,我不希望能够通过 php 实现来执行非常繁重的 LSA,这听起来像是一个非常有限的网络主机。

    干杯

    编辑: 上面的模块本身并没有做任何事情,但有一个例子包含在 打开 cmets。假设您下载了 python 模块,并且它是可访问的(例如在同一个文件夹中),您 可以实现一个简单的例子如下,

    #!/usr/bin/python
    import svd
    import math
    
    a = [[22.,10., 2.,  3., 7.],
         [14., 7.,10.,  0., 8.],
         [-1.,13.,-1.,-11., 3.],
         [-3.,-2.,13., -2., 4.],
         [ 9., 8., 1., -2., 4.],
         [ 9., 1.,-7.,  5.,-1.],
         [ 2.,-6., 6.,  5., 1.],
         [ 4., 5., 0., -2., 2.]]
    
    u,w,vt = svd.svd(a)
    print w
    

    这里的“w”包含您的奇异值列表。
    当然,这只会让你部分了解潜在语义分析及其相关内容。 您通常希望减少奇异值的数量,然后采用一些适当的距离 度量您的文档或单词或文档和单词等之间的相似性的度量。 结果向量之间夹角的余弦值非常流行。

    Latent Semantic Mapping (pdf)

    是迄今为止我读过的关于你剩下的步骤的最清晰、最简洁和信息最丰富的论文 需要按照 SVD 进行锻炼。

    Edit2:还请注意,如果您正在使用非常大的术语文档矩阵(我假设这个 是你在做什么)执行分解几乎肯定会更有效率 在离线模式下,然后仅以实时方式执行比较以响应请求。 虽然 svd-python 非常适合学习,但 svdlibc 更适合你想要的这么重的东西 计算。

    最后正如上面 bellegarda 论文中提到的,记住你不必重新计算 svd 每次你得到一个新的文件或请求。取决于你想要做什么,你可以 可能每周左右执行一次 svd,在离线模式下,在本地机器上, 然后上传结果(尽管存在大小/带宽问题)。

    祝你好运!

    【讨论】:

    • 非常感谢!!! :) 如果这可以与 PHP 的 passthru() 函数(thx ljyanes)结合使用,那就太好了。但是这个脚本没有给出任何输出。我必须做什么?我已经注释掉了这个:paste.bradleygill.com/index.php?paste_id=10389
    • 我添加了一些进一步的信息,包括来自 python 模块中 cmets 的工作示例。
    • 再次感谢您的编辑。你的代码正是我所做的,不是吗? ;) 查看我编写代码的代码粘贴站点。我想我只是拿错了包裹。我只下载了您上面链接的 svd.py 文件。我还需要加载其他内容吗?
    • 是的,看起来不错。但是请注意,python 对空格/缩进很敏感。当我下载您的示例时,我需要从所有行中删除前导空格,并将 #!/usr/bin/python 行添加到顶部。但假设您的执行目录或 python 路径中有 svd.py 文件(对于 debian,默认为 /usr/lib/python2.5/site-packages/ )
    • 我刚刚看到:这不是你的错,是我的错! :) 我不得不将文件 CHMOD 到 755 并在脚本的开头编写以下代码,现在它工作正常: print "Content-type: text/html\n\n";
    【解决方案4】:

    是的,这是可能的,但在 php 中实现 SVD 并不是最佳方法。正如您在此处看到的,PHP 比 C 慢,也比 C++ 慢,所以如果您可以使用其中一种语言执行此操作并将它们作为函数调用以获取结果,那么可能会更好。你可以找到算法here的实现,这样你就可以引导自己通过它。

    关于函数调用可以使用:

    • exec() 函数

    系统函数非常有用且功能强大,但它最大的问题之一是程序生成的所有文本都直接进入输出流。在某些情况下,您可能希望格式化生成的文本并以某种不同的方式显示它,或者根本不显示它。

    • system() 函数

    PHP 中的系统函数采用字符串参数和要执行的命令以及您希望传递给该命令的任何参数。此函数执行指定的命令,并将任何结果文本转储到输出流(Web 服务器情况下的 HTTP 输出,或者如果您将 PHP 作为命令行工具运行,则为控制台)。如果该函数发出文本输出,则该函数的返回是程序的最后一行输出。

    • passthru() 函数

    PHP 提供的一个与我们目前看到的类似的有趣函数是 passthru 函数。这个函数和其他函数一样,执行你告诉它的程序。但是,它会立即将来自该程序的原始输出发送到 PHP 当前正在使用的输出流(即 Web 服务器场景中的 HTTP 或 PHP 命令行版本中的 shell)。

    【讨论】:

    • 你应该提到你已经直接从ChipmunkNinja复制了函数描述。
    【解决方案5】:

    当您说“我不在乎时间限制是多少”时要小心。 SVD 是一个O(N^3) 操作(或O(MN^2),如果它是一个矩形m*n 矩阵),这意味着您很容易遇到问题可能需要很长时间的情况。如果 100*100 的情况需要一分钟,那么 1000*1000 的情况将需要 10^3 分钟,或者将近 17 小时(实际上可能更糟,因为您可能会超出缓存)。对于 PHP 之类的东西,为了计算所需的 FLOP 计数而乘以 N^3 的数字可能非常非常大。

    话虽如此,当然可以用 PHP 对其进行编码——该语言具有所需的数据结构和操作。

    【讨论】:

    • 非常感谢您!所以你认为用 PHP 编码是可能的,但 PHP 不是很适合,对吧?
    • 嗯,PHP 不是数值线性代数的理想选择,但能否使其适用于您的情况取决于细节。您将在多大的矩阵上运行它?究竟,你需要做什么?您可能需要查阅像《数值食谱》这样的书 nr.com> 以获取有关实现的信息。
    • 我想使用 SVD 进行潜在语义分析。所以 100x100 对矩阵来说是不够的,它们会很大......
    • Marco,我已经完成了 LSA,我可以肯定地告诉你,对于 any 大小的矩阵,PHP 将提供不可接受的响应时间,更不用说巨大了。为自己节省时间去弄清楚它并找到一种与 C 接口的方法。Svdlibc 对我来说非常有用:tedlab.mit.edu/~dr/svdlibc
    • 谢谢你,llimllib。只要我的网络服务器上有 C,我就会使用它。但目前我没有它,我无法使用控制台安装任何东西。
    【解决方案6】:

    关于问题1:绝对有可能。是否合理取决于您的场景:您的矩阵有多大?您打算多久运行一次代码?它是在网站上运行还是从命令行运行? 如果您确实关心速度,我会建议 writing a simple extension 包装对 GNU Scientific Library 的调用。

    【讨论】:

    • 感谢您的回答。我想在网站上运行它,脚本应该由 cronjob 调用。我不太关心速度。如果脚本总是对 1 个单一文本执行 SVD 就足够了。我一直需要的巨大矩阵也可以被缓存。为 GNU 科学库编写扩展是一个问题,因为我无法通过命令行在我的网站空间上安装库。
    • 如果您有 shell 访问权限并且可以安装二进制文件并使用 cron,您可能应该考虑编写独立的(可能是静态链接的)二进制文件,而不是 PHP 脚本。即使对于相同的算法,这也会更节省 CPU 和内存。
    猜你喜欢
    • 1970-01-01
    • 2011-06-30
    • 2015-04-16
    • 2010-10-06
    • 1970-01-01
    • 1970-01-01
    • 2016-01-10
    • 2014-03-10
    • 1970-01-01
    相关资源
    最近更新 更多