主頁 > 區塊鏈 > 自定義keras層的output_shape為None(或無法自動確定)

自定義keras層的output_shape為None(或無法自動確定)

2022-11-11 03:08:51 區塊鏈

我正在構建一個自定義 Keras 層,它本質上是帶有可訓練基本引數的 softmax 函式。雖然該層獨立作業,但當放置在順序模型中時,model.summary()將其輸出形狀確定為Nonemodel.fit()引發一個可能鏈接的例外:

ValueError: as_list() 未在未知的 TensorShape 上定義。

在其他自定義層(顯然包括來自 keras 的線性示例)中,可以在.build()呼叫之后確定輸出形狀。通過查看model.summary()的源代碼以及keras.layers.Layer,有這個@propertyLayer.output_shape無法自動確定輸出形狀。

然后我嘗試覆寫屬性并在保存后手動回傳input_shape傳遞給我的圖層.build()方法的引數(softmax 不會改變輸入的形狀),但這也不起作用:如果我呼叫super().output_shape before returning my value, model.summary()將形狀確定為?,而如果我不這樣做,則該值可能會顯示為看似正確,但在這兩種情況下,我都會在 .fit() 期間得到完全相同的錯誤。

代碼 iside call() 是否有什么特別之處會阻止 keras 理解輸出的形狀?
或者,是否有我遺漏的檔案?

我的層:

class B_Softmax(keras.layers.Layer):
    def __init__(self, b_init_mean=10, b_init_var=0.001):
        super(B_Softmax, self).__init__()
        self.b_init = tf.random_normal_initializer(b_init_mean, b_init_var)
        self._out_shape = None
        
    def build(self, input_shape):
        self.b = tf.Variable(
            initial_value = self.b_init(shape=(1,), dtype='float32'),
            trainable=True
        )
        self._out_shape = input_shape

    def call(self, inputs):
        # This is an implementation of Softmax for batched inputs
        # where the factor b is added to the exponents
        nominators  = tf.math.exp(self.b * inputs)
        denominator = tf.reduce_sum(nominators, axis=1)
        denominator = tf.squeeze(denominator)
        denominator = tf.expand_dims(denominator, -1)
        s           = tf.divide(nominators, denominator)
        return s

    @property
    def output_shape(self):    # If I comment out this function, summary prints 'None'
        self.output_shape      # If I leave this line, summary prints '?' 
        return self._out_shape # If the above line is commented out, summary prints '10' (correctly)
                               # but the same error is triggered in all three cases

該層獨立作業:

>>> A     = tf.constant([[1,2,3], [7,5,6]], dtype="float32")
>>> layer = B_Softmax(1.0)
>>> layer(A)
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[0.08991686, 0.24461554, 0.6654676 ],
       [0.6654677 , 0.08991687, 0.24461551]], dtype=float32)>

但是當我嘗試將它包含在模型中時,摘要看起來不正確:

input_dim = 5
model = keras.Sequential([
        Dense(32, activation='relu', input_shape=(input_dim,)),
        Dense(num_classes, activation="softmax"),
        B_Softmax(1.0)
])
model.summary()
Model: "sequential_1"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense_10 (Dense)            (None, 32)                192       
                                                                 
 dense_11 (Dense)            (None, 10)                330       
                                                                 
 b__softmax_18 (B_Softmax)   None  <-------------------1-------- "None", "?", or "10" (in a hacky way) may be printted           
                                                                 
=================================================================
Total params: 523
Trainable params: 523
Non-trainable params: 0

訓練失敗:

batch_size = 128
epochs = 15
model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])
model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_split=0.1)
ValueError: in user code:

    File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 1051, in train_function  *
        return step_function(self, iterator)
    File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 1040, in step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 1030, in run_step  **
        outputs = model.train_step(data)
    File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 894, in train_step
        return self.compute_metrics(x, y, y_pred, sample_weight)
    File "/usr/local/lib/python3.7/dist-packages/keras/engine/training.py", line 987, in compute_metrics
        self.compiled_metrics.update_state(y, y_pred, sample_weight)
    File "/usr/local/lib/python3.7/dist-packages/keras/engine/compile_utils.py", line 480, in update_state
        self.build(y_pred, y_true)
    File "/usr/local/lib/python3.7/dist-packages/keras/engine/compile_utils.py", line 398, in build
        y_pred)
    File "/usr/local/lib/python3.7/dist-packages/keras/engine/compile_utils.py", line 526, in _get_metric_objects
        return [self._get_metric_object(m, y_t, y_p) for m in metrics]
    File "/usr/local/lib/python3.7/dist-packages/keras/engine/compile_utils.py", line 526, in <listcomp>
        return [self._get_metric_object(m, y_t, y_p) for m in metrics]
    File "/usr/local/lib/python3.7/dist-packages/keras/engine/compile_utils.py", line 548, in _get_metric_object
        y_p_rank = len(y_p.shape.as_list())

    ValueError: as_list() is not defined on an unknown TensorShape.

uj5u.com熱心網友回復:

這并不能直接解決問題,而是回避它:我們不使用squeezeand expand_dims(前者似乎對 Tensorflow 的跟蹤有問題),而是keepdims=True在求和中使用以保持軸正確對齊 softmax 分母.

def call(self, inputs):
        # This is an implementation of Softmax for batched inputs
        # where the factor b is added to the exponents
        nominators  = tf.math.exp(self.b * inputs)
        denominator = tf.reduce_sum(nominators, axis=1, keepdims=True)
        s           = tf.divide(nominators, denominator)
        return s

可以說,最好使用內置的 softmax:

def call(self, inputs):
        return tf.nn.softmax(self.b * inputs)

uj5u.com熱心網友回復:

compute_output_shape您可以在 Layer 子類中實作該方法:

def compute_output_shape(self, input_shape):
    return [(None, out_shape)]

其中out_shape包含輸出的維度,或者您可以替換整個元組以具有您想要的任何輸出形狀。

uj5u.com熱心網友回復:

我發現代碼沒有問題,我認為輸入引數很重要,這樣做有一些注釋:

  1. 我使用資料集和 model.fit() 我也使用它而不使用拆分,因為我創建了一個帶有一條記錄的樣本。
  2. 模型輸入,我從 Input( 5, ) 修改為 Input ( 1, 5 ),它與資料集匹配創建了一個形狀(這就是我在摘要中添加選擇號 1 的原因)
  3. Categorize、BatchSize、Number of class、LossFN 和 Optimizers 通過 number_classes 引數根據網路的輸出維度進行調整。

示例:<< Loss FN 不決定模型,但 Input 和 Output 決定,不必說明它是如何創建的,洗掉了它不使用的內容或評論它>>

import tensorflow as tf

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Class / Definition
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
class B_Softmax(tf.keras.layers.Layer):
    def __init__(self, b_init_mean=10, b_init_var=0.001):
        super(B_Softmax, self).__init__()
        self.b_init = tf.random_normal_initializer(b_init_mean, b_init_var)
        self._out_shape = None
        
    def build(self, input_shape):
        self.b = tf.Variable(
            initial_value = self.b_init(shape=(1,), dtype='float32'),
            trainable=True
        )
        self._out_shape = input_shape

    def call(self, inputs):
        # This is an implementation of Softmax for batched inputs
        # where the factor b is added to the exponents
        nominators  = tf.math.exp(self.b * inputs)
        denominator = tf.reduce_sum(nominators, axis=1)
        denominator = tf.squeeze(denominator)
        denominator = tf.expand_dims(denominator, -1)
        s           = tf.divide(nominators, denominator)
        return s

    # @property
    # def output_shape(self):    # If I comment out this function, summary prints 'None'
        # self.output_shape      # If I leave this line, summary prints '?' 
        # return self._out_shape # If the above line is commented out, summary prints '10' (correctly)
    #                           but the same error is triggered in all three cases

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Variables
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""                              
A = tf.constant([[1,2,3], [7,5,6]], dtype="float32")

batch_size = 128
epochs = 15
input_dim = 5
num_classes = 1

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Dataset
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
start = 3
limit = 16
delta = 3
sample = tf.range( start, limit, delta )
sample = tf.cast( sample, dtype=tf.float32 )
sample = tf.constant( sample, shape=( 1, 1, 1, 5 ) )
dataset = tf.data.Dataset.from_tensor_slices(( sample, tf.constant( [0], shape=( 1, 1, 1, 1 ), dtype=tf.int64)))

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Model Initialize
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""   
layer = B_Softmax(1.0)
print( layer(A) )

model = tf.keras.Sequential([
        tf.keras.layers.Dense(32, activation='relu', input_shape=(1, input_dim)),
        tf.keras.layers.Dense(num_classes, activation="softmax"),
        B_Softmax(1.0)
])
model.summary()

model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Working
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""   
model.fit(dataset, batch_size=batch_size, epochs=epochs, validation_data=dataset)

輸出:

tf.Tensor(
[[0.09007736 0.24477491 0.6651477 ]
 [0.66514784 0.09007736 0.24477486]], shape=(2, 3), dtype=float32)
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #
=================================================================
 dense (Dense)               (None, 1, 32)             192

 dense_1 (Dense)             (None, 1, 1)              33

 b__softmax_1 (B_Softmax)    None                      1

=================================================================
Total params: 226
Trainable params: 226
Non-trainable params: 0
_________________________________________________________________
Epoch 1/15
1/1 [==============================] - 5s 5s/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 2/15
1/1 [==============================] - 0s 14ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 3/15
1/1 [==============================] - 0s 15ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 4/15
1/1 [==============================] - 0s 13ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 5/15
1/1 [==============================] - 0s 14ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 6/15
1/1 [==============================] - 0s 12ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 7/15
1/1 [==============================] - 0s 13ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 8/15
1/1 [==============================] - 0s 12ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 9/15
1/1 [==============================] - 0s 12ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 10/15
1/1 [==============================] - 0s 12ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 11/15
1/1 [==============================] - 0s 12ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 12/15
1/1 [==============================] - 0s 15ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 13/15
1/1 [==============================] - 0s 14ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 14/15
1/1 [==============================] - 0s 15ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00
Epoch 15/15
1/1 [==============================] - 0s 14ms/step - loss: 0.0000e 00 - accuracy: 0.0000e 00 - val_loss: 0.0000e 00 - val_accuracy: 0.0000e 00

C:\Python310>

轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/531233.html

標籤:Python张量流喀拉斯

上一篇:圖表已斷開:無法在“input_20”層獲取張量Tensor("input_20:0",shape=(?,25,2),dtype=float32)的值

下一篇:NaN來自tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES))

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • JAVA使用 web3j 進行token轉賬

    最近新學習了下區塊鏈這方面的知識,所學不多,給大家分享下。 # 1. 關于web3j web3j是一個高度模塊化,反應性,型別安全的Java和Android庫,用于與智能合約配合并與以太坊網路上的客戶端(節點)集成。 # 2. 準備作業 jdk版本1.8 引入maven <dependency> < ......

    uj5u.com 2020-09-10 03:03:06 more
  • 以太坊智能合約開發框架Truffle

    前言 部署智能合約有多種方式,命令列的瀏覽器的渠道都有,但往往跟我們程式員的風格不太相符,因為我們習慣了在IDE里寫了代碼然后打包運行看效果。 雖然現在IDE中已經存在了Solidity插件,可以撰寫智能合約,但是部署智能合約卻要另走他路,沒辦法進行一個快捷的部署與測驗。 如果團隊管理的區塊節點多、 ......

    uj5u.com 2020-09-10 03:03:12 more
  • 谷歌二次驗證碼成為區塊鏈專用安全碼,你怎么看?

    前言 谷歌身份驗證器,前些年大家都比較陌生,但隨著國內互聯網安全的加強,它越來越多地出現在大家的視野中。 比較廣泛接觸的人群是國際3A游戲愛好者,游戲盜號現象嚴重+國外賬號安全應用廣泛,這類游戲一般都會要求用戶系結名為“兩步驗證”、“雙重驗證”等,平臺一般都推薦用谷歌身份驗證器。 后來區塊鏈業務風靡 ......

    uj5u.com 2020-09-10 03:03:17 more
  • 密碼學DAY1

    目錄 ##1.1 密碼學基本概念 密碼在我們的生活中有著重要的作用,那么密碼究竟來自何方,為何會產生呢? 密碼學是網路安全、資訊安全、區塊鏈等產品的基礎,常見的非對稱加密、對稱加密、散列函式等,都屬于密碼學范疇。 密碼學有數千年的歷史,從最開始的替換法到如今的非對稱加密演算法,經歷了古典密碼學,近代密 ......

    uj5u.com 2020-09-10 03:03:50 more
  • 密碼學DAY1_02

    目錄 ##1.1 ASCII編碼 ASCII(American Standard Code for Information Interchange,美國資訊交換標準代碼)是基于拉丁字母的一套電腦編碼系統,主要用于顯示現代英語和其他西歐語言。它是現今最通用的單位元組編碼系統,并等同于國際標準ISO/IE ......

    uj5u.com 2020-09-10 03:04:50 more
  • 密碼學DAY2

    ##1.1 加密模式 加密模式:https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html ECB ECB : Electronic codebook, 電子密碼本. 需要加密的訊息按照塊密碼的塊大小被分為數個塊,并對每個塊進 ......

    uj5u.com 2020-09-10 03:05:42 more
  • NTP時鐘服務器的特點(京準電子)

    NTP時鐘服務器的特點(京準電子) NTP時鐘服務器的特點(京準電子) 京準電子官V——ahjzsz 首先對時間同步進行了背景介紹,然后討論了不同的時間同步網路技術,最后指出了建立全球或區域時間同步網存在的問題。 一、概 述 在通信領域,“同步”概念是指頻率的同步,即網路各個節點的時鐘頻率和相位同步 ......

    uj5u.com 2020-09-10 03:05:47 more
  • 標準化考場時鐘同步系統推進智能化校園建設

    標準化考場時鐘同步系統推進智能化校園建設 標準化考場時鐘同步系統推進智能化校園建設 安徽京準電子科技官微——ahjzsz 一、背景概述隨著教育事業的快速發展,學校建設如雨后春筍,隨之而來的學校教育、管理、安全方面的問題成了學校管理人員面臨的最大的挑戰,這些問題同時也是學生家長所擔心的。為了讓學生有更 ......

    uj5u.com 2020-09-10 03:05:51 more
  • 位元幣入門

    引言 位元幣基本結構 位元幣基礎知識 1)哈希演算法 2)非對稱加密技術 3)數字簽名 4)MerkleTree 5)哪有位元幣,有的是UTXO 6)位元幣挖礦與共識 7)區塊驗證(共識) 總結 引言 上一篇我們已經知道了什么是區塊鏈,此篇說一下區塊鏈的第一個應用——位元幣。其實先有位元幣,后有的區塊 ......

    uj5u.com 2020-09-10 03:06:15 more
  • 北斗對時服務器(北斗對時設備)電力系統應用

    北斗對時服務器(北斗對時設備)電力系統應用 北斗對時服務器(北斗對時設備)電力系統應用 京準電子科技官微(ahjzsz) 中國北斗衛星導航系統(英文名稱:BeiDou Navigation Satellite System,簡稱BDS),因為是目前世界范圍內唯一可以大面積提供免費定位服務的系統,所以 ......

    uj5u.com 2020-09-10 03:06:20 more
最新发布
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:46:47 more
  • Hyperledger Fabric 使用 CouchDB 和復雜智能合約開發

    在上個實驗中,我們已經實作了簡單智能合約實作及客戶端開發,但該實驗中智能合約只有基礎的增刪改查功能,且其中的資料管理功能與傳統 MySQL 比相差甚遠。本文將在前面實驗的基礎上,將 Hyperledger Fabric 的默認資料庫支持 LevelDB 改為 CouchDB 模式,以實作更復雜的資料... ......

    uj5u.com 2023-04-16 07:28:31 more
  • .NET Core 波場鏈離線簽名、廣播交易(發送 TRX和USDT)筆記

    Get Started NuGet You can run the following command to install the Tron.Wallet.Net in your project. PM> Install-Package Tron.Wallet.Net 配置 public reco ......

    uj5u.com 2023-04-14 08:08:00 more
  • DKP 黑客分析——不正確的代幣對比率計算

    概述: 2023 年 2 月 8 日,針對 DKP 協議的閃電貸攻擊導致該協議的用戶損失了 8 萬美元,因為 execute() 函式取決于 USDT-DKP 對中兩種代幣的余額比率。 智能合約黑客概述: 攻擊者的交易:0x0c850f,0x2d31 攻擊者地址:0xF38 利用合同:0xf34ad ......

    uj5u.com 2023-04-07 07:46:09 more
  • Defi開發簡介

    Defi開發簡介 介紹 Defi是去中心化金融的縮寫, 是一項旨在利用區塊鏈技術和智能合約創建更加開放,可訪問和透明的金融體系的運動. 這與傳統金融形成鮮明對比,傳統金融通常由少數大型銀行和金融機構控制 在Defi的世界里,用戶可以直接從他們的電腦或移動設備上訪問廣泛的金融服務,而不需要像銀行或者信 ......

    uj5u.com 2023-04-05 08:01:34 more
  • solidity簡單的ERC20代幣實作

    // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; import "hardhat/console.sol"; //ERC20 同質化代幣,每個代幣的本質或性質都是相同 //ETH 是原生代幣,它不是ERC20代幣, ......

    uj5u.com 2023-03-21 07:56:29 more
  • solidity 參考型別修飾符memory、calldata與storage 常量修飾符C

    在solidity語言中 參考型別修飾符(參考型別為存盤空間不固定的數值型別) memory、calldata與storage,它們只能修飾參考型別變數,比如字串、陣列、位元組等... memory 適用于方法傳參、返參或在方法體內使用,使用完就會清除掉,釋放記憶體 calldata 僅適用于方法傳參 ......

    uj5u.com 2023-03-08 07:57:54 more
  • solidity注解標簽

    在solidity語言中 注釋符為// 注解符為/* 內容*/ 或者 是 ///內容 注解中含有這幾個標簽給予我們使用 @title 一個應該描述合約/介面的標題 contract, library, interface @author 作者的名字 contract, library, interf ......

    uj5u.com 2023-03-08 07:57:49 more
  • 評價指標:相似度、GAS消耗

    【代碼注釋自動生成方法綜述】 這些評測指標主要來自機器翻譯和文本總結等研究領域,可以評估候選文本(即基于代碼注釋自動方法而生成)和參考文本(即基于手工方式而生成)的相似度. BLEU指標^[^?88^^?^]^:其全稱是bilingual evaluation understudy.該指標是最早用于 ......

    uj5u.com 2023-02-23 07:27:39 more
  • 基于NOSTR協議的“公有制”版本的Twitter,去中心化社交軟體Damus

    最近,一個幽靈,Web3的幽靈,在網路游蕩,它叫Damus,這玩意詮釋了什么叫做病毒式營銷,滑稽的是,一個Web3產品卻在Web2的產品鏈上瘋狂傳銷,各方大佬紛紛為其背書,到底發生了什么?Damus的葫蘆里,賣的是什么藥? 注冊和簡單實用 很少有什么產品在用戶注冊環節會有什么噱頭,但Damus確實出 ......

    uj5u.com 2023-02-05 06:48:39 more