IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> MATLAB | 赠书 | 逻辑回归(Logistic Regression) -> 正文阅读

[数据结构与算法]MATLAB | 赠书 | 逻辑回归(Logistic Regression)

微信公众号 slandarer随笔
这篇文章正在抽奖赠书
欢迎过去参与抽奖,文末有该书更详细介绍:
请在微信打开抽奖地址

抽奖推送链接:抽奖地址

在这里插入图片描述

之前的最小二乘法的两种解读那篇文章,我们拟合了多项式,拟合了线性多元函数,我们的函数映射结果是数值,但我们想要的得到的结果如果不是数值,而是(是/否)(TRUE/FALSE)应该怎么做?此即逻辑回归。

代价函数及其梯度(Cost function and gradient)

首先来看要拟合的函数,下面是我们之前拟合的函数的形式,很明显拟合结果为一个数值。
h θ ( x ) = θ T x = ∑ i = 0 n θ i x i = θ 0 + θ 1 x 1 + ? + θ n x n h_{\theta}(x)=\theta^Tx=\sum_{i=0}^{n} \theta_{i} x_{i}=\theta_{0}+\theta_{1} x_{1}+\cdots+\theta_{n} x_{n} hθ?(x)=θTx=i=0n?θi?xi?=θ0?+θ1?x1?+?+θn?xn?
我们想要将一个范围 ( ? ∞ , ∞ ) (-\infty,\infty) (?,)的数值映射到(是/否)(1/0)我们非常自然的能够想到sigmoid函数,这是一个能将数值从 ( ? ∞ , ∞ ) (-\infty,\infty) (?,)映射到 ( 0 , 1 ) (0,1) (0,1)的函数:
g ( z ) = 1 1 + e ? z g(z)=\frac{1}{1+e^{-z}} g(z)=1+e?z1?
在这里插入图片描述

我们直接把sigmoid函数往原本的拟合函数外面一套,拟合的函数不就能把变量很顺滑的映射到 ( 0 , 1 ) (0,1) (0,1)了嘛,然后我们认为大于0.5就代表是,小于0.5就代表否,美滋滋:
h θ ( x ) = g ( θ T x ) h_{\theta}(x)=g(\theta^Tx) hθ?(x)=g(θTx)

我们再来看代价函数的改变,代价函数我们并没用平常的平方损失函数,而是用了如下的一个形式:
J ( θ ) = 1 m ∑ i = 1 m [ ? y ( i ) log ? ( h θ ( x ( i ) ) ) ? ( 1 ? y ( i ) ) log ? ( 1 ? h θ ( x ( i ) ) ) ] J(\theta)=\frac{1}{m} \sum_{i=1}^{m}\left[-y^{(i)} \log \left(h_{\theta}\left(x^{(i)}\right)\right)-\left(1-y^{(i)}\right) \log \left(1-h_{\theta}\left(x^{(i)}\right)\right)\right] J(θ)=m1?i=1m?[?y(i)log(hθ?(x(i)))?(1?y(i))log(1?hθ?(x(i)))]
别看这个形式有些复杂,但其实并没有那么可怕,首先它将m个数据组都带入了后面的式子求了一个均值。而对于单独一组数据,我们的代价函数的形式是下面这样的:
J ( θ ) = ? y log ? ( h θ ( x ) ) ? ( 1 ? y ) log ? ( 1 ? h θ ( x ) ) J(\theta)=-y\log \left(h_{\theta}\left(x\right)\right)-\left(1-y\right) \log \left(1-h_{\theta}\left(x\right)\right) J(θ)=?ylog(hθ?(x))?(1?y)log(1?hθ?(x))
我们的y值取值只有(1/0),x很难真正取到正负无穷,也就是说 h θ ( x ) h_{\theta}(x) hθ?(x)范围为(0,1)并不会真正取到两端点,这时候代价函数可以看作一个条件函数:
J ( θ ) = { ? log ? ( h θ ( x ) ) y = 1 ? log ? ( 1 ? h θ ( x ) ) y = 0 J(\theta)=\begin{cases} -\log \left(h_{\theta}\left(x\right)\right) &y=1\\ -\log \left(1-h_{\theta}\left(x\right)\right) &y=0 \end{cases} J(θ)={?log(hθ?(x))?log(1?hθ?(x))?y=1y=0?
y=1时,我们考察的是 h θ ( x ) h_{\theta}(x) hθ?(x)与1的接近程度,越接近1, ? log ? ( h θ ( x ) ) -\log(h_{\theta}(x)) ?log(hθ?(x))就越趋紧于0,y=0时,我们考察的是 1 ? h θ ( x ) 1-h_{\theta}(x) 1?hθ?(x)与1的接近程度,越接近1, ? log ? ( 1 ? h θ ( x ) ) -\log(1-h_{\theta}(x)) ?log(1?hθ?(x))就越趋紧于0,总而言之,这是一个越接近真实值,计算值越接近0,越远离真实值,计算值越接近正无穷的非常巧妙的函数。

我们要求代价函数的极小值点,当然还是要让偏导等于0,这里我们对 J ( θ ) J(\theta) J(θ)求一下偏导,这玩意没那么好求,因此我们就一层一层来呗,先研究对sigmoid函数求导,再研究对 h θ ( x ) h_{\theta}(x) hθ?(x)求偏导然后链式求导法则走起来:

第三层求导:
g ( z ) = 1 1 + e ? z g ′ ( z ) = e ? z ( 1 + e ? z ) 2 = 1 + e ? z ? 1 ( 1 + e ? z ) 2 = 1 1 + e ? z ( 1 + e ? z ? 1 1 + e ? z ) = g ( z ) ( 1 ? g ( z ) ) \begin{aligned} g(z)&=\frac{1}{1+e^{-z}}\\ g'(z)&=\frac{e^{-z}}{(1+e^{-z})^2}=\frac{1+e^{-z}-1}{(1+e^{-z})^2}\\ &=\frac{1}{1+e^{-z}}(\frac{1+e^{-z}-1}{1+e^{-z}})\\ &=g(z)(1-g(z)) \end{aligned} g(z)g(z)?=1+e?z1?=(1+e?z)2e?z?=(1+e?z)21+e?z?1?=1+e?z1?(1+e?z1+e?z?1?)=g(z)(1?g(z))?

第二层求导:
h θ ( x ) = g ( θ T x ) = 1 1 + e ? θ T x = 1 1 + e ? ( θ 0 + θ 1 x 1 + ? + θ n x n ) ? h θ ( x ) ? θ j = 1 1 + e ? ( θ 0 + θ 1 x 1 + ? + θ n x n ) ( 1 ? 1 1 + e ? ( θ 0 + θ 1 x 1 + ? + θ n x n ) ) x j = h θ ( x ) ( 1 ? h θ ( x ) ) x j ? l o g ( h θ ( x ) ) ? θ j = h θ ( x ) ( 1 ? h θ ( x ) ) x j h θ ( x ) = ( 1 ? h θ ( x ) ) x j ? l o g ( 1 ? h θ ( x ) ) ? θ j = ? h θ ( x ) ( 1 ? h θ ( x ) ) x j 1 ? h θ ( x ) = ? h θ ( x ) x j \begin{aligned} h_{\theta}(x)&=g(\theta^Tx)=\frac{1}{1+e^{-\theta^Tx}}=\frac{1}{1+e^{-(\theta_{0}+\theta_{1} x_{1}+\cdots+\theta_{n} x_{n})}}\\ \\ \frac{\partial h_{\theta}(x)}{\partial\theta_{j}}&= \frac{1}{1+e^{-(\theta_{0}+\theta_{1} x_{1}+\cdots+\theta_{n} x_{n})}}\left(1-\frac{1}{1+e^{-(\theta_{0}+\theta_{1} x_{1}+\cdots+\theta_{n} x_{n})}}\right)x_j\\ &=h_{\theta}(x)(1-h_{\theta}(x))x_j\\ \\ \frac{\partial log(h_{\theta}(x))}{\partial\theta_{j}}&= \frac{h_{\theta}(x)(1-h_{\theta}(x))x_j}{h_{\theta}(x)}\\ &=(1-h_{\theta}(x))x_j\\ \\ \frac{\partial log(1-h_{\theta}(x))}{\partial\theta_{j}}&= \frac{-h_{\theta}(x)(1-h_{\theta}(x))x_j}{1-h_{\theta}(x)}\\ &=-h_{\theta}(x)x_j \end{aligned} hθ?(x)?θj??hθ?(x)??θj??log(hθ?(x))??θj??log(1?hθ?(x))??=g(θTx)=1+e?θTx1?=1+e?(θ0?+θ1?x1?+?+θn?xn?)1?=1+e?(θ0?+θ1?x1?+?+θn?xn?)1?(1?1+e?(θ0?+θ1?x1?+?+θn?xn?)1?)xj?=hθ?(x)(1?hθ?(x))xj?=hθ?(x)hθ?(x)(1?hθ?(x))xj??=(1?hθ?(x))xj?=1?hθ?(x)?hθ?(x)(1?hθ?(x))xj??=?hθ?(x)xj??

第一层求导:

先看看对于一组数据:
J ( θ ) = ? y log ? ( h θ ( x ) ) ? ( 1 ? y ) log ? ( 1 ? h θ ( x ) ) ? J ( θ ) ? θ j = ? y ( 1 ? h θ ( x ) ) x j + ( 1 ? y ) h θ ( x ) x j = ? y x j + y h θ ( x ) x j + h θ ( x ) x j ? y h θ ( x ) x j = ( h θ ( x ) ? y ) x j \begin{aligned} J(\theta)&=-y\log(h_{\theta}(x))-(1-y)\log(1-h_{\theta}(x))\\ \frac{\partial J(\theta)}{\partial\theta_{j}}&= -y(1-h_{\theta}(x))x_j+(1-y)h_{\theta}(x)x_j\\ &=-yx_j+yh_{\theta}(x)x_j+h_{\theta}(x)x_j-yh_{\theta}(x)x_j\\ &=(h_{\theta}(x)-y)x_j \end{aligned} J(θ)?θj??J(θ)??=?ylog(hθ?(x))?(1?y)log(1?hθ?(x))=?y(1?hθ?(x))xj?+(1?y)hθ?(x)xj?=?yxj?+yhθ?(x)xj?+hθ?(x)xj??yhθ?(x)xj?=(hθ?(x)?y)xj??

对于m组数据则有:
? J ( θ ) ? θ j = 1 m ∑ i = 1 m ( h θ ( x ( i ) ) ? y ( i ) ) x j ( i ) \frac{\partial J(\theta)}{\partial \theta_{j}}=\frac{1}{m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right) x_{j}^{(i)} ?θj??J(θ)?=m1?i=1m?(hθ?(x(i))?y(i))xj(i)?

特征映射(Feature mapping)

其次再看特征映射,对于如下情况我们假设横坐标为 x 1 x_1 x1?,纵坐标为 x 2 x_2 x2?:
在这里插入图片描述

很明显分类结果不光和 x 1 , x 2 x_1,x_2 x1?,x2?有关,还和交叉项有关,其次我们想到之前最小二乘法那篇时,我们使用了 1 , x , x 2 , x 3 , … 1,x,x^2,x^3,\dots 1,x,x2,x3,一系列项来拟合函数,在这里我们也很自然的能想到用 1 , x 1 , x 2 , x 1 2 , x 1 x 2 , x 2 2 , x 1 3 , x 1 2 x 2 , … 1,x_1,x_2,x_1^2,x_1x_2,x_2^2,x_1^3,x_1^2x_2,\dots 1,x1?,x2?,x12?,x1?x2?,x22?,x13?,x12?x2?,等一系列项来拟合函数,这里我们用了的项的最高次为6次,因而一共有28项:

m a p F e a t u r e ( x ) = ( ∣ ∣ ∣ ∣ ∣ ∣ ∣ … 1 x 1 x 2 x 1 2 x 1 x 2 x 2 2 x 1 3 … ∣ ∣ ∣ ∣ ∣ ∣ ∣ … ) mapFeature(x)=\begin{pmatrix} \mid & \mid & \mid & \mid & \mid & \mid & \mid &\dots \\ 1& x_1& x_2& x_1^2& x_1x_2& x_2^2& x_1^3&\dots \\ \mid & \mid & \mid & \mid & \mid & \mid & \mid &\dots \end{pmatrix} mapFeature(x)=???1?x1??x2??x12??x1?x2??x22??x13??????

正则化逻辑回归(Regularized logistic regression)

讲明白啥是逻辑回归,这里再说明一下正则化的作用,我们要对逻辑回归进行正则化首先是要防止其过拟合和欠拟合(主要是过拟合),就是防止图中左图及右图的情况:
在这里插入图片描述

什么时候容易出现左图情况?就是拟合所用的参数数量比较少,或者说大部分系数数值比较小的情况,而出现右图这种情况一般是参数数量比较多,或者说部分没那么重要的系数数值比较大的情况,因此我们想要拟合结果合理,我们有两种途径,一是调整参数数量,另一个便是将系数数值限定在一定范围内,这里正则化就是用到的第二种方法,我们将代价函数改写为:
J ( θ ) = 1 m ∑ i = 1 m [ ? y ( i ) log ? ( h θ ( x ( i ) ) ) ? ( 1 ? y ( i ) ) log ? ( 1 ? h θ ( x ( i ) ) ) ] + λ 2 m ∑ j = 1 n θ j 2 J(\theta)=\frac{1}{m} \sum_{i=1}^{m}\left[-y^{(i)} \log \left(h_{\theta}\left(x^{(i)}\right)\right)-\left(1-y^{(i)}\right) \log \left(1-h_{\theta}\left(x^{(i)}\right)\right)\right]+\frac{\lambda}{2 m} \sum_{j=1}^{n} \theta_{j}^{2} J(θ)=m1?i=1m?[?y(i)log(hθ?(x(i)))?(1?y(i))log(1?hθ?(x(i)))]+2mλ?j=1n?θj2?
这样就能起到限制 θ \theta θ大小的作用,需要注意的是 λ \lambda λ过大容易让 θ \theta θ过小从而出现欠拟合, λ \lambda λ过小甚至为0容易让 θ \theta θ过大从而出现过拟合,因此调节合适的 λ \lambda λ大小非常重要。相应的偏导也变为:
? J ( θ ) ? θ j = ( 1 m ∑ i = 1 m ( h θ ( x ( i ) ) ? y ( i ) ) x j ( i ) ) + λ m θ j \frac{\partial J(\theta)}{\partial \theta_{j}}=\left(\frac{1}{m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right) x_{j}^{(i)}\right)+\frac{\lambda}{m} \theta_{j} ?θj??J(θ)?=(m1?i=1m?(hθ?(x(i))?y(i))xj(i)?)+mλ?θj?

代码部分

数据来源于吴恩达的Machine Learning | Programming Exercise 2: Logistic Regression,这个练习2的完整文件及数据也会和完整代码一块放到文末提供的压缩包内。
数据是某一制造厂微芯片的两次测试结果及合格情况,数据第一第二列为两次测试结果,第三列为合格情况,合格记为1,不合格记为0。

导入数据并绘图

% 数据导入
oriData=readmatrix('ex2data2.txt'); 
X=oriData(:,[1,2]); 
y=oriData(:,3);

% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
% 绘制图像
ax=gca;
hold(ax,'on')
plot(X(y==0,1),X(y==0,2),'ko','MarkerFaceColor','y','MarkerSize',7)
plot(X(y==1,1),X(y==1,2),'k+','LineWidth',2,'MarkerSize',7)

% 修饰一下
grid(ax,'on')
ax.FontName='cambria';
ax.XColor=[1,1,1].*.3;
ax.YColor=[1,1,1].*.3;
ax.ZColor=[1,1,1].*.3;
ax.LineWidth=1.5;
ax.GridLineStyle='--';
ax.DataAspectRatio=[1,1,1];

在这里插入图片描述

数据特征映射

%X变量进行扩充为X_exp
% X_exp第一列为数值1
% degree为X1和X2的次数和(阶数),例如X1*X^2的degree为3
% 我们认为y的取值不光与X1,X2有关,还和其次方项及交叉项有关
% 该过程就是将原本两项[X1,X2],扩充为包含常数项在内的28% [X1,X2] => [1,X1,X2,X1^2,X1X2,X2^2,X1^3,X1^2*X2,X1*X2^2,X2^3,......]
degree=6;
X_exp=ones(size(X(:,1)));
for i=1:degree
    for j=0:i
        X_exp(:,end+1)=(X(:,1).^(i-j)).*(X(:,2).^j);
    end
end

构造代价函数及sigmoid函数

% sigmoid函数
function g=sigmoid(z)
g=1./(1+exp(-z));
end

% 梯度及代价值计算函数
function [J,grad]=costFunctionReg(theta,X,y,lambda)
m=length(y);

h_theta=sigmoid(X*theta);
J=sum(-y.*log(h_theta)-(1-y).*log(1-h_theta))/m+sum(theta(2:end).^2)*lambda/2/m;

grad=(sum((h_theta-y).*X,1)./m)'+[0;theta(2:end).*lambda./m];
end

求解

% 设置初始参数和梯度下降率
initial_theta=zeros(size(X_exp,2),1);
lambda=1;

% 设置条件并用自带函数寻找最优参数
options=optimset('GradObj','on','MaxIter',400);
[theta,J,exit_flag]= ...
	fminunc(@(t)(costFunctionReg(t,X_exp,y,lambda)),initial_theta,options);

绘制分界曲线

% 绘制分界曲线
degree=6;
X_sym=sym('1');
for i=1:degree
    for j=0:i
        X_sym(:,end+1)=(sym('x').^(i-j)).*(sym('y').^j);
    end
end

Func=matlabFunction(1./(1+exp(X_sym*theta))-.5);
fimplicit(Func,'LineWidth',2,'Color',[169,64,71]./255)

在这里插入图片描述

计算正确率

% 将根据梯度下降法得出的预测结果与实际情况对比,并计算正确率
p=sigmoid(X_exp*theta)>.5;
ac=mean(double(p == y))*100;
fprintf('准确率为: %f\n', ac);

完整代码

%@author:slandarer

% 数据导入
oriData=readmatrix('ex2data2.txt'); 
X=oriData(:,[1,2]); 
y=oriData(:,3);

% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
% 绘制图像
ax=gca;
hold(ax,'on')
plot(X(y==0,1),X(y==0,2),'ko','MarkerFaceColor','y','MarkerSize',7)
plot(X(y==1,1),X(y==1,2),'k+','LineWidth',2,'MarkerSize',7)

% 修饰一下
grid(ax,'on')
ax.FontName='cambria';
ax.XColor=[1,1,1].*.3;
ax.YColor=[1,1,1].*.3;
ax.ZColor=[1,1,1].*.3;
ax.LineWidth=1.5;
ax.GridLineStyle='--';
ax.DataAspectRatio=[1,1,1];

% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
%X变量进行扩充为X_exp
% X_exp第一列为数值1
% degree为X1和X2的次数和(阶数),例如X1*X^2的degree为3
% 我们认为y的取值不光与X1,X2有关,还和其次方项及交叉项有关
% 该过程就是将原本两项[X1,X2],扩充为包含常数项在内的28% [X1,X2] => [1,X1,X2,X1^2,X1X2,X2^2,X1^3,X1^2*X2,X1*X2^2,X2^3,......]
degree=6;
X_exp=ones(size(X(:,1)));
for i=1:degree
    for j=0:i
        X_exp(:,end+1)=(X(:,1).^(i-j)).*(X(:,2).^j);
    end
end

% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
% 设置初始参数和梯度下降率
initial_theta=zeros(size(X_exp,2),1);
lambda=1;

% 设置条件并用自带函数寻找最优参数
options=optimset('GradObj','on','MaxIter',400);
[theta,J,exit_flag]= ...
	fminunc(@(t)(costFunctionReg(t,X_exp,y,lambda)),initial_theta,options);


% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
% 绘制分界曲线
degree=6;
X_sym=sym('1');
for i=1:degree
    for j=0:i
        X_sym(:,end+1)=(sym('x').^(i-j)).*(sym('y').^j);
    end
end

Func=matlabFunction(1./(1+exp(X_sym*theta))-.5);
fimplicit(Func,'LineWidth',2,'Color',[169,64,71]./255)

% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
% 将根据梯度下降法得出的预测结果与实际情况对比,并计算正确率
p=sigmoid(X_exp*theta)>.5;
ac=mean(double(p == y))*100;
fprintf('准确率为: %f\n', ac);


% =========================================================================
% sigmoid函数
function g=sigmoid(z)
g=1./(1+exp(-z));
end

% 梯度及代价值计算函数
function [J,grad]=costFunctionReg(theta,X,y,lambda)
m=length(y);

h_theta=sigmoid(X*theta);
J=sum(-y.*log(h_theta)-(1-y).*log(1-h_theta))/m+sum(theta(2:end).^2)*lambda/2/m;

grad=(sum((h_theta-y).*X,1)./m)'+[0;theta(2:end).*lambda./m];
end

完整文件压缩包

链接: https://pan.baidu.com/s/1YIWxRx1qShsbYytjv-yrcA?pwd=slan
提取码: slan

赠书介绍

在这里插入图片描述

本书以简单的组合优化问题作为MATLAB智能优化算法实战应用的切入点,逐步深入使用MATLAB编写更复杂的智能优化算法和求解更复杂的组合优化问题,通过9个常见的组合优化问题、5个经典的智能优化算法及4个新颖的智能优化算法,让读者逐渐理解智能优化算法的实际求解过程、算法设计思路及代码编写思路。

目录

(1)遗传算法求解0-1背包问题;
(2)变邻域搜索算法求解旅行商问题
(3)大规模邻域搜索算法求解旅行商问题
(4)灰狼优化算法求解多旅行商问题
(5)蚁群算法求解容量受限的车辆路径问题
(6)模拟退火算法求解同时取送货的车辆路径问题
(7)遗传算法求解带时间窗的车辆路径问题
(8)萤火虫算法求解订单分批问题
(9)头脑风暴优化算法求解带时间窗和同时取送货的车辆路径问题
(10)鲸鱼优化算法求解开放式车辆路径问题。

抽奖地址=〉抽奖地址

微信公众号地址=〉

在这里插入图片描述
当然即使没有抽中也可以在如下链接进行购买:https://item.jd.com/13422442.html

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-01-25 10:49:54  更:2022-01-25 10:50:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 19:47:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码