Loading [MathJax]/extensions/TeX/boldsymbol.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >高斯过程 Gaussian Processes 原理、可视化及代码实现

高斯过程 Gaussian Processes 原理、可视化及代码实现

作者头像
AI算法与图像处理
发布于 2020-11-06 04:45:46
发布于 2020-11-06 04:45:46
6.5K00
代码可运行
举报
运行总次数:0
代码可运行

作者丨王桂波

来源丨https://zhuanlan.zhihu.com/p/75589452

编辑丨极市平台

导读

本文解析了高斯过程进行公式推导、原理阐述、可视化以及代码实现,并介绍了高斯过程回归基本原理、超参优化、高维输入等问题。

高斯过程 Gaussian Processes 是概率论和数理统计中随机过程的一种,是多元高斯分布的扩展,被应用于机器学习、信号处理等领域。本文对高斯过程进行公式推导、原理阐述、可视化以及代码实现,介绍了以高斯过程为基础的高斯过程回归 Gaussian Process Regression 基本原理、超参优化、高维输入等问题。

目录

  • 一元高斯分布
  • 多元高斯分布
  • 无限元高斯分布?
  • 核函数(协方差函数)
  • 高斯过程可视化
  • 高斯过程回归实现
  • 超参数优化
  • 多维输入
  • 高斯过程回归的优缺点

一元高斯分布

我们从最简单最常见的一元高斯分布开始,其概率密度函数为

其中 和 分别表示均值和方差,这个概率密度函数曲线画出来就是我们熟悉的钟形曲线,均值和方差唯一地决定了曲线的形状。

多元高斯分布

从一元高斯分布推广到多元高斯分布,假设各维度之间相互独立

其中 和 分别是第 1 维、第二维... 的均值和方差。对上式向量和矩阵表示上式,令

代入公式(2)得到

其中 是均值向量, 为协方差矩阵,由于我们假设了各维度直接相互独立,因此 是一个对角矩阵。在各维度变量相关时,上式的形式仍然一致,但此时协方差矩阵 不再是对角矩阵,只具备半正定和对称的性质。上式通常也简写为

无限元高斯分布?

在多元高斯分布的基础上考虑进一步扩展,假设有无限多维呢?用一个例子来展示这个扩展的过程(来源:MLSS 2012: J. Cunningham - Gaussian Processes for Machine Learning),假设我们在周一到周四每天的 7:00 测试了 4 次心率,如下图中 4 个点,可能的高斯分布如图所示(高瘦的那条)。这是一个一元高斯分布,只有每天 7: 00 的心率这个维度。

现在考虑不仅在每天的 7: 00 测心率(横轴),在 8:00 时也进行测量(纵轴),这个时候变成两个维度(二元高斯分布),如下图所示

更进一步,如果我们在每天的无数个时间点都进行测量,则变成了下图的情况。注意下图中把测量时间作为横轴,则每个颜色的一条线代表一个(无限个时间点的测量)无限维的采样。当对每次对无限维进行采样得到无限多个点时,其实可以理解为我们采样得到了一个函数。

当从函数的视角去看待采样,理解了每次采样无限维相当于采样一个函数之后,原本的概率密度函数不再是点的分布 ,而变成了函数的分布。这个无限元高斯分布即称为高斯过程。高斯过程正式地定义为:对于所有 ,都服从多元高斯分布,则称 是一个高斯过程,表示为

这里 表示均值函数(Mean function),返回各个维度的均值; 为协方差函数 Covariance Function(也叫核函数 Kernel Function)返回两个向量各个维度之间的协方差矩阵。一个高斯过程为一个均值函数和协方差函数唯一地定义,并且一个高斯过程的有限维度的子集都服从一个多元高斯分布(为了方便理解,可以想象二元高斯分布两个维度各自都服从一个高斯分布)。

核函数(协方差函数)

核函数是一个高斯过程的核心,核函数决定了一个高斯过程的性质。核函数在高斯过程中起生成一个协方差矩阵(相关系数矩阵)来衡量任意两个点之间的“距离”。不同的核函数有不同的衡量方法,得到的高斯过程的性质也不一样。最常用的一个核函数为高斯核函数,也成为径向基函数 RBF。其基本形式如下。其中 和 是高斯核的超参数。

高斯核函数的 python 实现如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import numpy as np

def gaussian_kernel(x1, x2, l=1.0, sigma_f=1.0):
    """Easy to understand but inefficient."""
    m, n = x1.shape[0], x2.shape[0]
    dist_matrix = np.zeros((m, n), dtype=float)
    for i in range(m):
        for j in range(n):
            dist_matrix[i][j] = np.sum((x1[i] - x2[j]) ** 2)
    return sigma_f ** 2 * np.exp(- 0.5 / l ** 2 * dist_matrix)

def gaussian_kernel_vectorization(x1, x2, l=1.0, sigma_f=1.0):
    """More efficient approach."""
    dist_matrix = np.sum(x1**2, 1).reshape(-1, 1) + np.sum(x2**2, 1) - 2 * np.dot(x1, x2.T)
    return sigma_f ** 2 * np.exp(-0.5 / l ** 2 * dist_matrix)

x = np.array([700, 800, 1029]).reshape(-1, 1)
print(gaussian_kernel_vectorization(x, x, l=500, sigma=10))

输出的向量 与自身的协方差矩阵为

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[[100.    98.02  80.53]
 [ 98.02 100.    90.04]
 [ 80.53  90.04 100.  ]]

高斯过程可视化

下图是高斯过程的可视化,其中蓝线是高斯过程的均值,浅蓝色区域 95% 置信区间(由协方差矩阵的对角线得到),每条虚线代表一个函数采样(这里用了 100 维模拟连续无限维)。左上角第一幅图是高斯过程的先验(这里用了零均值作为先验),后面几幅图展示了当观测到新的数据点的时候,高斯过程如何更新自身的均值函数和协方差函数。

接下来我们用公式推导上图的过程。将高斯过程的先验表示为 ,对应左上角第一幅图,如果现在我们观测到一些数据,并且假设 与 服从联合高斯分布

其中

则有

上述式子表明了给定数据 之后函数的分布 仍然是一个高斯过程,具体的推导可见 Gaussian Processes for Machine Learning。这个式子可以看出一些有趣的性质,均值 实际上是观测点 y 的一个线性函数,协方差项 的第一部分是我们的先验的协方差,减掉的后面的那一项实际上表示了观测到数据后函数分布不确定性的减少,如果第二项非常接近于 0,说明观测数据后我们的不确定性几乎不变,反之如果第二项非常大,则说明不确定性降低了很多。

上式其实就是高斯过程回归的基本公式,首先有一个高斯过程先验分布,观测到一些数据(机器学习中的训练数据),基于先验和一定的假设(联合高斯分布)计算得到高斯过程后验分布的均值和协方差。

简单高斯过程回归实现

考虑代码实现一个高斯过程回归,API 接口风格采用 sciki-learn fit-predict 风格。由于高斯过程回归是一种非参数化 (non-parametric)的模型,每次的 inference 都需要利用所有的训练数据进行计算得到结果,因此并没有一个显式的训练模型参数的过程,所以 fit 方法只需要将训练数据保存下来,实际的 inference 在 predict 方法中进行。Python 代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from scipy.optimize import minimize


class GPR:

    def __init__(self, optimize=True):
        self.is_fit = False
        self.train_X, self.train_y = None, None
        self.params = {"l": 0.5, "sigma_f": 0.2}
        self.optimize = optimize

    def fit(self, X, y):
        # store train data
        self.train_X = np.asarray(X)
        self.train_y = np.asarray(y)
        self.is_fit = True

    def predict(self, X):
        if not self.is_fit:
            print("GPR Model not fit yet.")
            return

        X = np.asarray(X)
        Kff = self.kernel(self.train_X, self.train_X)  # (N, N)
        Kyy = self.kernel(X, X)  # (k, k)
        Kfy = self.kernel(self.train_X, X)  # (N, k)
        Kff_inv = np.linalg.inv(Kff + 1e-8 * np.eye(len(self.train_X)))  # (N, N)
        
        mu = Kfy.T.dot(Kff_inv).dot(self.train_y)
        cov = Kyy - Kfy.T.dot(Kff_inv).dot(Kfy)
        return mu, cov

    def kernel(self, x1, x2):
        dist_matrix = np.sum(x1**2, 1).reshape(-1, 1) + np.sum(x2**2, 1) - 2 * np.dot(x1, x2.T)
        return self.params["sigma_f"] ** 2 * np.exp(-0.5 / self.params["l"] ** 2 * dist_matrix)
def y(x, noise_sigma=0.0):
    x = np.asarray(x)
    y = np.cos(x) + np.random.normal(0, noise_sigma, size=x.shape)
    return y.tolist()

train_X = np.array([3, 1, 4, 5, 9]).reshape(-1, 1)
train_y = y(train_X, noise_sigma=1e-4)
test_X = np.arange(0, 10, 0.1).reshape(-1, 1)

gpr = GPR()
gpr.fit(train_X, train_y)
mu, cov = gpr.predict(test_X)
test_y = mu.ravel()
uncertainty = 1.96 * np.sqrt(np.diag(cov))
plt.figure()
plt.title("l=%.2f sigma_f=%.2f" % (gpr.params["l"], gpr.params["sigma_f"]))
plt.fill_between(test_X.ravel(), test_y + uncertainty, test_y - uncertainty, alpha=0.1)
plt.plot(test_X, test_y, label="predict")
plt.scatter(train_X, train_y, label="train", c="red", marker="x")
plt.legend()

结果如下图,红点是训练数据,蓝线是预测值,浅蓝色区域是 95% 置信区间。真实的函数是一个 cosine 函数,可以看到在训练数据点较为密集的地方,模型预测的不确定性较低,而在训练数据点比较稀疏的区域,模型预测不确定性较高。

超参数优化

上文提到高斯过程是一种非参数模型,没有训练模型参数的过程,一旦核函数、训练数据给定,则模型就被唯一地确定下来。但是核函数本身是有参数的,比如高斯核的参数 和 ,我们称为这种参数为模型的超参数(类似于 k-NN 模型中 k 的取值)。

核函数本质上决定了样本点相似性的度量方法,进行影响到了整个函数的概率分布的形状。上面的高斯过程回归的例子中使用了 的超参数,我们可以选取不同的超参数看看回归出来的效果。

从上图可以看出, 越大函数更加平滑,同时训练数据点之间的预测方差更小,反之 越小则函数倾向于更加“曲折”,训练数据点之间的预测方差更大; 则直接控制方差大小, 越大方差越大,反之亦然。

如何选择最优的核函数参数 和 呢?答案是最大化在这两个超参数下 出现的概率,通过最大化边缘对数似然(Marginal Log-likelihood)来找到最优的参数,边缘对数似然表示为

具体的实现中,我们在 fit 方法中增加超参数优化这部分的代码,最小化负边缘对数似然。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from scipy.optimize import minimize


class GPR:

    def __init__(self, optimize=True):
        self.is_fit = False
        self.train_X, self.train_y = None, None
        self.params = {"l": 0.5, "sigma_f": 0.2}
        self.optimize = optimize

    def fit(self, X, y):
        # store train data
        self.train_X = np.asarray(X)
        self.train_y = np.asarray(y)

         # hyper parameters optimization
        def negative_log_likelihood_loss(params):
            self.params["l"], self.params["sigma_f"] = params[0], params[1]
            Kyy = self.kernel(self.train_X, self.train_X) + 1e-8 * np.eye(len(self.train_X))
            return 0.5 * self.train_y.T.dot(np.linalg.inv(Kyy)).dot(self.train_y) + 0.5 * np.linalg.slogdet(Kyy)[1] + 0.5 * len(self.train_X) * np.log(2 * np.pi)

        if self.optimize:
            res = minimize(negative_log_likelihood_loss, [self.params["l"], self.params["sigma_f"]],
                   bounds=((1e-4, 1e4), (1e-4, 1e4)),
                   method='L-BFGS-B')
            self.params["l"], self.params["sigma_f"] = res.x[0], res.x[1]

        self.is_fit = True

将训练、优化得到的超参数、预测结果可视化如下图,可以看到最优的

这里用 scikit-learn 的 GaussianProcessRegressor 接口进行对比

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import ConstantKernel, RBF

# fit GPR
kernel = ConstantKernel(constant_value=0.2, constant_value_bounds=(1e-4, 1e4)) * RBF(length_scale=0.5, length_scale_bounds=(1e-4, 1e4))
gpr = GaussianProcessRegressor(kernel=kernel, n_restarts_optimizer=2)
gpr.fit(train_X, train_y)
mu, cov = gpr.predict(test_X, return_cov=True)
test_y = mu.ravel()
uncertainty = 1.96 * np.sqrt(np.diag(cov))

# plotting
plt.figure()
plt.title("l=%.1f sigma_f=%.1f" % (gpr.kernel_.k2.length_scale, gpr.kernel_.k1.constant_value))
plt.fill_between(test_X.ravel(), test_y + uncertainty, test_y - uncertainty, alpha=0.1)
plt.plot(test_X, test_y, label="predict")
plt.scatter(train_X, train_y, label="train", c="red", marker="x")
plt.legend()

得到结果为 ,这个与我们实现的优化得到的超参数有一点点不同,可能是实现的细节有所不同导致。

多维输入

我们上面讨论的训练数据都是一维的,高斯过程直接可以扩展于多维输入的情况,直接将输入维度增加即可。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def y_2d(x, noise_sigma=0.0):
    x = np.asarray(x)
    y = np.sin(0.5 * np.linalg.norm(x, axis=1))
    y += np.random.normal(0, noise_sigma, size=y.shape)
    return y

train_X = np.random.uniform(-4, 4, (100, 2)).tolist()
train_y = y_2d(train_X, noise_sigma=1e-4)

test_d1 = np.arange(-5, 5, 0.2)
test_d2 = np.arange(-5, 5, 0.2)
test_d1, test_d2 = np.meshgrid(test_d1, test_d2)
test_X = [[d1, d2] for d1, d2 in zip(test_d1.ravel(), test_d2.ravel())]

gpr = GPR(optimize=True)
gpr.fit(train_X, train_y)
mu, cov = gpr.predict(test_X)
z = mu.reshape(test_d1.shape)

fig = plt.figure(figsize=(7, 5))
ax = Axes3D(fig)
ax.plot_surface(test_d1, test_d2, z, cmap=cm.coolwarm, linewidth=0, alpha=0.2, antialiased=False)
ax.scatter(np.asarray(train_X)[:,0], np.asarray(train_X)[:,1], train_y, c=train_y, cmap=cm.coolwarm)
ax.contourf(test_d1, test_d2, z, zdir='z', offset=0, cmap=cm.coolwarm, alpha=0.6)
ax.set_title("l=%.2f sigma_f=%.2f" % (gpr.params["l"], gpr.params["sigma_f"]))

下面是一个二维输入数据的高斯过程回归,左图是没有经过超参优化的拟合效果,右图是经过超参优化的拟合效果。

以上相关的代码放在 toys/GP 。

高斯过程回归的优缺点

  • 优点
    • (采用 RBF 作为协方差函数)具有平滑性质,能够拟合非线性数据
    • 高斯过程回归天然支持得到模型关于预测的不确定性(置信区间),直接输出关于预测点值的概率分布
    • 通过最大化边缘似然这一简洁的方式,高斯过程回归可以在不需要交叉验证的情况下给出比较好的正则化效果
  • 缺点
    • 高斯过程是一个非参数模型,每次的 inference 都需要对所有的数据点进行(矩阵求逆)。对于没有经过任何优化的高斯过程回归,n 个样本点时间复杂度大概是 ,空间复杂度是 ,在数据量大的时候高斯过程变得 intractable
    • 高斯过程回归中,先验是一个高斯过程,likelihood 也是高斯的,因此得到的后验仍是高斯过程。在 likelihood 不服从高斯分布的问题中(如分类),需要对得到的后验进行 approximate 使其仍为高斯过程
    • RBF 是最常用的协方差函数,但在实际中通常需要根据问题和数据的性质选择恰当的协方差函数

参考资料

1.Carl Edward Rasmussen - Gaussian Processes for Machine Learning https://www.gaussianprocess.org/gpml/chapters/RW.pdf 2.MLSS 2012 J. Cunningham - Gaussian Processes for Machine Learning https://www.columbia.edu/~jwp2128/Teaching/E6892/papers/mlss2012_cunningham_gaussian_processes.pdf 3.Martin Krasser's blog- Gaussian Processes https://krasserm.github.io/2018/03/19/gaussian-processes/ 4.scikit-learn GaussianProcessRegressor https://scikit-learn.org/stable/modules/generated/sklearn.gaussian_process.GaussianProcessRegressor.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI算法与图像处理 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
使用Searx搭建一个私人的搜索引擎平台,可展现Google/Bing等70多种搜索网站的搜索结果
更多参数设置可以参考https://github.com/asciimoo/searx/wiki/settings.yml。
叮当叮
2020/04/20
4.4K0
使用Searx搭建一个私人的搜索引擎平台,可展现Google/Bing等70多种搜索网站的搜索结果
说明:现在百毒各种犀利操作导致很多人都转向了谷歌,不过由于谷歌在国内被墙,对一些人来说访问起来是有点困难的,除了挂梯子以外,反代谷歌也可以,很久前就发过这种教程→传送门,不过最近找到了个好项目Searx,一个基于Python的完全开源免费搜索引擎平台,为你提供来自Google、Bing、Yahoo等70多种各大视频、图片、搜索、磁力等网站结果展示,并对搜索结果进行优化,同时不会存储你的任何搜索信息,搭建也很方便,有兴趣的可以搭建给需要谷歌的同事或朋友用下。
子润先生
2021/06/01
4.3K0
一款二次元的Web多人在线网络聊天系统:Fiora安装及使用
说明:Fiora是一款偏二次元的Web多人在线聊天应用,使用Node.js、Mongodb、Socket.io和React编写,使用起来还行,挺简洁的,这里水个搭建教程,有兴趣的可以玩玩。
星泽V社
2022/05/30
1.1K0
一款二次元的Web多人在线网络聊天系统:Fiora安装及使用
一个支持多用户的在线书签管理系统:My-BookMark
明:之前一直想找个书签系统,然后最近发现了个My-BookMark,用了下还不错,总算不用经常重复在不同电脑或者浏览器上备份书签了,该工具可以整合多个浏览器上的书签,对于快速搜索某个时间段的书签起到便捷式的作用,有效的避免了你在重装系统和更换浏览器上对书签的备份,无法整合分类和在其他地方上网时无法查看自己的书签!无论你在何时何地都可以查看搜索自己收藏的书签数据,安装也是很简单的,有需求的可以玩玩。
子润先生
2021/05/29
1.4K0
私密的搜索引擎搭建
说明:之前介绍过一个多平台聚合搜索服务Searx,都是以Google等国外搜索为主→传送门,然后这里说的秘迹搜索就是基于Searx二次开发,主要是聚合国内的百度、360、搜狗等搜索服务,专为国人开发,而且秘迹搜索可以最大程度的保护个人搜索隐私,Ta不会根据搜索关键词追踪用户,也不会通过历史搜索内容做广告推荐,目前该搜索源码开源,看见很多人想搭建个,发现教程挺简单的,这里就水个搭建教程。
用户1112170
2019/06/01
1.7K0
私密的搜索引擎搭建
使用FirefoxSend搭建一个临时文件分享系统
说明:Firefox Send是Firefox推出的一個全新的临时文件分享系统,不过貌似代码开源了,也有几个小伙伴搭建的时候遇到了点问题,要博主发个教程,这里就水一下手动搭建和Docker搭建。
栖枝perch
2020/04/02
1.8K0
Shiori:一个简单、美观且带Web界面的书签管理器
说明:Shiori是一个用Go语言编写的简单书签管理器,样式直接模仿的Pocket,有着基本书签管理功能,即添加,编辑,删除和搜索。支持导入和导出成Netscape书签文件,也可以从Pocket导入书签。可以通过命令行操作,也自带简单而漂亮的Web界面,适合那些不想使用命令行的,也可以内页浏览书签首页,用起来还行,这里就分享下。
子润先生
2021/05/28
6150
TopDocs:一款美观实用的在线文档编辑系统,支持Markdown语法
说明:最近博主对文档程序小有需求,找了很久发现都是单页,而且还不支持移动端,不是很理想,所以萌JJ大雕就专门花了半天时间,给博主写了一个,该文档程序基于graphql、nuxtjs、mongodb、keystonejs的实时在线文档编辑系统,可用作各种在线文档编辑和展示,支持markdown语法,对移动端特别友好,这里就开源分享出来,给对文档有需求的人。
子润先生
2021/05/28
1.1K0
一个可以解决因api抽风出现空目录的OneDrive目录程序:OneList
说明:目前OneDrive目录程序已经很多了,比如:PyOne、OneIndex和OLAINDEX。这几个各有特色,都挺好用的,不过有时候api在高峰期抽风的时候,都很容易出现空目录的情况,导致下载会出现问题,这里萌咖和sxyazi大佬就历时N天,写了个基于Python3的简约OneDrive目录列表,同时换了一种api来防止因使用人过多导致抽风等问题,稳定性大大的增加,而且使用Redis动态缓存策略,打开目录的速度是相当的快,不过该程序初衷只想安静的做个目录程序,所以是不会增加看视频的功能,如果你想看视频,那就选择开头的3个程序。
子润先生
2021/05/29
8200
Filestash:一个多功能的Web端文件管理器,支持SFTP/GDrive/Dropbox/S3等
说明:Filestash是一个类似Dropbox的文件管理器,通过浏览器即可使用,可让您在任何位置管理数据。包括上传文件和文件夹,编辑文件,音频播放器,视频播放器,图像查看器。目前支持FTP、SFTP、WebDAV、Git、S3、Minio Dropbox、Google Drive,貌似以后还会增加OneDrive,而且登录访问速度很快,可以拿来修改VPS或网盘文件,或者看看里面的小电影也行,安装方法也挺简单的,就一个Docker,这里说一下。
子润先生
2021/06/01
2.8K0
安装10分钟临时邮箱Forsaken Mail教程【实用篇】
当我们注册一些网站的时候,我们不想用自己的邮箱注册,因为不想接收那些垃圾推广广告,这个时候我们需要一个方便快捷,点击即用的邮箱,就类似于那个著名的10分钟临时邮箱网站,当10分钟一到,如果用户不在点击续用,邮箱就会自毁
夏末浅笑
2018/10/14
7.9K0
sish:一个开源、轻量且类似于Servo/Ngrok的内网穿透工具
说明:sish是一个SSH服务器,仅用于远程端口转发,可以快速将本地端口暴露在外网,作者声称其为Servo/Ngrok替代方案,仅使用SSH的HTTP(S)、WS(S)、TCP隧道连接到他们的localhost服务器,该工具和Servo差不多一样,不同就是Servo官方提供了免费的SSH客户端,而sish作者提供的客户端貌似因为滥用关闭了,所以就需要我们自己搭建了,这里就水下Docker和手动安装。
子润先生
2021/05/28
2.3K1
使用Plik搭建一个临时文件上传系统,自定义时长/下载即摧毁
说明:Plik是一个基于golang的可扩展且友好的临时文件上传系统。上传者可自定义文件保留时长,设置下载密码,允许上传者随时删除文件,设置下载一次就自动删除,二维码下载,上传者还可以选择不保存在服务器里,直接传到免费服务(貌似用的ShareX),还支持在线播放mp3/mp4文件,及一些功能拓展,挺强的,安装也简单。
用户1202364
2018/10/31
1.7K0
一款开源、轻巧且功能齐全的跨平台网盘程序:蓝眼云盘
说明:最近发现了一个不错的网盘程序蓝眼云盘,该程序后端使用golang开发,前端使用vue套件开发,而且开源免费,基本上目前除了离线下载外,其它功能都有,同时也支持多用户,超级管理员可以对用户进行权限,文件管理等,外观也蛮好看,安装包仅10M左右,可以同时在Windows、Linux、Mac OS操作系统中运行。作者更新也很频繁,功能也会越来越多,这里就大概说下安装方法。
子润先生
2021/06/01
2.9K0
一个简单的PHP Web代理:miniProxy
说明:miniProxy是一个用PHP编写的简单Web代理,可以让您绕过网页过滤器,或匿名浏览网页。一般我们可以拿来访问谷歌查询学习资料等,对于谷歌重度使用者或者需要经常使用谷歌的团队/班级来说,还是挺方便的,毕竟不用梯子就可以直接访问谷歌了。
小狐狸说事
2022/11/16
8260
一个简单的PHP Web代理:miniProxy
Lstu:一款简单、美观的轻量级网址缩短程序
说明:Lstu是一个使用Perl编写的轻量级短网址程序,还提供api、二维码生成、统计面板、网址导入和导出等功能,界面挺简洁的,用起来还行,这里就发个手动和Docker安装。
子润先生
2021/05/28
7800
一个简单的PHP Web代理:miniProxy
说明:miniProxy是一个用PHP编写的简单Web代理,可以让您绕过网页过滤器,或匿名浏览网页。一般我们可以拿来访问谷歌查询学习资料等,对于谷歌重度使用者或者需要经常使用谷歌的团队/班级来说,还是挺方便的,毕竟不用梯子就可以直接访问谷歌了。
青阳
2021/09/11
3.2K0
live-torrent:一个支持磁力链和种子的在线搜索云播Web客户端
说明:live-torrent是一个功能强大的BT Web客户端工具,支持BT搜索和云播,我们可以直接使用程序内置的引擎搜索查找资源,也可以自行上传种子文件或磁力链接添加任务,程序支持自动识别种子内视频文件,点击播放按钮可以直接在线播放,该程序支持对接OpenSubtitles,自动给视频添加字幕。同时也提供一个热门电影排行榜,并提供对应资源给你播放和下载。不过唯一有点小遗憾的就是,不支持在线搜索中文资源,所以中文资源只能自己上传种子文件进行识别播放下载。
用户8851537
2021/08/16
6.6K0
使用Instantbox快速搭建一个开箱即用的Web端临时Linux系统
我们很多时候想学习下Linux或者程序搭建,然后出错了,不会解决的可能会直接重装系统,很麻烦,然后这里博主就找到了个可以解决该问题的工具instantbox,使用该工具可以让你仅通过浏览器的情况下,快速创建一个开箱即用的Linux系统,可以随时调整配置、使用时长,不用的话可以直接删掉,目前有Ubuntu、CentOS、Debian、Alpine等主流系统,不过由于是通过Docker实现的,所以平时有些命令操作肯定是不能用了,但一般情况下还是可以满足需求的,搭建方法也是超简单,这里说下。
王图思睿
2021/06/15
5430
使用Instantbox快速搭建一个开箱即用的Web端临时Linux系统
一款开源,简单的轻量级RSS阅读器:selfoss安装教程
说明:关于RSS订阅器,之前发过不少了,比如Feedbin、FreshRSS等,功能都挺强大的,这里就再介绍个轻量级的RSS订阅器selfoss,使用起来是非常简单的,界面颜值也还不错,支持很多种订阅和网站,比如Twitter、Github、Tumblr等。
子润先生
2021/05/28
1.2K0
推荐阅读
相关推荐
使用Searx搭建一个私人的搜索引擎平台,可展现Google/Bing等70多种搜索网站的搜索结果
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验