编号50. pow(x,n)

本文详细解析了LeetCode第50题pow(x,n)的快速幂算法实现,通过示例展示了如何高效计算x的n次幂,特别是针对大整数的指数运算,提出了一种折半思想的优化方案,避免了传统循环计算的高复杂度问题。

LeetCode50. pow(x,n)

题目描述:实现 pow(x, n) ,即计算 x 的 n 次幂函数。
示例 1:
输入: 2.00000, 10
输出: 1024.00000
示例 2:
输入: 2.10000, 3
输出: 9.26100
示例 3:
输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25
说明:
-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [ − 2 31 , 2 31 − 1 ] [−2^{31}, 2^{31 − 1}] [231,2311]
初步思路:判断n的正负号,如果为0,则为1;如果为负,则x为1/x;如果为正,则x不变。

class Solution {
    public double myPow(double x, int n) {
        if(n==0)
            return 1.00000;   
        if(n<0)
        {
            x = 1.0/x;
            n = -n;
        }
        double ret = x;
        for(int i=0;i<n-1;i++)
            {
                ret = ret*x;
            }
             return ret;                 
    }
}

此解法复杂度过高,当n取最大值当时候会超时;
改进:因此运用折半的思想,每折半一次,作为底数的x都会变为原来的平方,并且还要考虑折半为奇数的情况,当为奇数时,需要额外乘x

class Solution {
    public double myPow(double x, int n) {
        if(n==0)
            return 1.00000;   
        if(n<0)
        {
            x = 1.0/x;
            n = -n;
        }
        double ret = 1.0;
        for(int i=n;i!=0;i/=2)
            {
                if(i%2 !=0)
                    ret = ret*x;
                x = x*x;
            }
        return ret;
class RDL(nn.Module): """ Args: num_classes (int): number of classes. feat_dim (int): feature dimension. """ def __init__(self, num_classes=10, feat_dim=3, knearest=4, use_gpu=True,output_device = 0,learnable=True): super(RDL, self).__init__() self.num_classes = num_classes self.feat_dim = feat_dim self.use_gpu = use_gpu self.knearest = knearest self.output_device=output_device # if self.use_gpu: # self.centers = nn.Parameter(torch.randn(self.num_classes, self.feat_dim).cuda()) # else: # self.centers = nn.Parameter(torch.randn(self.num_classes, self.feat_dim)) if learnable==True: if self.use_gpu: self.centers = nn.Parameter(torch.randn(self.num_classes, self.feat_dim).cuda(output_device)) else: self.centers = nn.Parameter(torch.randn(self.num_classes, self.feat_dim)) else: if self.use_gpu: self.centers = torch.autograd.Variable(torch.randn(self.num_classes, self.feat_dim).cuda(output_device),requires_grad=False) else: self.centers =torch.autograd.Variable(torch.randn(self.num_classes, self.feat_dim),requires_grad=False) def forward(self, x, labels, epoch=0): """ Args: x: feature matrix with shape (batch_size, feat_dim). labels: ground truth labels with shape (batch_size). """ batch_size = x.size(0) # n * 10 # print(torch.norm(x,dim=1)) #print("label", labels.size()) cur_centers = self.centers[labels] #print("cur_centers", cur_centers.size()) X_c = torch.sqrt(torch.pow(cur_centers, 2).sum(dim = 1)).cuda(self.output_device) # C_2 = torch.sqrt(torch.pow(self.centers, 2).sum(dim = 1)).cuda(self.output_device) # C x_2 = torch.sqrt(torch.pow(x, 2).sum(dim = 1).cuda(self.output_device)) # N x_2L = torch.mul(x_2, torch.pow(X_c, -1)) C_2 = torch.pow(X_c, -1) C_2 = torch.diag(C_2) x_2 = torch.pow(x_2, -1) x_2 = torch.diag(x_2) x = torch.mm(x.t(), x_2).t() #n * d C = torch.mm(cur_centers.t(), C_2).t() # n * d dist = torch.mm(x, C.t()) dist = 1 - dist # classes = torch.arange(self.num_classes).long() # if self.use_gpu: classes = classes.cuda() # labels = labels.unsqueeze(1).expand(batch_size, self.num_classes) # mask = labels.eq(classes.expand(batch_size, self.num_classes)) # dist = dist * mask.float() dist = torch.mul(dist, dist) dist_in = torch.diag(dist) dist_out = dist - dist_in dist_in = torch.mul(dist_in, dist_in) dist_out=torch.mul(dist_out,dist_out) lossA_in = dist_in.clamp(min=1e-12, max=1e+12).sum() / batch_size lossA_out = dist_out.clamp(min=1e-12, max=1e+12).sum() / (batch_size * (batch_size - 1)) #print(x) # print("size", x.size(), x_2.size()) # print(torch.mul(x_2, torch.pow(X_c, -1)).size()) dist_L = torch.pow(1 - x_2L, 2) lossL = dist_L.clamp(min=1e-12, max=1e+12).sum() / batch_size # loss=lossA_in - lossA_out + lossL*0.01 loss = lossA_in- lossA_out*0.01+lossL*0.01 # torch.save(self.centers, './test_center.pt') # exit(0) # print(torch.norm(self.centers,dim=1)) return loss
09-29
帮我检查一下有错误嘛class WeightQuantizer(torch.nn.Module): '''From GPTQ Repo''' def __init__(self, shape=1): super(WeightQuantizer, self).__init__() self.register_buffer('maxq', torch.tensor(0)) self.register_buffer('scale', torch.zeros(shape)) self.register_buffer('zero', torch.zeros(shape)) self.enable = True def configure( self, bits, perchannel=False, sym=True, mse=False, norm=2.4, grid=100, maxshrink=.8, outlier_threshold=None # 异常值阈值 ): self.bits = bits self.perchannel = perchannel self.sym = sym # self.mse = mse self.mse = False self.norm = norm self.grid = grid self.maxshrink = maxshrink self.outlier_threshold = outlier_threshold # 判断是否是异常通道的阈值 if sym: self.maxq = torch.tensor(2**(bits-1)-1) else: self.maxq = torch.tensor(2**bits - 1) def detect_outliers_by_threshold(self, channel_weights): # 根据阈值判断该通道是否是异常通道 if self.outlier_threshold is None: return False return (torch.abs(channel_weights) >= self.outlier_threshold).any().item() # 有没有异常值 def find_params(self, x): if self.bits == 16 or (not self.enable): return dev = x.device self.maxq = self.maxq.to(dev) shape = x.shape if self.perchannel: x = x.flatten(1) else: x = x.flatten().unsqueeze(0) # tmp = torch.zeros(x.shape[0], device=dev) # xmin = torch.minimum(x.min(1)[0], tmp) # xmax = torch.maximum(x.max(1)[0], tmp) n_channels = x.shape[0] # 通道数 self.scale = torch.zeros(n_channels, device=dev) self.zero = torch.zeros(n_channels, device=dev) self.maxq = torch.zeros(n_channels, dtype=torch.int32, device=dev) for i in range(n_channels): xi = x[i].unsqueeze(0) # 判断是否是异常通道 is_outlier = self.detect_outliers_by_threshold(xi) bits = 8 if is_outlier else self.bits maxq = 2**(bits - 1) - 1 if self.sym else 2**bits - 1 self.maxq[i] = maxq # 计算量化参数 xmin = torch.minimum(xi.min(1)[0], torch.zeros(1, device=dev)) xmax = torch.maximum(xi.max(1)[0], torch.zeros(1, device=dev)) if self.sym: xmax = torch.maximum(torch.abs(xmin), xmax).clamp(min=1e-5) scale = xmax / maxq zero = torch.zeros_like(scale) else: tmp = (xmin == 0) & (xmax == 0) xmin[tmp] = -1 xmax[tmp] = +1 scale = (xmax - xmin).clamp(min=1e-5) / maxq zero = torch.round(-xmin / scale) # # 量化参数 # if self.sym: # xmax = torch.maximum(torch.abs(xmin), xmax).clamp(min=1e-5) # self.scale = xmax / self.maxq # self.zero = torch.zeros_like(self.scale) # else: # tmp = (xmin == 0) & (xmax == 0) # xmin[tmp] = -1 # xmax[tmp] = +1 # self.scale = (xmax - xmin).clamp(min=1e-5) / self.maxq # self.zero = torch.round(-xmin / self.scale) if self.mse: best = torch.full([x.shape[0]], float('inf'), device=dev) for i in range(int(self.maxshrink * self.grid)): #### p = 1 - i / self.grid xmin1 = p * xmin xmax1 = p * xmax if self.sym: scale1 = xmax1 / self.maxq zero1 = torch.zeros_like(scale1) q = sym_quant_dequant(x, scale1.unsqueeze(1), self.maxq) else: scale1 = (xmax1 - xmin1) / self.maxq zero1 = torch.round(-xmin1 / scale1) q = asym_quant_dequant(x, scale1.unsqueeze(1), zero1.unsqueeze(1), self.maxq) q -= x q.abs_() q.pow_(self.norm) err = torch.sum(q, 1) tmp = err < best if torch.any(tmp): best[tmp] = err[tmp] self.scale[tmp] = scale1[tmp] self.zero[tmp] = zero1[tmp] self.scale[i] = scale self.zero[i] = zero # -------------------------------------------------------------------------------------------------- if not self.perchannel: tmp = shape[0] self.scale = self.scale.repeat(tmp) self.zero = self.zero.repeat(tmp) self.maxq = self.maxq.repeat(tmp) shape = [-1] + [1] * (len(shape) - 1) self.scale = self.scale.reshape(shape) self.zero = self.zero.reshape(shape) self.maxq = self.maxq.reshape(shape).int() return def quantize(self, x): x_dtype = x.dtype if self.enable and self.ready() and self.bits < 16: if self.sym: return sym_quant_dequant(x, self.scale, self.maxq).to(x_dtype) return asym_quant_dequant(x, self.scale, self.zero, self.maxq).to(x_dtype) return x
08-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值