1005.E. Maximize Sum Of Array After K Negations

该博客讨论了LeetCode问题1005,内容涉及如何在进行K次元素取负操作后最大化数组的和。作者提出了两种策略:当K小于等于负数的数量时,翻转最小的K个负数;当K大于负数的数量时,考虑K与负数数量之差的奇偶性来决定操作。文章提供了C++和Python的实现,并表达了对LeetCode题目数量增长的感慨。

一个数组每次选一个*(-1),K次后求最大sum。

desc

思路:

1. 维护最小堆,either in place or not.

2. 细分析负数数量和K奇偶.

  • K<=#负数:翻转最小的K个负数
  • K>#负数:翻转所有负数
    • (K-#负数)为偶,res=sum
    • (K-#负数)为奇,res=sum-min*2

C++

heap

class Solution {
public:
    int largestSumAfterKNegations(vector<int>& A, int K) {
        multiset<int> s;
        int res = 0;
        
        for (auto x: A) {
            s.insert(x);
            res += x;
        }
        while(K--) {
            int tmp = *s.begin();
            s.erase(s.begin());
            s.insert(tmp * -1);
            res = res - tmp*2;
        }
        return res;
    }
};
class Solution {
public:
    int largestSumAfterKNegations(vector<int>& A, int K) {
        int res = 0;
        int cnt = 0;
        sort(A.begin(), A.end());
        int min_v;
        
        for (int i=0; i<A.size(); i++) {
            if (A[i]<0 && cnt++<K) 
                A[i] = -A[i];
            min_v = min(min_v, A[i]);
            res += A[i];
        }
        if ((cnt > K) || (K-cnt)%2 == 0)
            return res;
        return res - 2 * min_v;
    }
};

Python

class Solution(object):
    def largestSumAfterKNegations(self, A, K):
        """
        :type A: List[int]
        :type K: int
        :rtype: int
        """
        s = sum(A)
        heapq.heapify(A)
        while K > 0:
            min_v = heapq.heappop(A)
            heapq.heappush(A, -min_v)
            K = K-1
            s += -2*min_v
        return s
class Solution(object):
    def largestSumAfterKNegations(self, A, K):
        for _ in range(K):
            A.sort()
            A[0]=-A[0]
        return sum(A)
class Solution(object):
    def largestSumAfterKNegations(self, A, K):
        A.sort()
        i = 0
        while i<len(A) and i<K and A[i]<0:
            A[i] = -A[i]
            i += 1
        if (K-i) % 2:
            return sum(A)-min(A)*2
        return sum(A)

 

碎碎念:

遥想第一次刷lc的时候才只有一百多题啊一百多,今天打开看着标号1500+...真的是一脸懵逼+绝望...

<think>嗯,用户这聚焦在torch.optim.AdamW的maximize参数上,看来是在深度学习调优时遇到了方向性问题。从用户引用资料看,ta已经查阅了PyTorch官方文档(引用[1][2]),甚至注意到Adam和AdamW的参数一致性,说明有扎实的基础。不过ta特意强调AdamW,可能正在处理权重衰减敏感的任务(如Transformer微调)。 用户的核心困惑在于:为什么优化器需要显式指定最大化?这其实涉及优化算法的对称性问题。常规梯度下降默认最小化,但像强化学习的奖励最大化、某些损失函数设计(如-ACC)等场景需要反向操作。AdamW作为Adam的改进变体,其maximize参数正是为这类场景设计。 值得深入解释的是实现机制:当maximize=True时,优化器在内部对梯度取反,相当于执行梯度上升。但要注意其数学等价性:设目标函数为$f(\theta)$,则最大化问题可转化为最小化$g(\theta) = -f(\theta)$。优化器自动完成这个转换,避免用户手动修改损失函数。 结合用户引用的代码片段(引用[3]),可以推测ta可能在训练循环中遇到了验证指标优化的需求。比如在Early Stopping时监控准确率而非损失值,此时设置maximize=True就能直接优化准确率指标。不过需要提醒:分类任务通常仍建议最小化交叉熵,因为准确率不可导。 用户可能忽略的细节是:maximize参数与weight_decay的交互。当同时启用时,权重衰减仍作用于原始参数而非取反后的梯度。这在最大化物理约束的目标函数(如能量效率)时可能引发问题,需要额外处理约束条件。 最后注意到用户引用了SGD(引用[4]),或许在对比不同优化器特性。可以强调AdamW的maximize与SGD的同类参数行为一致,但AdamW的自适应学习率使其在非凸优化中更鲁棒。</think>在 PyTorch 的 `torch.optim.AdamW` 优化器中,`maximize` 参数的作用是**控制优化方向**,其核心功能如下: ### 1. **参数定义** ```python torch.optim.AdamW(..., maximize: bool = False, ...) ``` - **默认值**: `False`(最小化目标函数) - **作用**: 决定优化器是寻找目标函数的最小值还是最大值 ### 2. **数学原理** 设目标函数为 $f(\theta)$,参数为 $\theta$,梯度为 $g_t = \nabla f(\theta_t)$: - 当 `maximize=False` (默认) 时: $$ \theta_{t+1} = \theta_t - \eta \cdot m_t / (\sqrt{v_t} + \epsilon) $$ 执行梯度下降,寻找 $f(\theta)$ 的最小值[^1][^2]。 - 当 `maximize=True` 时: $$ \theta_{t+1} = \theta_t + \eta \cdot m_t / (\sqrt{v_t} + \epsilon) $$ 等价于优化 $-f(\theta)$,执行梯度上升,寻找 $f(\theta)$ 的最大值[^2]。 ### 3. **应用场景** | 场景 | `maximize=False` (默认) | `maximize=True` | |---------------------|-------------------------------|-----------------------------| | **典型任务** | 最小化损失函数 (如交叉熵损失) | 最大化奖励/指标 (如准确率) | | **反向传播梯度方向**| 负梯度方向更新参数 | 正梯度方向更新参数 | | **示例领域** | 分类/回归任务 | 强化学习策略优化、某些自定义指标优化 | ### 4. **使用示例 ```python import torch import torch.nn as nn model = nn.Linear(10, 1) optimizer = torch.optim.AdamW( model.parameters(), lr=0.01, maximize=True # 最大化目标函数 ) # 训练循环中需计算需最大化的目标值(如准确率) for data, target in dataloader: output = model(data) reward = calculate_reward(output, target) # 需最大化的指标 optimizer.zero_grad() (-reward).backward() # 通过负号转换为最小化问题 optimizer.step() ``` > **关键说明**:当 `maximize=True` 时,反向传播需计算 `-reward.backward()`,因为优化器内部已对梯度取反[^2]。 ### 5. **与手动转换的等价性** 以下两种方式等价: ```python # 方式1:显式使用 maximize=True optimizer = AdamW(params, maximize=True) loss = -reward # 需最大化的目标取负 loss.backward() # 方式2:手动梯度取反 optimizer = AdamW(params, maximize=False) reward.backward() # 直接对目标反向传播 ``` ### 注意事项 1. **权重衰减独立性**:`weight_decay` 参数的行为不受 `maximize` 影响,始终应用 L2 正则化[^2][^4] 2. **与其他参数交互**:`betas`, `eps` 等参数在两种模式下计算规则一致 3. **梯度裁剪**:若使用梯度裁剪,需注意 `maximize=True` 时梯度方向已反转
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值