【吴恩达机器学习-week2】多个变量的特征缩放和学习率问题

特征缩放和学习率(多变量)

目标

  • 利用上一个实验中开发的多变量例程
  • 在具有多个特征的数据集上运行梯度下降
  • 探索学习率对梯度下降的影响
  • 通过 Z 分数归一化进行特征缩放,提高梯度下降的性能
import numpy as np
np.set_printoptions(precision=2)
import matplotlib.pyplot as plt
dlblue = '#0096ff'; dlorange = '#FF9300'; dldarkred='#C00000'; dlmagenta='#FF40FF'; dlpurple='#7030A0'; 
plt.style.use('./deeplearning.mplstyle')
from lab_utils_multi import  load_house_data, compute_cost, run_gradient_descent 
from lab_utils_multi import  norm_plot, plt_contour_multi, plt_equal_scale, plot_cost_i_w
  • 解释一下:np.set_printoptions(precision=2)

    np.set_printoptions(precision=2) 是 NumPy 中的函数,用于设置打印数组时的精度。通过设置 precision 参数为 2,它会将浮点数数组的打印精度限制为小数点后两位。这样可以使输出更加整洁和易读,尤其是在处理大型数组时。

问题陈述

与之前的实验类似,你将使用房价预测的示例。训练数据集包含许多具有 4 个特征(面积、卧室数、楼层数和房龄)的示例,如下表所示。请注意,在本实验中,大小特征是以平方英尺为单位的,而之前的实验中使用的是 1000 平方英尺。这个数据集比之前的实验数据集要大。

我们希望使用这些值构建一个线性回归模型,以便我们可以预测其他房屋的价格 - 比如,一所面积为 1200 平方英尺,有 3 间卧室,1 层,40 年房龄的房屋的价格。

数据集:

大小(平方英尺)卧室数楼层数房龄价格(1000美元)
9522165271.5
12443264232
19473217509.8
# load the dataset
X_train, y_train = load_house_data()
X_features = ['size(sqft)','bedrooms','floors','age']
  • 解释一下:X_train, y_train = load_house_data()

    def load_house_data():data = np.loadtxt("./data/houses.txt", delimiter=',', skiprows=1)X = data[:,:4]y = data[:,4]return X, y
    

    这段代码定义了一个名为 load_house_data 的函数,用于加载房屋数据集。

    函数的主要步骤如下:

    1. 使用 NumPy 的 loadtxt 函数从指定路径的文件中加载数据集。加载的文件是一个以逗号分隔的文本文件,其中第一行是列标题,因此我们通过 skiprows=1 参数跳过第一行
    2. 将加载的数据集分成特征矩阵 X 和目标向量 y。特征矩阵 X 包含所有行的前四列,而目标向量 y 包含所有行的第五列
    3. 最后,函数返回特征矩阵 X 和目标向量 y

    通过这个函数,我们可以方便地加载房屋数据集,并将其用于训练线性回归模型。

    • data[:,:4] 的含义

      是对二维数组 data 进行的切片操作。

      在二维数组中,使用逗号分隔的切片操作是针对行和列进行切片的。第一个 : 表示对行进行切片,第二个 :4 表示对列进行切片。

      因此,data[:,:4] 返回的是二维数组 data 的所有行和前四列的子数组,即一个二维的切片。

让我们通过绘制每个特征与价格的关系来查看数据集及其特征。

fig,ax=plt.subplots(1, 4, figsize=(12, 3), sharey=True)
for i in range(len(ax)):ax[i].scatter(X_train[:,i],y_train)ax[i].set_xlabel(X_features[i])
ax[0].set_ylabel("Price (1000's)")
plt.show()
  • 解释一下:sharey=True

    sharey=True指定了子图共享y轴。这意味着子图将共享相同的 y 轴范围,使得它们在垂直方向上对齐,并且更容易进行比较。

  • ax 是什么

    在Matplotlib中,ax 通常是指代图形中的坐标轴对象。在这个例子中,ax是一个包含四个子图坐标轴对象的数组。每个子图都可以在对应的坐标轴对象上进行绘图。

  • 解释一下:ax[i].scatter(X_train[:,i],y_train)

    • ax[i].scatter(X_train[:,i],y_train):这在第 i 个子图(ax[i])上绘制了一个散点图,其中 X_train[:,i] 表示训练数据中所有行的第 i 个特征的值,而 y_train 表示目标变量(通常是价格)。它显示了每个特征与目标变量之间的个别关系。
  • 解释一下:ax[i].set_xlabel(X_features[i])

    ax[i].set_xlabel(X_features[i]):这将第 i 个子图的 x 轴标签设置为第 i 个特征的名称X_features[i])。这有助于识别哪个特征正在被绘制。

  • 解释一下:ax[0].set_ylabel("Price (1000's)")

    这将第一个子图(因为 Python 的索引从0开始)的 y 轴标签设置为“价格(以千为单位)”。这表明目标变量表示价格,可能以千为单位。PS:因为 sharey=True ,所以只用设置一个子图的 y 轴标签

在这里插入图片描述

绘制每个特征与目标变量价格的图表,可以提供一些关于哪些特征对价格影响最大的线索。从上面的结果可以看出,房屋尺寸增加也会增加价格。卧室数量和楼层数似乎对价格影响不大。新房比旧房价格更高。

多变量梯度下降

以下是你在上一个实验室中开发的多变量梯度下降的方程式:

重复执行直到收敛: { w j : = w j − α ∂ J ( w , b ) ∂ w j 对于 j = 0..n-1 b : = b − α ∂ J ( w , b ) ∂ b } \begin{align*} \text{重复执行直到收敛:} \; \lbrace \newline\; & w_j := w_j - \alpha \frac{\partial J(\mathbf{w},b)}{\partial w_j} \tag{1} \; & \text{对于 j = 0..n-1}\newline & b\ \ := b - \alpha \frac{\partial J(\mathbf{w},b)}{\partial b} \newline \rbrace \end{align*} 重复执行直到收敛:{}wj:=wjαwjJ(w,b)b  :=bαbJ(w,b)对于 j = 0..n-1(1)

其中, n n n 是特征数量,参数 w j w_j wj b b b 同时更新,并且

∂ J ( w , b ) ∂ w j = 1 m ∑ i = 0 m − 1 ( f w , b ( x ( i ) ) − y ( i ) ) x j ( i ) ∂ J ( w , b ) ∂ b = 1 m ∑ i = 0 m − 1 ( f w , b ( x ( i ) ) − y ( i ) ) \begin{align} \frac{\partial J(\mathbf{w},b)}{\partial w_j} &= \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)})x_{j}^{(i)} \tag{2} \\ \frac{\partial J(\mathbf{w},b)}{\partial b} &= \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{\mathbf{w},b}(\mathbf{x}^{(i)}) - y^{(i)}) \tag{3} \end{align} wjJ(w,b)bJ(w,b)=m1i=0m1(fw,b(x(i))y(i))xj(i)=m1i=0m1(fw,b(x(i))y(i))(2)(3)

  • m m m 是数据集中的训练样本数量
  • f w , b ( x ( i ) ) f_{\mathbf{w},b}(\mathbf{x}^{(i)}) fw,b(x(i))是模型的预测值,而 y ( i ) y^{(i)} y(i) 是目标值

学习率

在讲座中讨论了一些与设置学习率 α \alpha α 相关的问题。学习率控制了参数更新的大小。参见上面的方程 ( 1 ) (1) 1。学习率是所有参数共享的。

让我们运行梯度下降算法,并尝试在我们的数据集上尝试几种 α \alpha α 的设置。

α = 9.9 e − 7 \alpha = 9.9e-7 α=9.9e7

#set alpha to 9.9e-7
_, _, hist = run_gradient_descent(X_train, y_train, 10, alpha = 9.9e-7)
  • run_gradient_descent 的实现:

    def run_gradient_descent(X,y,iterations=1000, alpha = 1e-6):m,n = X.shape # m 是训练集的个数,n 是特征值的个数(w 的个数)# initialize parametersinitial_w = np.zeros(n)initial_b = 0# run gradient descentw_out, b_out, hist_out = gradient_descent_houses(X ,y, initial_w, initial_b,compute_cost, compute_gradient_matrix, alpha, iterations)print(f"w,b found by gradient descent: w: {w_out}, b: {b_out:0.2f}")return(w_out, b_out, hist_out)
    

此时学习率太高了。解决方案没有收敛。成本增加而不是减少。让我们绘制结果:

plot_cost_i_w(X_train, y_train, hist)

在这里插入图片描述

右边的图显示了其中一个参数的值。在每次迭代中,它都会超过最优值,结果导致成本增加而不是接近最小值。请注意,这不是一个完全准确的图像,因为每次迭代都会修改4个参数,而不仅仅是一个参数。此图仅显示了其中一个参数的值,而其他参数保持在良好的值。在这个和后面的图中,你可能会注意到蓝线和橙线略微偏离。

α = 1 e − 7 \alpha = 1e-7 α=1e7

在这里插入图片描述

特征缩放

  • 为什么要进行特征缩放

    进行特征缩放的主要原因是确保不同特征具有相似的范围和尺度。这在机器学习中是很重要的,因为许多机器学习算法都假设输入特征具有相似的尺度。特征缩放有几个重要的原因:

    1. 加速收敛速度:在梯度下降等优化算法中,特征缩放可以使目标函数更快地收敛。如果特征具有不同的范围和尺度,那么梯度下降算法可能会在某些方向上进行更大的更新,而在其他方向上进行更小的更新,导致收敛速度变慢。
    2. 避免算法偏向:如果某些特征具有较大的范围,那么它们对目标函数的影响可能会比其他特征更大。这可能会导致算法更倾向于关注那些范围较大的特征,而忽略其他特征。通过进行特征缩放,可以确保所有特征对目标函数的影响是相似的,避免算法偏向。
    3. 提高模型性能:在某些情况下,特征缩放可以提高模型的性能。例如,在基于距离的模型(如 K 近邻算法)中,特征的尺度可以影响距离的计算。如果某些特征具有较大的尺度,那么它们可能会对距离的计算产生更大的影响,从而导致模型性能下降。通过特征缩放,可以确保所有特征对距离的计算影响相似,提高模型的性能。

三种不同的技术:

  1. 特征缩放,基本上是将每个特征除以用户选择的值,以使其范围介于 -1 和 1 之间
  2. 均值归一化 x i : = x i − μ i m a x − m i n x_i := \dfrac{x_i - \mu_i}{max - min} xi:=maxminxiμi
  3. Z 分数归一化

Z 分数归一化

经过 Z 分数归一化后,所有特征的均值将为 0,标准差为 1

要实现 Z 分数归一化,调整输入值如下所示的公式:

x j ( i ) = x j ( i ) − μ j σ j (4) x^{(i)}_j = \dfrac{x^{(i)}_j - \mu_j}{\sigma_j} \tag{4} xj(i)=σjxj(i)μj(4)

其中, j j j 是矩阵 X X X 中的一个特征或列

µ j µ_j µj 是特征 ( j ) (j) j所有值的均值

∗ σ j *\sigma_j σj 是特征 ( j ) (j) j的**标准差。***

μ j = 1 m ∑ i = 0 m − 1 x j ( i ) σ j 2 = 1 m ∑ i = 0 m − 1 ( x j ( i ) − μ j ) 2 \begin{align} \mu_j &= \frac{1}{m} \sum_{i=0}^{m-1} x^{(i)}_j \tag{5}\\ \sigma^2_j &= \frac{1}{m} \sum_{i=0}^{m-1} (x^{(i)}_j - \mu_j)^2 \tag{6} \end{align} μjσj2=m1i=0m1xj(i)=m1i=0m1(xj(i)μj)2(5)(6)

实现注意: 当对特征进行归一化时,重要的是存储用于归一化的值 - 均值标准差用于计算。在从模型中学习参数后,我们通常希望预测之前未见过的房屋价格。给定一个新的 x 值(客厅面积和卧室数量),我们必须首先使用之前从训练集中计算得到的均值和标准差来归一化 x。

实现

def zscore_normalize_features(X):# 计算每个特征的均值mu = np.mean(X, axis=0)                 # mu will have shape (n,)# 计算每个特征的标准差sigma  = np.std(X, axis=0)                  # sigma will have shape (n,)# 进行归一化操作X_norm = (X - mu) / sigma      return (X_norm, mu, sigma)#check our work
#from sklearn.preprocessing import scale
#scale(X_orig, axis=0, with_mean=True, with_std=True, copy=True)
  • 解释一下:scale(X_orig, axis=0, with_mean=True, with_std=True, copy=True)

    这段代码使用了 scikit-learn 中的 scale 函数,该函数用于对输入数据进行标准化处理。下面是对该函数的参数进行解释:

    • X_orig:要进行标准化处理的输入数据。通常是一个二维数组,其中每一行代表一个样本,每一列代表一个特征。
    • axis:标准化处理的轴向。默认值为 0,表示对每一列进行标准化处理,即计算每个特征的均值和标准差,并将数据标准化为均值为 0、标准差为 1 的分布。如果设置为 1,表示对每一行进行标准化处理。
    • with_mean:是否对数据进行均值归一化。默认值为 True,表示将数据减去均值,使得均值为 0。
    • with_std:是否对数据进行标准差归一化。默认值为 True,表示将数据除以标准差,使得标准差为 1。
    • copy:是否复制输入数据。默认值为 True,表示将原始数据进行复制,不修改原始数据。如果设置为 False,表示在原始数据上直接进行修改。

    综合起来,这段代码的作用是对输入数据进行标准化处理,使得每个特征的均值为 0,标准差为 1,以及可选择是否对数据进行均值归一化和标准差归一化。

下面的图显示了逐步的转换过程。

mu     = np.mean(X_train,axis=0)   
sigma  = np.std(X_train,axis=0) 
X_mean = (X_train - mu)
X_norm = (X_train - mu)/sigma      fig,ax=plt.subplots(1, 3, figsize=(12, 3))
ax[0].scatter(X_train[:,0], X_train[:,3])
ax[0].set_xlabel(X_features[0]); ax[0].set_ylabel(X_features[3]);
ax[0].set_title("unnormalized")
ax[0].axis('equal')ax[1].scatter(X_mean[:,0], X_mean[:,3])
ax[1].set_xlabel(X_features[0]); ax[0].set_ylabel(X_features[3]);
ax[1].set_title(r"X - $\mu$")
ax[1].axis('equal')ax[2].scatter(X_norm[:,0], X_norm[:,3])
ax[2].set_xlabel(X_features[0]); ax[0].set_ylabel(X_features[3]);
ax[2].set_title(r"Z-score normalized")
ax[2].axis('equal')
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
fig.suptitle("distribution of features before, during, after normalization")
plt.show()

在这里插入图片描述

上面的图显示了训练集中两个参数之间的关系,“age” 和 “sqft”。这些图绘制的比例相等

  • 左侧:未归一化:‘size(sqft)’ 特征的值范围或方差远大于 ‘age’ 特征的值范围或方差。
  • 中间:第一步去除了每个特征的平均值或均值。这使得特征围绕零中心。很难看出 ‘age’ 特征的差异,但 ‘size(sqft)’ 明显围绕零中心。
  • 右侧:第二步除以方差。这使得两个特征都围绕零中心,并且具有相似的尺度。

让我们对数据进行归一化,并将其与原始数据进行比较。

# normalize the original features
X_norm, X_mu, X_sigma = zscore_normalize_features(X_train)
print(f"X_mu = {X_mu}, \nX_sigma = {X_sigma}")
print(f"Peak to Peak range by column in Raw        X:{np.ptp(X_train,axis=0)}")   
print(f"Peak to Peak range by column in Normalized X:{np.ptp(X_norm,axis=0)}")

通过归一化,每列的峰值范围从数千的因子减少到 2-3 的因子。

fig,ax=plt.subplots(1, 4, figsize=(12, 3))# 对第 i 列的特征进行归一化,并绘图
for i in range(len(ax)):norm_plot(ax[i],X_train[:,i],)ax[i].set_xlabel(X_features[i])ax[0].set_ylabel("count");
fig.suptitle("distribution of features before normalization")
plt.show()

在这里插入图片描述

请注意,上面归一化后的数据范围围绕零中心,大致在 +/- 1 范围内。最重要的是,每个特征的范围相似。

让我们使用归一化后的数据重新运行梯度下降算法。请注意学习率 α \alpha α 的值大大增加了。这将加速下降过程。

w_norm, b_norm, hist = run_gradient_descent(X_norm, y_train, 1000, 1.0e-1, )

通过归一化后的特征,我们可以在更快的时间内获得非常准确的结果!请注意,在这个相当短的运行过程结束时,每个参数的梯度都变得非常小。对于使用归一化特征的回归问题,学习率 0.1 是一个很好的起点。

让我们绘制我们的预测值与目标值的对比图。请注意,预测是使用归一化后的特征进行的,而绘图是使用原始特征值进行的。

# 用归一化后的特征得到的预测值
m = X_norm.shape[0] # m 是数据量
yp = np.zeros(m) # yp 是预测的价格# 使用归一化后的特征 X_norm[i] 与归一化后的权重 w_norm 进行点乘,再加上归一化后的偏置 b_norm,得到预测的价格。
for i in range(m):yp[i] = np.dot(X_norm[i], w_norm) + b_norm# 将原始特征值与预测值绘制在同一图表中,用于对比    
fig,ax=plt.subplots(1,4,figsize=(12, 3),sharey=True)
for i in range(len(ax)):ax[i].scatter(X_train[:,i],y_train, label = 'target')ax[i].set_xlabel(X_features[i])ax[i].scatter(X_train[:,i],yp,color=dlorange, label = 'predict')
ax[0].set_ylabel("Price"); ax[0].legend();
fig.suptitle("target versus prediction using z-score normalized model")
plt.show()

在这里插入图片描述

结果看起来不错。需要注意几点:

  • 当使用多个特征时,我们不能再使用单个图表显示结果与特征的关系。
  • 在生成图表时,使用了归一化后的特征。任何使用从归一化训练集学习到的参数进行的预测都必须使用归一化的特征。

**预测:**生成我们的模型的目的是使用它来预测不在数据集中的房屋价格。让我们预测一间具有 1200 平方英尺、3 间卧室、1 层、40 年历史的房屋的价格。请记住,在使用模型进行预测之前,必须使用训练数据归一化时得到的均值和标准差对数据进行归一化处理。

# 首先,归一化需要预测的样本
x_house = np.array([1200, 3, 1, 40])
x_house_norm = (x_house - X_mu) / X_sigma
print(x_house_norm)
x_house_predict = np.dot(x_house_norm, w_norm) + b_norm
print(f" predicted price of a house with 1200 sqft, 3 bedrooms, 1 floor, 40 years old = ${x_house_predict*1000:0.0f}")

代价轮廓

另一种观察特征缩放的方式是通过代价轮廓。当特征的尺度不匹配时,在轮廓图中绘制的代价与参数之间的关系是不对称的。

在下面的图中,参数的尺度是匹配的。左图是在归一化特征之前对房屋面积 w[0] 与卧室数量 w[1] 的代价轮廓图。由于不对称,完成轮廓的曲线并不可见。相比之下,当特征归一化时,代价轮廓更加对称。结果是在梯度下降过程中,参数的更新可以使每个参数取得相同的进展。

plt_equal_scale(X_train, X_norm, y_train)

在这里插入图片描述

小结

  • 利用之前实验中开发的具有多个特征的线性回归例程
  • 探索学习率 α \alpha α 对收敛性的影响
  • 发现使用 Z 分数归一化进行特征缩放在加速收敛方面的价值

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/835843.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

完美撤离暗区突围测试资格获取指南 超简单的暗区突围资格申请

完美撤离!暗区突围测试资格获取指南 超简单的暗区突围资格申请! 最近游戏圈关注度最高的一件事莫过于暗区突围国际服的上线,随着暗区突围PC端的上线,这款游戏的测试资格申请成为了玩家们心头的一个大问题,许多玩家爱不…

Python 检查某个文件是否存在

在Python中,你可以使用os模块的path.exists()函数来检查一个文件是否存在。以下是一个简单的例子: import os # 文件路径 file_path /path/to/your/file.txt # 检查文件是否存在 if os.path.exists(file_path): print(f"文件 {file_path} …

[Kotlin]创建一个私有包并使用

1.创建Kotlin测试项目 在Android Studio或其他IDE中选择“Create New Project”。选择Kotlin和Gradle作为项目类型和构建系统。指定项目名称和位置,完成设置。 2.创建Android Library模块 官方文档:创建 Android 库 | Android Studio | Android De…

拼多多二面,原来是我对自动化测试的理解太浅了

如果你入职一家新的公司,领导让你开展自动化测试,作为一个新人,你肯定会手忙脚乱,你会如何落地自动化测试呢? 01 什么是自动化 有很多人做了很长时间的自动化但却连自动化的概念都不清楚,这样的人也是很悲…

Java面试题:AQS

AQS AbsractQueuedSynchronizer抽象队列同步器 构建锁或者其他同步组件的基础框架 Synchronized和AQS的区别 Synchronized由c实现,悲观锁,自动释放锁,竞争激烈时使用重量级锁,性能较差 AQS由java提供,悲观锁,手动开启关闭,在竞争激烈的情况下提供了多种解决的方案 AQS常见…

openai 开源模型Whisper语音转文本模型下载使用

Whisper Whisper 是一种通用语音识别模型。它是在大量不同音频数据集上进行训练的,也是一个多任务模型,可以执行多语言语音识别、语音翻译和语言识别。官方地址 https://github.com/openai/whisper 方法 一个Transformer序列到序列模型被训练在多种语音处理任务上,包括多语…

libcity笔记:

1 __init__ 2 encode 得到的内容如下: data_feature的内容: 一共有多少个location1【包括pad的一个】最长的时间间隔(秒)最长的距离间隔(千米)多少个useer idpadding 的locationidpad_item的内容 location…

AWVS安装Runtime Error at 107:1161

invalid or missing database information from settings.ini 这个是操作系统的环境引起的问题。 可以尝试的方法: 1、用CCleaner卸载或者删除之前安装的AWVS 工具——找到acunetix——卸载 2、清理注册表 查看: 修复: 3、删除其他文件 安装E…

开源基金会AtomGit教程

大家伙,我是雄雄,欢迎关注微信公众号:雄雄的小课堂。 注册 点击链接进入官网,先注册,然后登录:https://atomgit.com/ 编辑个人资料,修改一下自己的信息,用户名后面提交代码的时候要…

Canvas绘制图片和区域(前端使用Canvas绘制图片,并在图片上绘制区域)

简介&#xff1a;在Web开发中&#xff0c;有时候我们需要在图片上进行一些交互式操作&#xff0c;比如绘制区域、标记等。这种场景下&#xff0c;我们可以使用HTML5的<canvas>元素来实现。Canvas 是 HTML5 提供的一种图形绘制接口&#xff0c;可以通过 JavaScript 在网页…

Agisoft Metashape Pro for Mac/win:开启三维建模新视界

在当今数字化的时代&#xff0c;三维建模技术正发挥着越来越重要的作用。而 Agisoft Metashape Pro for Mac/win 无疑是该领域的一颗璀璨明星。 这款强大的三维建模软件为专业人士和爱好者提供了无与伦比的工具和功能。无论你是从事建筑设计、考古研究、影视特效制作还是地理信…

【Leetcode】55- 跳跃游戏

问题简述 给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#…

智能体Agent笔记

智能体的定义&#xff1a; 1. 可以感受环境中的动态条件 2. 能采取动作影响环境 3. 能运用推理能力理解信息&#xff0c;解决问题&#xff0c;产生推断&#xff0c;决定动作。 我个人觉得智能体是个饼&#xff0c;最核心的问题是&#xff0c;你如何解决大模型的幻觉问题&…

基于STM32的衣柜防潮系统设计的毕业论文

基于STM32的衣柜防潮系统设计的毕业论文 一、引言 随着生活品质的提升&#xff0c;人们对家居环境的舒适度要求越来越高。衣柜作为家居存储衣物的重要部分&#xff0c;其内部环境的湿度控制显得尤为重要。湿度过高可能导致衣物发霉、变质&#xff0c;严重影响衣物的使用寿命和…

[Android]常见的包管理方式

在Android开发中&#xff0c;包管理主要是通过构建和依赖管理工具来处理。下面列举了几种最常见和主流的包管理方式&#xff1a; 一、Gradle Gradle 是 Android 官方推荐的构建工具&#xff0c;几乎成为了 Android 开发的标准。它支持自定义构建逻辑、依赖管理、多项目构建等…

CMS垃圾回收器为什么被移除

CMS&#xff08;Concurrent Mark-Sweep&#xff09;垃圾回收器是Java虚拟机中一种以获取最短回收停顿时间为目标的收集器。CMS的主要特点是它允许垃圾回收线程与应用程序线程同时运行&#xff0c;尽可能减少应用程序的停顿时间。尽管它在多核处理器上表现良好&#xff0c;并且能…

笨方法自学python(三)-数学计算

数字和数学计算 这章练习里有很多的数学运算符号。我们来看一遍它们都叫什么名字 plus 加号-minus 减号/ slash 斜杠*asterisk 星号% percent 百分号< less-than 小于号greater-than 大于号< less-than-equal 小于等于号 greater-than-equal 大于等于号 print ("I …

JavaScript中,改变this的三种方法

在JavaScript中&#xff0c;this 关键字是一个特殊的变量&#xff0c;它在函数执行时确定了函数的上下文。通常&#xff0c;this 指向调用该函数的对象。但是&#xff0c;在某些情况下&#xff0c;我们可能需要改变 this 的指向。以下是三种常见的方法来改变 this 的指向&#…

优先队列全面讲解

主题&#xff1a; 优先队列是一种非常有用的数据结构&#xff0c;它让你能够管理一组数据&#xff0c;使得每次访问或移除数据时&#xff0c;总是得到当前集合中优先级最高&#xff08;或最低&#xff09;的那个元素。这个特性让优先队列非常适用于需要快速访问集合中最重要元…

20232906 2023-2024-2 《网络与系统攻防技术》第九次作业

20232906 2023-2024-2 《网络与系统攻防技术》第九次作业 1.实验内容 本次实践的对象是一个名为pwn1的linux可执行文件。 该程序正常执行流程是&#xff1a;main调用foo函数,foo函数会简单回显任何用户输入的字符串。 该程序同时包含另一个代码片段&#xff0c;getShell&am…