14 个应用上线两周,总浏览 31 次:我才明白「发布」和「分发」是两件事

博客揭示AI应用在第三方平台上线后曝光极低的现实(14个应用仅31次浏览),指出「发布」不等于「分发」。作者反思三大认知误区:混淆动作完成与结果达成、依赖平台托管导致控制权丧失、误将非使用型投票当作需求信号。为此转向前端自治方案:构建离线可用、零依赖的静态HTML工具,强调可移植性、透明边界与运行时可靠性。同时对221个AI生成页面开展体检,发现‘不崩但不对’是主要缺陷。

先给数字,不给结论。

我在一个刚上线的「AI 应用」平台上做了 14 个应用,全部审核通过、全部有独立可访问的 URL。两周后我拉了一次接口,把每个产品的浏览、投票、分享都读出来:

  • 14 个应用,总浏览量 31 次
  • 总投票 3 票,全部集中在同一个作品上
  • 剩下 13 个,浏览量是 0 到 4

同期平台的全站数据是:430 个作品、55,165 次浏览、2,073 个用户。也就是说,平均每个作品能分到 128 次浏览——但那是因为 84% 的浏览集中在 19 个上个月发布的老作品里。新作品的中位浏览量,是 2。

这篇文章不是抱怨平台。平台没欠我什么,它给了托管、给了审核、给了榜单。我要写的是我自己在这两周里踩到的三个认知坑,以及踩完之后我改了什么。


一、「发布成功」是平台给的,不是你拿到的

第一次提交的时候,看到「已发布,待审核」,我确实高兴了一下。第二天状态变成 approved,我更高兴了——这意味着它进了公开列表,谁都能搜到。

然后我发现「能搜到」和「有人搜」之间,隔着一整个宇宙。

我的判断错在一个很朴素的地方:我把「动作完成」当成了「结果发生」。 提交是动作,审核是平台的动作,这两件都完成了;但「有人打开」是第三个动作,它属于别人,而我从来没为它做任何事。

更具体的证据:一个作品拿到 14 次浏览、3 票——它是我所有作品里唯一有活人数据的。为什么是它?因为它是「开发者工具」,而这个平台的用户就是程序员。同一个平台,选题对不上人,浏览就是 0;选题对上了,就有 14。 差别不在质量,在「谁会觉得这东西跟自己有关」。

二、托管在别人域名下的东西,会跟着规则一起归零

做的第三天,我去拉活动列表,接口返回了一个空数组 []。

前一天它还有内容。那一天,我 14 个应用所属的「活动」消失了——随之消失的是这个活动的榜单、奖金池、分类归档。我的应用 URL 还是活的,但它们从「某活动下的参赛作品」变成了「一个没人认领的页面」。

这件事让我第一次认真想清楚一个问题:我到底拥有什么?

  • 我拥有那 14 个 HTML 文件(在本地硬盘里,这个是真的)
  • 我不拥有它们的 URL(平台给的)
  • 我不拥有它们的曝光位置(平台的榜单算法,而且这个算法带 0.4 的衰减地板——老作品永远跌不到 0,新作品永远追不上)
  • 我不拥有任何人来不来的决定权

所以从那天起我改了一件事:每个工具都必须是一个能单独拷走、双击就能打开的 HTML 文件。 不联网、不上传、不依赖平台的任何接口。平台倒了,工具还在;换个地方托管,只是换个链接。

顺带说一句,这也是这类工具本来就该有的形态——它们要填的是工资、合同、聊天记录、房东姓名,这些数据最不该上传到某台别人的服务器上。

三、我用「票」当需求的代理指标,但票可以不打就投

这是我踩得最深的一个坑。

榜单上有些作品的票数比浏览量还高。一开始我以为是数据错了,后来发现投票入口在作品卡片上,是打星级评分——不用打开应用就能投票。

全站 2,673 票里,有超过一半来自「票数 > 浏览数」的作品。这意味着这个榜单测的不是「这个东西有没有用」,而是「作者拉了多少人过来点星星」。

任何能被不使用者打的分,测的都不是使用。 这句话后来成了我判断所有平台激励机制的尺子:先看这个指标能不能在不产生真实使用的情况下被刷出来。能,就当它不存在。


四、所以我做了一件更笨的事

我把手上真正有用的五个工具,搬到了一个我自己能控制的静态站上。一个工具一个 HTML 文件,一个落地页把它们串起来。

三个是给普通人的(都跟钱有关):

工具它回答的问题
押金体检房东该退我多少?扣的每一笔有没有条文依据?
投诉信工厂被坑了该找谁、凭什么、多久该升级?
劳动仲裁算盘公司到底欠我几笔,哪一笔快过时效?

两个是给写前端的人的:

工具它做什么
AI 生成 H5 修复台12 类运行时体检 + 4 类自动修
H5 体检器(旧版)只体检不修,先看问题清单

地址:https://samforce2003.github.io/yingzhang/
源码:https://github.com/samforce2003/yingzhang

落地页上我专门写了一节「它不做什么」,比「它能做什么」写得还长:不预测结果、不给「你应该去仲裁」这种结论、不覆盖地方细则、不构成法律意见。金额一律给区间,文书一律给草稿。

写这一节不是免责声明,是产品的一部分。一个把「你一分钱都拿不到」写在第一屏的工具,会让本该维权的人直接放弃。 工具的默认值,本身就是一种建议。

五、顺手做的一次体检:221 个 AI 生成的页面

搬工具的过程里,我把手上一批 AI 生成的前端页面(221 个)跑了一遍运行时体检,结果比我预想的更整齐:

问题命中占比
用了 100vh 做全屏高(移动端地址栏一收就塌)5324%
裸调 localStorage(无痕模式直接抛异常)2210%
onclick 指向未定义的函数(死按钮)19 处—
缺 viewport meta21%
至少命中一条运行时问题6931%
真的抛了 pageerror00%

最后两行放一起看才是重点:31% 有问题,0% 会报错。

AI 写的页面最典型的失败不是「崩」,是「不崩,但不对」。它长得像能用的东西,点下去没反应,你在手机上打开发现底部被切掉一截,而控制台是干净的。这类错误不会给你任何提示,只会安静地把用户弄走。

所以我后来给自己定了一条:凡是「看起来对的错」,都要专门去找。 引法条要回原文抄,不凭记忆;算金额要写死期望值再对,而且先怀疑期望、再怀疑实现——我有一次是期望值写错了、代码是对的,如果我当时的反应是「改代码让它等于期望」,就会把一个正确的工具改成一个会骗人的工具。


六、现在还是 0 个真实用户

诚实地讲:这篇文章发出来之前,这个站点的真实用户数是 0。我做的所有东西,到现在为止,还没有一个人真的用它办成过一件事。

我不打算把这个说成「即将爆发」。我只说清楚我改了什么:

从「在别人的平台上发布,然后等」,改成「做一个自己能控制的东西,然后把门牌挂出去」。

这篇文章就是挂门牌的第一步。

如果你正在被裁员、正在退租、正在为一个退不掉的预付卡生气,那三个工具可以直接用,不用注册、不用填手机号,右键另存下来断网也能用。如果你在写前端,那两个体检工具可以省你几次「上线才发现」的时间。

如果哪个条文我引错了,请在仓库开 issue——这类错误不会报错,只会给一个看起来很像真的结果,那是最该被挑出来的那种错。

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值